using System.Collections.Concurrent;
using MealPlan.Api.Models;
namespace MealPlan.Api.Services;
///
/// Thread-safe in-memory refresh token store registered as a singleton.
/// Note: tokens live only for the lifetime of the process. For multi-instance
/// deployments this should be swapped for a shared store (e.g. Redis), but it
/// satisfies the "do not modify the database" constraint of this project.
///
public class InMemoryRefreshTokenStore : IRefreshTokenStore
{
private readonly ConcurrentDictionary _tokens = new();
public void Add(RefreshToken token) => _tokens[token.Token] = token;
public RefreshToken? Get(string token) =>
_tokens.TryGetValue(token, out var found) ? found : null;
public RefreshToken? Revoke(string token)
{
if (!_tokens.TryGetValue(token, out var found))
{
return null;
}
var wasActive = found.IsActive;
found.IsRevoked = true;
return wasActive ? found : null;
}
public void RemoveExpired()
{
foreach (var kvp in _tokens)
{
if (kvp.Value.IsRevoked || DateTime.UtcNow >= kvp.Value.ExpiresAtUtc)
{
_tokens.TryRemove(kvp.Key, out _);
}
}
}
}