Dashboard-Performance, CI-Workflow, Settings-Aufteilung, Backup-Härtung
- Dashboard: Fehlzeiten-Warnung lädt Mitarbeitssitzungen einmal vorab statt pro Schüler/Eintrag einzeln nachzuschlagen (N+1 vermieden); neues IParticipationSessionRepository.GetAll() dafür. - CI: .gitea/workflows/ci.yml baut und testet bei jedem Push/PR. Dabei fehlende Release|Any CPU-Konfiguration für 6 Projekte in der .sln behoben (LehrerApp.Data.Tests wurde bei Release-Builds der Solution bislang stillschweigend übersprungen). TreatWarningsAsErrors jetzt aktiv. - SettingsViewModel (1986 Zeilen) als partial class auf 20 Themen- dateien aufgeteilt, Verhalten unverändert. - Backup: optionaler zweiter Sicherungsordner (USB-Stick/Netzlaufwerk, best-effort) und Integritätsprüfung nach jedem Backup (DatabaseEncryptionService.CanOpenAndRead). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,65 @@ public sealed class DatabaseEncryptionServiceTests
|
||||
Assert.Single(reopened.GetCollection<BsonDocument>("t").FindAll());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOpenAndRead_OhneVorhandeneDatei_GibtFalseZurueck()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
var service = new DatabaseEncryptionService();
|
||||
|
||||
Assert.False(service.CanOpenAndRead(temp.Path, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOpenAndRead_GueltigeUnverschluesselteDatenbank_GibtTrueZurueck()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
using (var db = new LiteDatabase(temp.Path))
|
||||
db.GetCollection<BsonDocument>("t").Insert(new BsonDocument { ["x"] = 1 });
|
||||
|
||||
var service = new DatabaseEncryptionService();
|
||||
|
||||
Assert.True(service.CanOpenAndRead(temp.Path, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOpenAndRead_GueltigeVerschluesselteDatenbankMitRichtigemPasswort_GibtTrueZurueck()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
using (var db = new LiteDatabase(new ConnectionString(temp.Path) { Password = "geheim123" }))
|
||||
db.GetCollection<BsonDocument>("t").Insert(new BsonDocument { ["x"] = 1 });
|
||||
|
||||
var service = new DatabaseEncryptionService();
|
||||
|
||||
Assert.True(service.CanOpenAndRead(temp.Path, "geheim123"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOpenAndRead_FalschesPasswort_GibtFalseZurueck()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
using (var db = new LiteDatabase(new ConnectionString(temp.Path) { Password = "geheim123" }))
|
||||
db.GetCollection<BsonDocument>("t").Insert(new BsonDocument { ["x"] = 1 });
|
||||
|
||||
var service = new DatabaseEncryptionService();
|
||||
|
||||
Assert.False(service.CanOpenAndRead(temp.Path, "falsch"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOpenAndRead_BeschaedigteDatei_GibtFalseZurueck()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
// Eine kurze Textdatei initialisiert LiteDB stillschweigend als neue, leere Datenbank
|
||||
// (kleiner als eine Seite) — erst genug Datenmüll jenseits der Seitengröße lässt das
|
||||
// Datei-Layout tatsächlich fehlschlagen und simuliert eine echte Beschädigung
|
||||
// (z.B. durch einen vollen Datenträger während der Backup-Kopie).
|
||||
File.WriteAllBytes(temp.Path, Enumerable.Repeat((byte)0x42, 32_768).ToArray());
|
||||
var service = new DatabaseEncryptionService();
|
||||
|
||||
Assert.False(service.CanOpenAndRead(temp.Path, null));
|
||||
}
|
||||
|
||||
private sealed class TempDatabase : IDisposable
|
||||
{
|
||||
private readonly string _directory = System.IO.Path.Combine(
|
||||
|
||||
Reference in New Issue
Block a user