using LiteDB; using MailSharp.MailClient.Models; namespace MailSharp.MailClient.Services; public interface IAccountStore { Account Add(Account account, string plainPassword); Account? Get(int id); List GetAll(); void Remove(int id); void Update(Account account); string GetPlainPassword(Account account); } // Holds a single long-lived LiteDatabase connection for the app's lifetime (registered as a // singleton). LiteDatabase is thread-safe for concurrent operations; opening/closing a new // connection per call instead would race on the OS file lock under concurrent requests. public class LiteDbAccountStore : IAccountStore, IDisposable { private readonly LiteDatabase _db; private readonly IPasswordProtector _protector; public LiteDbAccountStore(IWebHostEnvironment env, IPasswordProtector protector) { _protector = protector; var dir = Path.Combine(env.ContentRootPath, "App_Data"); Directory.CreateDirectory(dir); _db = new LiteDatabase(Path.Combine(dir, "accounts.db")); } private ILiteCollection Accounts => _db.GetCollection("accounts"); public Account Add(Account account, string plainPassword) { account.ProtectedPassword = _protector.Protect(plainPassword); Accounts.Insert(account); return account; } public Account? Get(int id) => Accounts.FindById(id); public List GetAll() => [.. Accounts.FindAll()]; public void Remove(int id) => Accounts.Delete(id); public void Update(Account account) => Accounts.Update(account); public string GetPlainPassword(Account account) => _protector.Unprotect(account.ProtectedPassword); public void Dispose() => _db.Dispose(); }