Skip to content

Commit

Permalink
feat(notification): adjust create notification endpoint (#906)
Browse files Browse the repository at this point in the history
Refs: #812
Reviewed-By: Norbert Truchsess <[email protected]>
  • Loading branch information
Phil91 authored Aug 14, 2024
1 parent de22921 commit 0823e2d
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
namespace Org.Eclipse.TractusX.Portal.Backend.Notifications.Service.BusinessLogic;

/// <inheritdoc />
public class NotificationBusinessLogic : INotificationBusinessLogic
public class NotificationBusinessLogic(
IPortalRepositories portalRepositories,
IIdentityService identityService,
IOptions<NotificationSettings> options) : INotificationBusinessLogic
{
private static readonly IEnumerable<NotificationTypeId> ValidNotificationTypes =
[
Expand All @@ -40,32 +43,18 @@ public class NotificationBusinessLogic : INotificationBusinessLogic
NotificationTypeId.CREDENTIAL_EXPIRY
];

private readonly IPortalRepositories _portalRepositories;
private readonly IIdentityData _identityData;
private readonly NotificationSettings _settings;

/// <summary>
/// Creates a new instance of <see cref="NotificationBusinessLogic" />
/// </summary>
/// <param name="portalRepositories">Access to the repository factory.</param>
/// <param name="identityService">Access to the identity</param>
/// <param name="settings">Access to the notifications options</param>
public NotificationBusinessLogic(IPortalRepositories portalRepositories, IIdentityService identityService, IOptions<NotificationSettings> settings)
{
_portalRepositories = portalRepositories;
_identityData = identityService.IdentityData;
_settings = settings.Value;
}
private readonly NotificationSettings _settings = options.Value;
private readonly IIdentityData _identityData = identityService.IdentityData;

/// <inheritdoc />
public Task<Pagination.Response<NotificationDetailData>> GetNotificationsAsync(int page, int size, NotificationFilters filters, SearchSemanticTypeId semantic) =>
Pagination.CreateResponseAsync(page, size, _settings.MaxPageSize, _portalRepositories.GetInstance<INotificationRepository>()
Pagination.CreateResponseAsync(page, size, _settings.MaxPageSize, portalRepositories.GetInstance<INotificationRepository>()
.GetAllNotificationDetailsByReceiver(_identityData.IdentityId, semantic, filters.IsRead, filters.TypeId, filters.TopicId, filters.OnlyDueDate, filters.Sorting ?? NotificationSorting.DateDesc, filters.DoneState, filters.SearchTypeIds, filters.SearchQuery));

/// <inheritdoc />
public async Task<NotificationDetailData> GetNotificationDetailDataAsync(Guid notificationId)
{
var result = await _portalRepositories.GetInstance<INotificationRepository>().GetNotificationByIdAndValidateReceiverAsync(notificationId, _identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
var result = await portalRepositories.GetInstance<INotificationRepository>().GetNotificationByIdAndValidateReceiverAsync(notificationId, _identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
if (result == default)
{
throw NotFoundException.Create(NotificationErrors.NOTIFICATION_NOT_FOUND, [new("notificationId", notificationId.ToString())]);
Expand All @@ -81,12 +70,12 @@ public async Task<NotificationDetailData> GetNotificationDetailDataAsync(Guid no

/// <inheritdoc />
public Task<int> GetNotificationCountAsync(bool? isRead) =>
_portalRepositories.GetInstance<INotificationRepository>().GetNotificationCountForUserAsync(_identityData.IdentityId, isRead);
portalRepositories.GetInstance<INotificationRepository>().GetNotificationCountForUserAsync(_identityData.IdentityId, isRead);

/// <inheritdoc />
public async Task<NotificationCountDetails> GetNotificationCountDetailsAsync()
{
var details = await _portalRepositories.GetInstance<INotificationRepository>().GetCountDetailsForUserAsync(_identityData.IdentityId).ToListAsync().ConfigureAwait(false);
var details = await portalRepositories.GetInstance<INotificationRepository>().GetCountDetailsForUserAsync(_identityData.IdentityId).ToListAsync().ConfigureAwait(false);
var unreadNotifications = details.Where(x => !x.IsRead);
return new NotificationCountDetails(
details.Where(x => x.IsRead).Sum(x => x.Count),
Expand All @@ -102,7 +91,7 @@ public async Task SetNotificationStatusAsync(Guid notificationId, bool isRead)
{
var isReadFlag = await CheckNotificationExistsAndValidateReceiver(notificationId).ConfigureAwait(ConfigureAwaitOptions.None);

_portalRepositories.GetInstance<INotificationRepository>().AttachAndModifyNotification(notificationId, notification =>
portalRepositories.GetInstance<INotificationRepository>().AttachAndModifyNotification(notificationId, notification =>
{
notification.IsRead = isReadFlag;
},
Expand All @@ -111,20 +100,21 @@ public async Task SetNotificationStatusAsync(Guid notificationId, bool isRead)
notification.IsRead = isRead;
});

await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}

/// <inheritdoc />
public async Task DeleteNotificationAsync(Guid notificationId)
{
await CheckNotificationExistsAndValidateReceiver(notificationId).ConfigureAwait(ConfigureAwaitOptions.None);

_portalRepositories.GetInstance<INotificationRepository>().DeleteNotification(notificationId);
await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
portalRepositories.GetInstance<INotificationRepository>().DeleteNotification(notificationId);
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}

private async Task<bool> CheckNotificationExistsAndValidateReceiver(Guid notificationId)
{
var result = await _portalRepositories.GetInstance<INotificationRepository>().CheckNotificationExistsByIdAndValidateReceiverAsync(notificationId, _identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
var result = await portalRepositories.GetInstance<INotificationRepository>().CheckNotificationExistsByIdAndValidateReceiverAsync(notificationId, _identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
if (result == default || !result.IsNotificationExisting)
{
throw NotFoundException.Create(NotificationErrors.NOTIFICATION_NOT_FOUND, [new("notificationId", notificationId.ToString())]);
Expand All @@ -146,17 +136,17 @@ public async Task CreateNotification(NotificationRequest data)
throw ConflictException.Create(NotificationErrors.INVALID_NOTIFICATION_TYPE, [new("notificationTypeId", data.NotificationTypeId.ToString())]);
}

var userExists = await _portalRepositories.GetInstance<IUserRepository>().CheckUserExists(data.Requester).ConfigureAwait(ConfigureAwaitOptions.None);
var userExists = await portalRepositories.GetInstance<IUserRepository>().CheckUserExists(data.Receiver).ConfigureAwait(ConfigureAwaitOptions.None);
if (!userExists)
{
throw NotFoundException.Create(NotificationErrors.USER_NOT_FOUND, [new("userId", data.Requester.ToString())]);
throw NotFoundException.Create(NotificationErrors.USER_NOT_FOUND, [new("userId", data.Receiver.ToString())]);
}

_portalRepositories.GetInstance<INotificationRepository>().CreateNotification(data.Requester, data.NotificationTypeId, false, n =>
portalRepositories.GetInstance<INotificationRepository>().CreateNotification(data.Receiver, data.NotificationTypeId, false, n =>
{
n.CreatorUserId = _identityData.IdentityId;
n.Content = data.Content;
});
await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,9 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Notifications.Service.Controllers;
[EnvironmentRoute("MVC_ROUTING_BASEPATH")]
[Consumes("application/json")]
[Produces("application/json")]
public class NotificationController : ControllerBase
public class NotificationController(INotificationBusinessLogic logic)
: ControllerBase
{
private readonly INotificationBusinessLogic _logic;

/// <summary>
/// Creates a new instance of <see cref="NotificationController" />
/// </summary>
/// <param name="logic">The business logic for the notifications</param>
public NotificationController(INotificationBusinessLogic logic)
{
_logic = logic;
}

/// <summary>
/// Gets all notifications for the logged in user
/// </summary>
Expand Down Expand Up @@ -86,7 +76,7 @@ public NotificationController(INotificationBusinessLogic logic)
[FromQuery] bool? doneState = null,
[FromQuery] string? searchQuery = null
) =>
_logic.GetNotificationsAsync(page, size, new NotificationFilters(isRead, notificationTypeId, notificationTopicId, onlyDueDate, sorting, doneState, searchTypeIds, searchQuery), searchSemantic);
logic.GetNotificationsAsync(page, size, new NotificationFilters(isRead, notificationTypeId, notificationTopicId, onlyDueDate, sorting, doneState, searchTypeIds, searchQuery), searchSemantic);

/// <summary>
/// Gets a notification for the logged in user
Expand All @@ -104,7 +94,7 @@ public NotificationController(INotificationBusinessLogic logic)
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)]
public Task<NotificationDetailData> GetNotification([FromRoute] Guid notificationId) =>
_logic.GetNotificationDetailDataAsync(notificationId);
logic.GetNotificationDetailDataAsync(notificationId);

/// <summary>
/// Gets the notification count for the current logged in user
Expand All @@ -124,7 +114,7 @@ public Task<NotificationDetailData> GetNotification([FromRoute] Guid notificatio
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)]
public Task<int> NotificationCount([FromQuery] bool? isRead) =>
_logic.GetNotificationCountAsync(isRead);
logic.GetNotificationCountAsync(isRead);

/// <summary>
/// Gets the notification count for the current logged in user
Expand All @@ -138,7 +128,7 @@ public Task<int> NotificationCount([FromQuery] bool? isRead) =>
[Authorize(Policy = PolicyTypes.ValidIdentity)]
[ProducesResponseType(typeof(NotificationCountDetails), StatusCodes.Status200OK)]
public Task<NotificationCountDetails> NotificationCountDetails() =>
_logic.GetNotificationCountDetailsAsync();
logic.GetNotificationCountDetailsAsync();

/// <summary>
/// Changes the read status of a notification
Expand All @@ -160,7 +150,7 @@ public Task<NotificationCountDetails> NotificationCountDetails() =>
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)]
public async Task<ActionResult> SetNotificationToRead([FromRoute] Guid notificationId, [FromQuery] bool isRead = true)
{
await _logic.SetNotificationStatusAsync(notificationId, isRead).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.SetNotificationStatusAsync(notificationId, isRead).ConfigureAwait(ConfigureAwaitOptions.None);
return NoContent();
}

Expand All @@ -182,29 +172,28 @@ public async Task<ActionResult> SetNotificationToRead([FromRoute] Guid notificat
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)]
public async Task<ActionResult> DeleteNotification([FromRoute] Guid notificationId)
{
await _logic.DeleteNotificationAsync(notificationId).ConfigureAwait(ConfigureAwaitOptions.None);
await logic.DeleteNotificationAsync(notificationId).ConfigureAwait(ConfigureAwaitOptions.None);
return NoContent();
}

/// <summary>
/// Creates a notification with the given data
/// </summary>
/// <param name="data">Data for the notification</param>
/// <returns>Return NoContent</returns>
/// <remarks>Example: POST: /api/notification/ssi-credentials</remarks>
/// <response code="204">Count of the notifications.</response>
/// <response code="400">NotificationStatus does not exist.</response>
/// <response code="403">IamUserId is not assigned.</response>
[HttpPost]
[Route("ssi-credentials")]
[Authorize(Roles = "create_notifications")]
[Authorize(Policy = PolicyTypes.ValidIdentity)]
[Authorize(Roles = "create_ssi_notifications")]
[Authorize(Policy = PolicyTypes.ServiceAccount)]
[ProducesResponseType(typeof(int), StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status403Forbidden)]
public async Task<ActionResult> CreateNotification([FromBody] NotificationRequest data)
{
await _logic.CreateNotification(data).ConfigureAwait(false);
await logic.CreateNotification(data).ConfigureAwait(false);
return NoContent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
namespace Org.Eclipse.TractusX.Portal.Backend.Notifications.Service.Models;

public record NotificationRequest(
[property: JsonPropertyName("requester")] Guid Requester,
[property: JsonPropertyName("receiver")] Guid Receiver,
[property: JsonPropertyName("content")] string Content,
[property: JsonPropertyName("notificationTypeId")] NotificationTypeId NotificationTypeId
);
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ public async Task CreateNotification_WithNotExistingCompanyUser_ThrowsForbiddenE
}));
var userId = Guid.NewGuid();
var data = _fixture.Build<NotificationRequest>()
.With(x => x.Requester, userId)
.With(x => x.Receiver, userId)
.With(x => x.NotificationTypeId, NotificationTypeId.CREDENTIAL_APPROVAL)
.Create();
A.CallTo(() => _userRepository.CheckUserExists(userId)).Returns(false);
Expand All @@ -487,7 +487,7 @@ public async Task CreateNotification_WithInvalidNotificationType_ThrowsForbidden
MaxPageSize = 15
}));
var userId = Guid.NewGuid();
var data = _fixture.Build<NotificationRequest>().With(x => x.Requester, userId).With(x => x.NotificationTypeId, NotificationTypeId.INFO).Create();
var data = _fixture.Build<NotificationRequest>().With(x => x.Receiver, userId).With(x => x.NotificationTypeId, NotificationTypeId.INFO).Create();
async Task Act() => await sut.CreateNotification(data).ConfigureAwait(false);

// Act
Expand All @@ -509,7 +509,7 @@ public async Task CreateNotification_WithValidData_ExecutesSuccessfully(Notifica
var userId = Guid.NewGuid();
var notifications = new List<Notification>();
var data = _fixture.Build<NotificationRequest>()
.With(x => x.Requester, userId)
.With(x => x.Receiver, userId)
.With(x => x.Content, "test")
.With(x => x.NotificationTypeId, notificationTypeId)
.Create();
Expand Down

0 comments on commit 0823e2d

Please sign in to comment.