Fixed auth state caching
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using DotBased.ASP.Auth.Domains.Auth;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
|
||||
namespace DotBased.ASP.Auth;
|
||||
|
||||
@@ -12,42 +13,45 @@ public class AuthDataCache
|
||||
|
||||
private readonly BasedAuthConfiguration _configuration;
|
||||
|
||||
private readonly CacheNodeCollection<AuthenticationStateModel> _authenticationStateCollection = [];
|
||||
private readonly AuthStateCacheCollection<AuthenticationStateModel, AuthenticationState> _authenticationStateCollection = [];
|
||||
|
||||
public Result PurgeSessionState(string id) => _authenticationStateCollection.Remove(id) ? Result.Ok() : Result.Failed("Failed to purge session state from cache! Or the session was not cached...");
|
||||
|
||||
public void CacheSessionState(AuthenticationStateModel state) => _authenticationStateCollection.Insert(new CacheNode<AuthenticationStateModel>(state));
|
||||
public void CacheSessionState(AuthenticationStateModel stateModel, AuthenticationState? state = null) => _authenticationStateCollection[stateModel.Id] =
|
||||
new AuthStateCacheNode<AuthenticationStateModel, AuthenticationState>(stateModel, state);
|
||||
|
||||
public Result<AuthenticationStateModel> RequestSessionState(string id)
|
||||
public Result<Tuple<AuthenticationStateModel, AuthenticationState?>> RequestSessionState(string id)
|
||||
{
|
||||
if (!_authenticationStateCollection.TryGetValue(id, out var node))
|
||||
return Result<AuthenticationStateModel>.Failed("No cached object found!");
|
||||
return Result<Tuple<AuthenticationStateModel, AuthenticationState?>>.Failed("No cached object found!");
|
||||
string failedMsg;
|
||||
if (node.Object != null)
|
||||
if (node.StateModel != null)
|
||||
{
|
||||
if (node.IsValidLifespan(_configuration.CachedAuthSessionLifespan))
|
||||
return Result<AuthenticationStateModel>.Ok(node.Object);
|
||||
return Result<Tuple<AuthenticationStateModel, AuthenticationState?>>.Ok(new Tuple<AuthenticationStateModel, AuthenticationState?>(node.StateModel, node.State));
|
||||
failedMsg = $"Session has invalid lifespan, removing entry: [{id}] from cache!";
|
||||
}
|
||||
else
|
||||
failedMsg = $"Returned object is null, removing entry: [{id}] from cache!";
|
||||
_authenticationStateCollection.Remove(id);
|
||||
return Result<AuthenticationStateModel>.Failed(failedMsg);
|
||||
return Result<Tuple<AuthenticationStateModel, AuthenticationState?>>.Failed(failedMsg);
|
||||
}
|
||||
}
|
||||
|
||||
public class CacheNode<T> where T : class
|
||||
public class AuthStateCacheNode<TStateModel, TState> where TStateModel : class where TState : class
|
||||
{
|
||||
public CacheNode(T obj)
|
||||
public AuthStateCacheNode(TStateModel stateModel, TState? state)
|
||||
{
|
||||
Object = obj;
|
||||
StateModel = stateModel;
|
||||
State = state;
|
||||
}
|
||||
public T? Object { get; private set; }
|
||||
public TStateModel? StateModel { get; private set; }
|
||||
public TState? State { get; private set; }
|
||||
public DateTime DateCached { get; private set; } = DateTime.Now;
|
||||
|
||||
public void UpdateObject(T obj)
|
||||
public void UpdateObject(TStateModel obj)
|
||||
{
|
||||
Object = obj;
|
||||
StateModel = obj;
|
||||
DateCached = DateTime.Now;
|
||||
}
|
||||
|
||||
@@ -55,37 +59,37 @@ public class CacheNode<T> where T : class
|
||||
/// Checks if the cached object is within the given lifespan.
|
||||
/// </summary>
|
||||
/// <param name="lifespan">The max. lifespan</param>
|
||||
public bool IsValidLifespan(TimeSpan lifespan) => DateCached.Add(lifespan) < DateTime.Now;
|
||||
public bool IsValidLifespan(TimeSpan lifespan) => DateCached.Add(lifespan) > DateTime.Now;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is CacheNode<T> cacheObj)
|
||||
return typeof(T).Equals(cacheObj.Object);
|
||||
if (obj is AuthStateCacheNode<TStateModel, TState> cacheObj)
|
||||
return StateModel != null && StateModel.Equals(cacheObj.StateModel);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode() => typeof(T).GetHashCode();
|
||||
public override string ToString() => typeof(T).ToString();
|
||||
public override int GetHashCode() => typeof(TStateModel).GetHashCode();
|
||||
public override string ToString() => typeof(TStateModel).ToString();
|
||||
}
|
||||
|
||||
public class CacheNodeCollection<TItem> : KeyedCollection<string, CacheNode<TItem>> where TItem : class
|
||||
public class AuthStateCacheCollection<TStateModel, TState> : KeyedCollection<string, AuthStateCacheNode<TStateModel, TState>> where TStateModel : class where TState : class
|
||||
{
|
||||
protected override string GetKeyForItem(CacheNode<TItem> item) => item.Object?.ToString() ?? string.Empty;
|
||||
protected override string GetKeyForItem(AuthStateCacheNode<TStateModel, TState> item) => item.StateModel?.ToString() ?? string.Empty;
|
||||
|
||||
public new CacheNode<TItem>? this[string id]
|
||||
public new AuthStateCacheNode<TStateModel, TState>? this[string id]
|
||||
{
|
||||
get => TryGetValue(id, out CacheNode<TItem>? nodeValue) ? nodeValue : null;
|
||||
get => TryGetValue(id, out AuthStateCacheNode<TStateModel, TState>? nodeValue) ? nodeValue : null;
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
if (TryGetValue(id, out CacheNode<TItem>? nodeValue))
|
||||
if (TryGetValue(id, out AuthStateCacheNode<TStateModel, TState>? nodeValue))
|
||||
Remove(nodeValue);
|
||||
Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Insert(CacheNode<TItem> node)
|
||||
public void Insert(AuthStateCacheNode<TStateModel, TState> node)
|
||||
{
|
||||
if (Contains(node))
|
||||
Remove(node);
|
||||
|
Reference in New Issue
Block a user