using System.Collections.ObjectModel; using DotBased.ASP.Auth.Domains.Auth; namespace DotBased.ASP.Auth; public class AuthDataCache { public AuthDataCache(IAuthDataRepository dataRepository, BasedAuthConfiguration configuration) { DataRepository = dataRepository; _configuration = configuration; } public readonly IAuthDataRepository DataRepository; private readonly BasedAuthConfiguration _configuration; private readonly CacheNodeCollection _authenticationStateCollection = []; public Result PurgeSessionFromCache(string id) => _authenticationStateCollection.Remove(id) ? Result.Ok() : Result.Failed("Failed to purge session state from cache!"); public async Task> RequestAuthStateAsync(string id) { if (_authenticationStateCollection.TryGetValue(id, out var node)) { if (node.Object == null) { _authenticationStateCollection.Remove(id); return Result.Failed($"Returned object is null, removing entry [{id}] from cache!"); } if (node.IsValidLifespan(_configuration.CachedAuthSessionLifespan)) return Result.Ok(node.Object); } var dbResult = await DataRepository.GetAuthenticationStateAsync(id); if (!dbResult.Success || dbResult.Value == null) { _authenticationStateCollection.Remove(id); return Result.Failed("Unknown session state!"); } if (node == null) node = new CacheNode(dbResult.Value); else node.UpdateObject(dbResult.Value); if (node.Object != null) return Result.Ok(node.Object); return node.Object != null ? Result.Ok(node.Object) : Result.Failed("Failed to get db object!"); } /* * */ } public class CacheNode where T : class { public CacheNode(T obj) { Object = obj; } public T? Object { get; private set; } public DateTime DateCached { get; private set; } = DateTime.Now; public void UpdateObject(T obj) { Object = obj; DateCached = DateTime.Now; } /// /// Checks if the cached object is within the given lifespan. /// /// The max. lifespan public bool IsValidLifespan(TimeSpan lifespan) => DateCached.Add(lifespan) < DateTime.Now; public override bool Equals(object? obj) { if (obj is CacheNode cacheObj) return typeof(T).Equals(cacheObj.Object); return false; } public override int GetHashCode() => typeof(T).GetHashCode(); public override string ToString() => typeof(T).ToString(); } public class CacheNodeCollection : KeyedCollection> where TItem : class { protected override string GetKeyForItem(CacheNode item) => item.Object?.ToString() ?? string.Empty; }