-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PM-10563] Notification Center API (#4852)
* PM-10563: Notification Center API * PM-10563: continuation token hack * PM-10563: Resolving merge conflicts * PM-10563: Unit Tests * PM-10563: Paging simplification by page number and size in database * PM-10563: Request validation * PM-10563: Read, Deleted status filters change * PM-10563: Plural name for tests * PM-10563: Request validation to always for int type * PM-10563: Continuation Token returns null on response when no more records available * PM-10563: Integration tests for GET * PM-10563: Mark notification read, deleted commands date typos fix * PM-10563: Integration tests for PATCH read, deleted * PM-10563: Request, Response models tests * PM-10563: EditorConfig compliance * PM-10563: Extracting to const * PM-10563: Update db migration script date * PM-10563: Update migration script date
- Loading branch information
1 parent
de2dc24
commit 21fcfcd
Showing
18 changed files
with
1,272 additions
and
39 deletions.
There are no files selected for viewing
71 changes: 71 additions & 0 deletions
71
src/Api/NotificationCenter/Controllers/NotificationsController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#nullable enable | ||
using Bit.Api.Models.Response; | ||
using Bit.Api.NotificationCenter.Models.Request; | ||
using Bit.Api.NotificationCenter.Models.Response; | ||
using Bit.Core.Models.Data; | ||
using Bit.Core.NotificationCenter.Commands.Interfaces; | ||
using Bit.Core.NotificationCenter.Models.Filter; | ||
using Bit.Core.NotificationCenter.Queries.Interfaces; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace Bit.Api.NotificationCenter.Controllers; | ||
|
||
[Route("notifications")] | ||
[Authorize("Application")] | ||
public class NotificationsController : Controller | ||
{ | ||
private readonly IGetNotificationStatusDetailsForUserQuery _getNotificationStatusDetailsForUserQuery; | ||
private readonly IMarkNotificationDeletedCommand _markNotificationDeletedCommand; | ||
private readonly IMarkNotificationReadCommand _markNotificationReadCommand; | ||
|
||
public NotificationsController( | ||
IGetNotificationStatusDetailsForUserQuery getNotificationStatusDetailsForUserQuery, | ||
IMarkNotificationDeletedCommand markNotificationDeletedCommand, | ||
IMarkNotificationReadCommand markNotificationReadCommand) | ||
{ | ||
_getNotificationStatusDetailsForUserQuery = getNotificationStatusDetailsForUserQuery; | ||
_markNotificationDeletedCommand = markNotificationDeletedCommand; | ||
_markNotificationReadCommand = markNotificationReadCommand; | ||
} | ||
|
||
[HttpGet("")] | ||
public async Task<ListResponseModel<NotificationResponseModel>> ListAsync( | ||
[FromQuery] NotificationFilterRequestModel filter) | ||
{ | ||
var pageOptions = new PageOptions | ||
{ | ||
ContinuationToken = filter.ContinuationToken, | ||
PageSize = filter.PageSize | ||
}; | ||
|
||
var notificationStatusFilter = new NotificationStatusFilter | ||
{ | ||
Read = filter.ReadStatusFilter, | ||
Deleted = filter.DeletedStatusFilter | ||
}; | ||
|
||
var notificationStatusDetailsPagedResult = | ||
await _getNotificationStatusDetailsForUserQuery.GetByUserIdStatusFilterAsync(notificationStatusFilter, | ||
pageOptions); | ||
|
||
var responses = notificationStatusDetailsPagedResult.Data | ||
.Select(n => new NotificationResponseModel(n)) | ||
.ToList(); | ||
|
||
return new ListResponseModel<NotificationResponseModel>(responses, | ||
notificationStatusDetailsPagedResult.ContinuationToken); | ||
} | ||
|
||
[HttpPatch("{id}/delete")] | ||
public async Task MarkAsDeletedAsync([FromRoute] Guid id) | ||
{ | ||
await _markNotificationDeletedCommand.MarkDeletedAsync(id); | ||
} | ||
|
||
[HttpPatch("{id}/read")] | ||
public async Task MarkAsReadAsync([FromRoute] Guid id) | ||
{ | ||
await _markNotificationReadCommand.MarkReadAsync(id); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
src/Api/NotificationCenter/Models/Request/NotificationFilterRequestModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#nullable enable | ||
using System.ComponentModel.DataAnnotations; | ||
|
||
namespace Bit.Api.NotificationCenter.Models.Request; | ||
|
||
public class NotificationFilterRequestModel : IValidatableObject | ||
{ | ||
/// <summary> | ||
/// Filters notifications by read status. When not set, includes notifications without a status. | ||
/// </summary> | ||
public bool? ReadStatusFilter { get; set; } | ||
|
||
/// <summary> | ||
/// Filters notifications by deleted status. When not set, includes notifications without a status. | ||
/// </summary> | ||
public bool? DeletedStatusFilter { get; set; } | ||
|
||
/// <summary> | ||
/// A cursor for use in pagination. | ||
/// </summary> | ||
[StringLength(9)] | ||
public string? ContinuationToken { get; set; } | ||
|
||
/// <summary> | ||
/// The number of items to return in a single page. | ||
/// Default 10. Minimum 10, maximum 1000. | ||
/// </summary> | ||
[Range(10, 1000)] | ||
public int PageSize { get; set; } = 10; | ||
|
||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) | ||
{ | ||
if (!string.IsNullOrWhiteSpace(ContinuationToken) && | ||
(!int.TryParse(ContinuationToken, out var pageNumber) || pageNumber <= 0)) | ||
{ | ||
yield return new ValidationResult( | ||
"Continuation token must be a positive, non zero integer.", | ||
[nameof(ContinuationToken)]); | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/Api/NotificationCenter/Models/Response/NotificationResponseModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#nullable enable | ||
using Bit.Core.Models.Api; | ||
using Bit.Core.NotificationCenter.Enums; | ||
using Bit.Core.NotificationCenter.Models.Data; | ||
|
||
namespace Bit.Api.NotificationCenter.Models.Response; | ||
|
||
public class NotificationResponseModel : ResponseModel | ||
{ | ||
private const string _objectName = "notification"; | ||
|
||
public NotificationResponseModel(NotificationStatusDetails notificationStatusDetails, string obj = _objectName) | ||
: base(obj) | ||
{ | ||
if (notificationStatusDetails == null) | ||
{ | ||
throw new ArgumentNullException(nameof(notificationStatusDetails)); | ||
} | ||
|
||
Id = notificationStatusDetails.Id; | ||
Priority = notificationStatusDetails.Priority; | ||
Title = notificationStatusDetails.Title; | ||
Body = notificationStatusDetails.Body; | ||
Date = notificationStatusDetails.RevisionDate; | ||
ReadDate = notificationStatusDetails.ReadDate; | ||
DeletedDate = notificationStatusDetails.DeletedDate; | ||
} | ||
|
||
public NotificationResponseModel() : base(_objectName) | ||
{ | ||
} | ||
|
||
public Guid Id { get; set; } | ||
|
||
public Priority Priority { get; set; } | ||
|
||
public string? Title { get; set; } | ||
|
||
public string? Body { get; set; } | ||
|
||
public DateTime Date { get; set; } | ||
|
||
public DateTime? ReadDate { get; set; } | ||
|
||
public DateTime? DeletedDate { get; set; } | ||
} |
29 changes: 29 additions & 0 deletions
29
src/Core/NotificationCenter/NotificationCenterServiceCollectionExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#nullable enable | ||
using Bit.Core.NotificationCenter.Authorization; | ||
using Bit.Core.NotificationCenter.Commands; | ||
using Bit.Core.NotificationCenter.Commands.Interfaces; | ||
using Bit.Core.NotificationCenter.Queries; | ||
using Bit.Core.NotificationCenter.Queries.Interfaces; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace Bit.Core.NotificationCenter; | ||
|
||
public static class NotificationCenterServiceCollectionExtensions | ||
{ | ||
public static void AddNotificationCenterServices(this IServiceCollection services) | ||
{ | ||
// Authorization Handlers | ||
services.AddScoped<IAuthorizationHandler, NotificationAuthorizationHandler>(); | ||
services.AddScoped<IAuthorizationHandler, NotificationStatusAuthorizationHandler>(); | ||
// Commands | ||
services.AddScoped<ICreateNotificationCommand, CreateNotificationCommand>(); | ||
services.AddScoped<ICreateNotificationStatusCommand, CreateNotificationStatusCommand>(); | ||
services.AddScoped<IMarkNotificationDeletedCommand, MarkNotificationDeletedCommand>(); | ||
services.AddScoped<IMarkNotificationReadCommand, MarkNotificationReadCommand>(); | ||
services.AddScoped<IUpdateNotificationCommand, UpdateNotificationCommand>(); | ||
// Queries | ||
services.AddScoped<IGetNotificationStatusDetailsForUserQuery, GetNotificationStatusDetailsForUserQuery>(); | ||
services.AddScoped<IGetNotificationStatusForUserQuery, GetNotificationStatusForUserQuery>(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
src/Core/NotificationCenter/Queries/Interfaces/IGetNotificationStatusDetailsForUserQuery.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
#nullable enable | ||
using Bit.Core.Models.Data; | ||
using Bit.Core.NotificationCenter.Models.Data; | ||
using Bit.Core.NotificationCenter.Models.Filter; | ||
|
||
namespace Bit.Core.NotificationCenter.Queries.Interfaces; | ||
|
||
public interface IGetNotificationStatusDetailsForUserQuery | ||
{ | ||
Task<IEnumerable<NotificationStatusDetails>> GetByUserIdStatusFilterAsync(NotificationStatusFilter statusFilter); | ||
Task<PagedResult<NotificationStatusDetails>> GetByUserIdStatusFilterAsync(NotificationStatusFilter statusFilter, | ||
PageOptions pageOptions); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.