| | | 1 | | using Anichron.Core.Domain; |
| | | 2 | | using Microsoft.EntityFrameworkCore; |
| | | 3 | | |
| | | 4 | | namespace Anichron.Core.Data.Repository; |
| | | 5 | | |
| | | 6 | | public interface IRefreshTokenRepository |
| | | 7 | | { |
| | | 8 | | Task<RefreshToken?> FindByHashWithUserAsync(string tokenHash, CancellationToken ct); |
| | | 9 | | Task<RefreshToken?> FindByHashAsync(string tokenHash, CancellationToken ct); |
| | | 10 | | void Add(RefreshToken token); |
| | | 11 | | Task RevokeAllActiveByUserIdAsync(Guid userId, Instant revokedAt, CancellationToken ct); |
| | | 12 | | Task<int> DeleteExpiredAsync(Instant before, CancellationToken ct); |
| | | 13 | | } |
| | | 14 | | |
| | 5 | 15 | | public sealed class EfRefreshTokenRepository(AnichronDbContext db) : IRefreshTokenRepository |
| | | 16 | | { |
| | | 17 | | public Task<RefreshToken?> FindByHashWithUserAsync(string tokenHash, CancellationToken ct) |
| | 2 | 18 | | => db.RefreshTokens.Include(r => r.User).FirstOrDefaultAsync(r => r.TokenHash == tokenHash, ct); |
| | | 19 | | |
| | | 20 | | public Task<RefreshToken?> FindByHashAsync(string tokenHash, CancellationToken ct) |
| | 3 | 21 | | => db.RefreshTokens.FirstOrDefaultAsync(r => r.TokenHash == tokenHash, ct); |
| | | 22 | | |
| | | 23 | | public void Add(RefreshToken token) |
| | 1 | 24 | | => db.RefreshTokens.Add(token); |
| | | 25 | | |
| | | 26 | | public Task RevokeAllActiveByUserIdAsync(Guid userId, Instant revokedAt, CancellationToken ct) |
| | 0 | 27 | | => db.RefreshTokens |
| | 0 | 28 | | .Where(t => t.UserId == userId && t.RevokedAt == null) |
| | 0 | 29 | | .ExecuteUpdateAsync(s => s.SetProperty(t => t.RevokedAt, revokedAt), ct); |
| | | 30 | | |
| | | 31 | | public Task<int> DeleteExpiredAsync(Instant before, CancellationToken ct) |
| | 0 | 32 | | => db.RefreshTokens.Where(t => t.ExpiresAt < before).ExecuteDeleteAsync(ct); |
| | | 33 | | } |