Datensicherheit: Backup, Verschlüsselung, App-Sperre (Kapitel 13.3)
Automatisches rollierendes Backup der Datenbank beim Start mit Wiederherstellung über die Einstellungen, versionierte Schema-Migration, optionale Passwort-Verschlüsselung der LiteDB-Datei und eine App-Sperre nach Inaktivität mit eigenem Passwort. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -530,11 +530,54 @@ Fächer- und Kompetenzverwaltung existiert bereits in
|
||||
"Schüler ausgewählt?", kein Textfeld zum Andocken vorhanden).
|
||||
|
||||
### 13.3 Datensicherheit
|
||||
- [ ] **13.3.1** Automatisches lokales Backup der LiteDB beim Start (rollierend, letzte 10).
|
||||
- [ ] **13.3.2** Wiederherstellung aus einem Backup über die Einstellungen.
|
||||
- [ ] **13.3.3** Schema-Migration: Versionsnummer in der DB, Migrationsschritte beim Start.
|
||||
- [ ] **13.3.4** Optionale Verschlüsselung der lokalen Datenbank (LiteDB-Passwort).
|
||||
- [ ] **13.3.5** App-Sperre nach Inaktivität (Schülerdaten auf dem Lehrerrechner).
|
||||
- [x] **13.3.1** Automatisches lokales Backup der LiteDB beim Start (rollierend, letzte 10) —
|
||||
[BackupService.cs](LehrerApp.Core/Services/BackupService.cs). Reine Dateikopie nach
|
||||
`<AppData>/LehrerApp/backups/`, läuft in `AppBootstrapper.BuildServices()` **vor** dem
|
||||
Öffnen der Datenbank (unabhängig von Verschlüsselung, kein LiteDB-Handle nötig). Behält
|
||||
standardmäßig die letzten 10 Backups, ältere werden entfernt. 6 Tests in
|
||||
[BackupServiceTests.cs](LehrerApp.Tests/BackupServiceTests.cs).
|
||||
- [x] **13.3.2** Wiederherstellung aus einem Backup über die Einstellungen — neuer Tab
|
||||
"Sicherheit" in [SettingsView.axaml](LehrerApp.Desktop/Views/Settings/SettingsView.axaml)
|
||||
listet vorhandene Backups mit Zeitstempel/Größe, "Wiederherstellen" fragt über einen neuen
|
||||
generischen [ConfirmDialog](LehrerApp.Desktop/Views/Shared/ConfirmDialog.axaml) nach,
|
||||
kopiert das Backup über die aktive Datenbankdatei und startet die App danach automatisch
|
||||
neu (`AppBootstrapper.RestartApplication()`) — ein laufender LiteDB-Verbindung kann nicht
|
||||
sicher "heiß" auf eine andere Datei umgehängt werden.
|
||||
- [x] **13.3.3** Schema-Migration mit Versionsnummer — `LiteDbContext` schreibt die
|
||||
Schema-Version in eine `meta`-Collection und führt Migrationsschritte nur noch aus, wenn
|
||||
die gespeicherte Version dahinter liegt (`RunVersionedMigrations`), statt wie bisher bei
|
||||
jedem Start erneut über alle Daten zu laufen. Die bestehenden (bereits idempotenten)
|
||||
Migrationsschritte wurden als Version-1-Schritt gebündelt, für zukünftige
|
||||
Schema-Änderungen ergänzt man einen weiteren `if (version < N)`-Block. 2 Tests in
|
||||
[LiteDbContextTests.cs](LehrerApp.Data.Tests/LiteDbContextTests.cs).
|
||||
- [x] **13.3.4** Optionale Verschlüsselung der lokalen Datenbank —
|
||||
[DatabaseEncryptionService.cs](LehrerApp.Data/DatabaseEncryptionService.cs). Passwort
|
||||
setzen/ändern/entfernen läuft über eine Kopie (neue Datei mit Zielpasswort anlegen, alle
|
||||
Collections umkopieren, Datei austauschen) statt über `LiteDatabase.Rebuild(...)` mit
|
||||
Passwort — das ist in LiteDB 5.0.21 nachweislich fehlerhaft (per Skript verifiziert: wirft
|
||||
"this data file is encrypted" beim Rebuild einer unverschlüsselten Datei). Ist die
|
||||
Datenbank verschlüsselt, fragt ein eigenes Fenster
|
||||
([DbPasswordPromptWindow](LehrerApp.Desktop/Views/DbPasswordPromptWindow.axaml)) das
|
||||
Passwort ab, **bevor** `AppBootstrapper.BuildServices()` (und damit das Öffnen der
|
||||
Datenbank) läuft — siehe `App.axaml.cs`. Ändern/Entfernen des Passworts läuft über
|
||||
Einstellungen → Sicherheit, jeweils mit Neustart der App danach. 4 Tests in
|
||||
[DatabaseEncryptionServiceTests.cs](LehrerApp.Data.Tests/DatabaseEncryptionServiceTests.cs).
|
||||
- [x] **13.3.5** App-Sperre nach Inaktivität —
|
||||
[AppLockService.cs](LehrerApp.Core/Services/AppLockService.cs) (eigenes, gesalzenes
|
||||
PBKDF2-Passwort, unabhängig von einer eventuellen Datenbank-Verschlüsselung) +
|
||||
[AppLockViewModel.cs](LehrerApp.Desktop/ViewModels/AppLockViewModel.cs) (Inaktivitäts-Timer,
|
||||
Sperrbildschirm-Logik). Maus-/Tastatureingaben im Hauptfenster setzen den Timer zurück
|
||||
([MainWindow.axaml.cs](LehrerApp.Desktop/Views/MainWindow.axaml.cs)); läuft er ab, blendet
|
||||
ein Overlay in [MainWindow.axaml](LehrerApp.Desktop/Views/MainWindow.axaml) die gesamte
|
||||
Oberfläche aus, bis das Passwort stimmt. Einstellbar (aktiv/inaktiv, Zeit, Passwort) über
|
||||
Einstellungen → Sicherheit, wirkt sofort ohne Neustart. 2 Tests in
|
||||
[AppLockViewModelTests.cs](LehrerApp.Desktop.Tests/AppLockViewModelTests.cs) (reine
|
||||
Unlock-Logik; der zeitbasierte Inaktivitäts-Timer selbst ist nicht automatisiert getestet).
|
||||
**Hinweis:** `RestartApplication()` startet den Prozess über `Environment.ProcessPath`
|
||||
neu — im veröffentlichten Programm korrekt, im Entwicklungsbetrieb über `dotnet run`
|
||||
zeigt `ProcessPath` auf den `dotnet`-Host statt auf die App, ein Neustart über die
|
||||
Einstellungen ist dort also nur in einer veröffentlichten Build (`dotnet publish`)
|
||||
sinnvoll zu testen.
|
||||
|
||||
### 13.4 Codepflege
|
||||
- [ ] **13.4.1** `CLAUDE.md` mit Projektkonventionen anlegen (`/init`).
|
||||
|
||||
Reference in New Issue
Block a user