You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.8 KiB

2 months ago
using System.IO;
using System.Text.Json;
namespace Housing.Services;
public sealed class LoginHistoryStore
{
private const int MaxHistoryCount = 3;
private readonly string _filePath;
private readonly LoginHistoryData _data;
private LoginHistoryStore(string filePath, LoginHistoryData data)
{
_filePath = filePath;
_data = data;
}
public static LoginHistoryStore Load(string filePath)
{
try
{
if (!File.Exists(filePath))
{
return new LoginHistoryStore(filePath, new LoginHistoryData());
}
var json = File.ReadAllText(filePath);
var data = JsonSerializer.Deserialize<LoginHistoryData>(json) ?? new LoginHistoryData();
data.Fields ??= new Dictionary<string, List<string>>();
return new LoginHistoryStore(filePath, data);
}
catch
{
return new LoginHistoryStore(filePath, new LoginHistoryData());
}
}
public IReadOnlyList<string> GetValues(string fieldName)
{
return _data.Fields.TryGetValue(fieldName, out var values)
? values.Where(value => !string.IsNullOrWhiteSpace(value)).Take(MaxHistoryCount).ToArray()
: Array.Empty<string>();
}
public void Remember(string fieldName, string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return;
}
if (!_data.Fields.TryGetValue(fieldName, out var values))
{
values = new List<string>();
_data.Fields[fieldName] = values;
}
values.RemoveAll(item => string.Equals(item, value, StringComparison.OrdinalIgnoreCase));
values.Insert(0, value);
if (values.Count > MaxHistoryCount)
{
values.RemoveRange(MaxHistoryCount, values.Count - MaxHistoryCount);
}
}
public bool Forget(string fieldName, string value)
{
if (string.IsNullOrWhiteSpace(value) ||
!_data.Fields.TryGetValue(fieldName, out var values))
{
return false;
}
var removedCount = values.RemoveAll(item => string.Equals(item, value, StringComparison.OrdinalIgnoreCase));
if (values.Count == 0)
{
_data.Fields.Remove(fieldName);
}
return removedCount > 0;
}
public void Save()
{
var directory = Path.GetDirectoryName(_filePath);
if (!string.IsNullOrWhiteSpace(directory))
{
Directory.CreateDirectory(directory);
}
var json = JsonSerializer.Serialize(_data, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(_filePath, json);
}
private sealed class LoginHistoryData
{
public Dictionary<string, List<string>> Fields { get; set; } = new(StringComparer.OrdinalIgnoreCase);
}
}