57 lines
2.4 KiB
C#
57 lines
2.4 KiB
C#
using JobTrackerApi.Data;
|
|
using JobTrackerApi.Models;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace JobTrackerApi.Services;
|
|
|
|
public sealed class UserNotificationStore(JobTrackerContext db, TimeProvider timeProvider)
|
|
{
|
|
public Task<UserNotification?> GetAsync(Guid notificationId, CancellationToken cancellationToken)
|
|
{
|
|
EnsureOwnerScope();
|
|
return db.UserNotifications.AsNoTracking().FirstOrDefaultAsync(notification => notification.Id == notificationId, cancellationToken);
|
|
}
|
|
|
|
public Task<List<UserNotification>> ListAsync(int limit, CancellationToken cancellationToken)
|
|
{
|
|
EnsureOwnerScope();
|
|
if (limit is < 1 or > 100) throw new ArgumentOutOfRangeException(nameof(limit));
|
|
return db.UserNotifications.AsNoTracking()
|
|
.Where(notification => notification.DismissedAtUtc == null)
|
|
.OrderByDescending(notification => notification.CreatedAtUtc)
|
|
.Take(limit)
|
|
.ToListAsync(cancellationToken);
|
|
}
|
|
|
|
public Task<int> UnreadCountAsync(CancellationToken cancellationToken)
|
|
{
|
|
EnsureOwnerScope();
|
|
return db.UserNotifications.CountAsync(
|
|
notification => notification.DismissedAtUtc == null && notification.ReadAtUtc == null,
|
|
cancellationToken);
|
|
}
|
|
|
|
public Task<int> MarkReadAsync(Guid notificationId, CancellationToken cancellationToken)
|
|
{
|
|
EnsureOwnerScope();
|
|
var now = timeProvider.GetUtcNow().UtcDateTime;
|
|
return db.UserNotifications
|
|
.Where(notification => notification.Id == notificationId && notification.ReadAtUtc == null)
|
|
.ExecuteUpdateAsync(setters => setters.SetProperty(notification => notification.ReadAtUtc, now), cancellationToken);
|
|
}
|
|
|
|
public Task<int> DismissAsync(Guid notificationId, CancellationToken cancellationToken)
|
|
{
|
|
EnsureOwnerScope();
|
|
var now = timeProvider.GetUtcNow().UtcDateTime;
|
|
return db.UserNotifications
|
|
.Where(notification => notification.Id == notificationId && notification.DismissedAtUtc == null)
|
|
.ExecuteUpdateAsync(setters => setters.SetProperty(notification => notification.DismissedAtUtc, now), cancellationToken);
|
|
}
|
|
|
|
private void EnsureOwnerScope()
|
|
{
|
|
if (db.CurrentUserId is null) throw new InvalidOperationException("Notification access requires an authenticated owner scope.");
|
|
}
|
|
}
|