Files
jobtrackingapp/JobTrackerApi/Services/UserNotificationStore.cs
T

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.");
}
}