Files
sequence/services/csharp/example/RedisSequenceStore.cs
T
Vitalii Litvinchuk 23958e8e2c first commit
2026-06-13 23:23:50 +03:00

63 lines
2.0 KiB
C#

using StackExchange.Redis;
using System.Text.Json;
using SequenceAuth.Lib;
namespace SequenceAuth.Example;
public class RedisSequenceStore(IConnectionMultiplexer redis) : ISequenceStore
{
private readonly IDatabase _db = redis.GetDatabase();
public async Task<Option<SequenceData>> GetSequenceAsync(string sequenceId)
{
var value = await _db.StringGetAsync(sequenceId);
return ((string?)value) switch
{
null => Option<SequenceData>.None(),
string str => ParseData(str)
};
}
private static Option<SequenceData> ParseData(string str)
{
var data = JsonSerializer.Deserialize<SequenceData>(str);
return data switch
{
null => Option<SequenceData>.None(),
_ => Option<SequenceData>.Some(data)
};
}
public async Task<StoreOutcome> SaveSequenceAsync(string sequenceId, SequenceData data)
{
var json = JsonSerializer.Serialize(data);
_ = await _db.StringSetAsync(sequenceId, json);
_ = await _db.SetAddAsync($"UserSessions:{data.UserId}", sequenceId);
return StoreOutcome.Success;
}
public async Task<StoreOutcome> InvalidateUserSessionsAsync(string userId)
{
var sessionKeys = await _db.SetMembersAsync($"UserSessions:{userId}");
foreach(var key in sessionKeys)
{
var seqOpt = await GetSequenceAsync(key.ToString());
_ = seqOpt.State switch
{
OptionState.Some => await UpdateToCompromisedAsync(key.ToString(), seqOpt.Value!),
_ => StoreOutcome.Failure
};
}
return StoreOutcome.Success;
}
private async Task<StoreOutcome> UpdateToCompromisedAsync(string sequenceId, SequenceData data)
{
var compData = data with { State = SequenceState.Compromised };
var json = JsonSerializer.Serialize(compData);
_ = await _db.StringSetAsync(sequenceId, json);
return StoreOutcome.Success;
}
}