diff --git a/DysonNetwork.Sphere/Permission/PermissionService.cs b/DysonNetwork.Sphere/Permission/PermissionService.cs index a3e49ba..041b2c7 100644 --- a/DysonNetwork.Sphere/Permission/PermissionService.cs +++ b/DysonNetwork.Sphere/Permission/PermissionService.cs @@ -35,11 +35,9 @@ public class PermissionService( { var cacheKey = _GetPermissionCacheKey(actor, area, key); - var cachedValue = await cache.GetAsync(cacheKey); - if (cachedValue != null) - { + var (hit, cachedValue) = await cache.GetAsyncWithStatus(cacheKey); + if (hit) return cachedValue; - } var now = SystemClock.Instance.GetCurrentInstant(); var groupsKey = _GetGroupsCacheKey(actor); @@ -49,8 +47,8 @@ public class PermissionService( { groupsId = await db.PermissionGroupMembers .Where(n => n.Actor == actor) - .Where(n => n.ExpiredAt == null || n.ExpiredAt < now) - .Where(n => n.AffectedAt == null || n.AffectedAt >= now) + .Where(n => n.ExpiredAt == null || n.ExpiredAt > now) + .Where(n => n.AffectedAt == null || n.AffectedAt <= now) .Select(e => e.GroupId) .ToListAsync(); @@ -60,10 +58,11 @@ public class PermissionService( } var permission = await db.PermissionNodes - .Where(n => n.GroupId == null || groupsId.Contains(n.GroupId.Value)) - .Where(n => n.Key == key && (n.GroupId != null || n.Actor == actor) && n.Area == area) - .Where(n => n.ExpiredAt == null || n.ExpiredAt < now) - .Where(n => n.AffectedAt == null || n.AffectedAt >= now) + .Where(n => (n.GroupId == null && n.Actor == actor) || + (n.GroupId != null && groupsId.Contains(n.GroupId.Value))) + .Where(n => n.Key == key && n.Area == area) + .Where(n => n.ExpiredAt == null || n.ExpiredAt > now) + .Where(n => n.AffectedAt == null || n.AffectedAt <= now) .FirstOrDefaultAsync(); var result = permission is not null ? _DeserializePermissionValue(permission.Value) : default; diff --git a/DysonNetwork.Sphere/Storage/CacheService.cs b/DysonNetwork.Sphere/Storage/CacheService.cs index 3b9308f..acae560 100644 --- a/DysonNetwork.Sphere/Storage/CacheService.cs +++ b/DysonNetwork.Sphere/Storage/CacheService.cs @@ -43,6 +43,11 @@ public interface ICacheService /// Gets a value from the cache /// Task GetAsync(string key); + + /// + /// Get a value from the cache with the found status + /// + Task<(bool found, T? value)> GetAsyncWithStatus(string key); /// /// Removes a specific key from the cache @@ -231,6 +236,20 @@ public class CacheServiceRedis : ICacheService return JsonConvert.DeserializeObject(value!, _serializerSettings); } + public async Task<(bool found, T? value)> GetAsyncWithStatus(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("Key cannot be null or empty", nameof(key)); + + var value = await _database.StringGetAsync(key); + + if (value.IsNullOrEmpty) + return (false, default); + + // For NodaTime serialization, use the configured serializer settings + return (true, JsonConvert.DeserializeObject(value!, _serializerSettings)); + } + public async Task RemoveAsync(string key) { if (string.IsNullOrEmpty(key))