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:
@@ -0,0 +1,80 @@
|
||||
using LiteDB;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Data.Tests;
|
||||
|
||||
public sealed class DatabaseEncryptionServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public void IsEncrypted_OhneVorhandeneDatei_GibtFalseZurueck()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
var service = new DatabaseEncryptionService();
|
||||
|
||||
Assert.False(service.IsEncrypted(temp.Path));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsEncrypted_UnverschluesselteDatenbank_GibtFalseZurueck()
|
||||
{
|
||||
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.False(service.IsEncrypted(temp.Path));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetPassword_VerschluesseltDieDatenbankUndBehaeltDieDaten()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
using (var db = new LiteDatabase(temp.Path))
|
||||
db.GetCollection<BsonDocument>("t").Insert(new BsonDocument { ["Name"] = "Hallo" });
|
||||
|
||||
var service = new DatabaseEncryptionService();
|
||||
service.SetPassword(temp.Path, currentPassword: null, newPassword: "geheim123");
|
||||
|
||||
Assert.True(service.IsEncrypted(temp.Path));
|
||||
Assert.True(service.VerifyPassword(temp.Path, "geheim123"));
|
||||
Assert.False(service.VerifyPassword(temp.Path, "falsch"));
|
||||
|
||||
using var reopened = new LiteDatabase(new ConnectionString(temp.Path) { Password = "geheim123" });
|
||||
var doc = reopened.GetCollection<BsonDocument>("t").FindAll().First();
|
||||
Assert.Equal("Hallo", doc["Name"].AsString);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetPassword_EntferntDasPasswortWiederWennNeuesPasswortNullIst()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
var service = new DatabaseEncryptionService();
|
||||
using (var db = new LiteDatabase(new ConnectionString(temp.Path) { Password = "geheim123" }))
|
||||
db.GetCollection<BsonDocument>("t").Insert(new BsonDocument { ["x"] = 1 });
|
||||
|
||||
service.SetPassword(temp.Path, currentPassword: "geheim123", newPassword: null);
|
||||
|
||||
Assert.False(service.IsEncrypted(temp.Path));
|
||||
using var reopened = new LiteDatabase(temp.Path);
|
||||
Assert.Single(reopened.GetCollection<BsonDocument>("t").FindAll());
|
||||
}
|
||||
|
||||
private sealed class TempDatabase : IDisposable
|
||||
{
|
||||
private readonly string _directory = System.IO.Path.Combine(
|
||||
System.IO.Path.GetTempPath(), $"lehrerapp-dbenc-tests-{Guid.NewGuid():N}");
|
||||
public string Path { get; }
|
||||
|
||||
public TempDatabase()
|
||||
{
|
||||
Directory.CreateDirectory(_directory);
|
||||
Path = System.IO.Path.Combine(_directory, "test.db");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_directory)) Directory.Delete(_directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,6 +115,26 @@ public sealed class LiteDbContextTests
|
||||
new ExamResult { StudentId = studentId, ExamId = examId }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NeueDatenbank_HatDieAktuelleSchemaVersionNachDemErstenOeffnen()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
using var context = new LiteDbContext(temp.Path);
|
||||
|
||||
Assert.Equal(1, context.SchemaVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SchemaVersion_WirdUeberEinenNeustartHinwegBeibehalten()
|
||||
{
|
||||
using var temp = new TempDatabase();
|
||||
using (var first = new LiteDbContext(temp.Path)) { }
|
||||
|
||||
using var second = new LiteDbContext(temp.Path);
|
||||
|
||||
Assert.Equal(1, second.SchemaVersion);
|
||||
}
|
||||
|
||||
private sealed class TempDatabase : IDisposable
|
||||
{
|
||||
private readonly string _directory = System.IO.Path.Combine(
|
||||
|
||||
Reference in New Issue
Block a user