using LiteDB; namespace LehrerApp.Data; /// /// Prüft und ändert den Passwortschutz einer LiteDB-Datei. /// Passwort-Änderungen laufen über eine Kopie (neue Datei mit Zielpasswort, alle /// Collections umkopiert, dann Austausch) statt über LiteDatabase.Rebuild mit /// Passwort, das in LiteDB 5.0.21 nachweislich fehlschlägt (per Skript verifiziert). /// public class DatabaseEncryptionService { public bool IsEncrypted(string dbPath) { if (!File.Exists(dbPath)) return false; try { using var db = new LiteDatabase(dbPath); return false; } catch (LiteException) { return true; } } public bool VerifyPassword(string dbPath, string password) { try { using var db = new LiteDatabase(new ConnectionString(dbPath) { Password = password }); return true; } catch (LiteException) { return false; } } /// Öffnet die Datei probeweise und liest die Sammlungsliste, um eine strukturell gültige /// (nicht nur vorhandene) LiteDB-Datei zu bestätigen — z.B. direkt nach dem Anlegen eines /// Backups, das durch einen vollen Datenträger oder einen vorzeitig entfernten USB-Stick /// beschädigt worden sein könnte. Bewusst breites Catch: jede Art von Fehlschlag beim Öffnen /// oder Lesen bedeutet hier "Backup nicht verifizierbar", nicht nur ein falsches Passwort. public bool CanOpenAndRead(string dbPath, string? password) { if (!File.Exists(dbPath)) return false; try { var connection = password is null ? new ConnectionString(dbPath) : new ConnectionString(dbPath) { Password = password }; using var db = new LiteDatabase(connection); _ = db.GetCollectionNames().ToList(); return true; } catch { return false; } } /// Setzt (newPassword != null), ändert oder entfernt (newPassword == null) das /// Passwort der Datenbank. Der Aufrufer muss sicherstellen, dass keine andere /// Verbindung (z.B. der laufende ) die Datei offen hält. public void SetPassword(string dbPath, string? currentPassword, string? newPassword) { var tempPath = dbPath + ".reencrypt.tmp"; if (File.Exists(tempPath)) File.Delete(tempPath); var srcConnection = currentPassword is null ? new ConnectionString(dbPath) : new ConnectionString(dbPath) { Password = currentPassword }; var dstConnection = newPassword is null ? new ConnectionString(tempPath) : new ConnectionString(tempPath) { Password = newPassword }; using (var src = new LiteDatabase(srcConnection)) using (var dst = new LiteDatabase(dstConnection)) { foreach (var name in src.GetCollectionNames()) { var docs = src.GetCollection(name).FindAll().ToList(); if (docs.Count > 0) dst.GetCollection(name).InsertBulk(docs); } } File.Copy(tempPath, dbPath, overwrite: true); File.Delete(tempPath); } }