using LiteDB; namespace LehrerApp.Api; public class UserStore(string dataPath) : IDisposable { private readonly LiteDatabase _db = new(Path.Combine(dataPath, "users.db")); private ILiteCollection Col { get { var col = _db.GetCollection("users"); col.EnsureIndex(x => x.Username, unique: true); return col; } } public bool CreateUser(string username, string password) { if (Col.Exists(x => x.Username == username)) return false; Col.Insert(new UserEntry { Username = username, PasswordHash = PasswordHasher.Hash(password) }); return true; } public bool SetPassword(string username, string password) { var user = Col.FindOne(x => x.Username == username); if (user is null) return false; user.PasswordHash = PasswordHasher.Hash(password); Col.Update(user); return true; } /// /// Prüft die Anmeldedaten und liefert bei Erfolg den GESPEICHERTEN Nutzereintrag zurück - /// nicht bloß true/false. Wichtig: LiteDBs Standard-Collation vergleicht Strings (und damit /// auch den eindeutigen Index auf Username) standardmäßig case-insensitive, d.h. ein Login mit /// abweichender Groß-/Kleinschreibung authentifiziert erfolgreich. Würde der Aufrufer daraufhin /// den roh eingegebenen Benutzernamen als userId für den Server-seitigen Event-Speicher /// verwenden (siehe EventStore.GetCol), würde ein einziger andersartig getippter Login auf /// einem zweiten Gerät einen komplett getrennten, nicht überlappenden Datenbestand erzeugen, /// obwohl es sich aus Nutzersicht um dasselbe Konto handelt. Der kanonisch gespeicherte Name /// aus diesem Rückgabewert stellt sicher, dass die userId unabhängig von der beim Login /// eingegebenen Schreibweise stets identisch ist. /// public UserEntry? Authenticate(string username, string password) { var user = Col.FindOne(x => x.Username == username); return user is not null && PasswordHasher.Verify(password, user.PasswordHash) ? user : null; } public void Dispose() => _db.Dispose(); } public class UserEntry { public ObjectId Id { get; set; } = ObjectId.NewObjectId(); public string Username { get; set; } = ""; public string PasswordHash { get; set; } = ""; }