62 lines
2.6 KiB
C#
62 lines
2.6 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Tiku.Application.Security;
|
|
using Tiku.Infrastructure.Persistence;
|
|
|
|
namespace Tiku.Infrastructure.Security;
|
|
|
|
internal sealed class AuthorizationCacheInvalidationProcessor(
|
|
TikuDbContext dbContext,
|
|
IAccessSecurityCache cache) : IAuthorizationCacheInvalidationProcessor
|
|
{
|
|
public async Task<int> ProcessPendingAsync(int batchSize = 100, CancellationToken cancellationToken = default)
|
|
{
|
|
if (!cache.IsConfigured)
|
|
{
|
|
return 0;
|
|
}
|
|
var items = await dbContext.AuthorizationCacheInvalidations
|
|
.Where(item => item.ProcessedAt == null)
|
|
.OrderBy(item => item.CreatedAt)
|
|
.Take(Math.Clamp(batchSize, 1, 500))
|
|
.ToArrayAsync(cancellationToken);
|
|
var processed = 0;
|
|
foreach (var item in items)
|
|
{
|
|
try
|
|
{
|
|
switch (item.TargetType)
|
|
{
|
|
case "session" when item.SessionId.HasValue:
|
|
await cache.InvalidateSessionAsync(item.SessionId.Value, cancellationToken);
|
|
break;
|
|
case "user" when item.UserId.HasValue:
|
|
await cache.InvalidateUserAsync(item.UserId.Value, cancellationToken);
|
|
break;
|
|
case "tenant" when item.TenantId.HasValue:
|
|
await cache.InvalidateTenantAsync(item.TenantId.Value, cancellationToken);
|
|
break;
|
|
case "membership" when item.TenantId.HasValue && item.UserId.HasValue:
|
|
await cache.InvalidateMembershipAsync(item.TenantId.Value, item.UserId.Value, cancellationToken);
|
|
break;
|
|
case "scope" when item.Realm.HasValue && item.Version.HasValue:
|
|
await cache.SetAuthorizationVersionAsync(item.Realm.Value, item.TenantId, item.Version.Value, cancellationToken);
|
|
break;
|
|
default:
|
|
throw new InvalidOperationException($"Invalid authorization cache invalidation {item.Id}.");
|
|
}
|
|
item.ProcessedAt = DateTimeOffset.UtcNow;
|
|
item.LastError = null;
|
|
item.AttemptCount++;
|
|
processed++;
|
|
}
|
|
catch (Exception exception) when (exception is not OperationCanceledException)
|
|
{
|
|
item.AttemptCount++;
|
|
item.LastError = exception.Message;
|
|
}
|
|
}
|
|
await dbContext.SaveChangesAsync(cancellationToken);
|
|
return processed;
|
|
}
|
|
}
|