Baustein 8: Settings-Tab "Synchronisation" (Kapitel 10)
Neuer Tab in den Einstellungen: Server-URL, Login, Verbindungstest, Logout. - Neu SyncSettingsService (Muster AiSettingsService): Token AES-256-verschluesselt ueber SyncCrypto mit eigenem, rein lokalem Schluessel - ersetzt die bisherigen Klartext-Helfer AppBootstrapper.LoadServerUrl/SaveServerUrl und die unverschluesselte auth.token-Datei - Neu SyncAuthService fuer den Login-HTTP-Aufruf gegen /api/auth/login und den Verbindungstest (unterscheidet erreichbar & angemeldet / erreichbar aber nicht angemeldet / nicht erreichbar) - Speichern/Anmelden startet die App neu (AppBootstrapper. RestartApplication, gleiches Muster wie bei DB-Passwort/AppLock- Aenderungen) - SyncEngine/SnapshotService werden nur einmalig beim Start registriert, es gibt keinen Live-Re-Registrierungspfad Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
using LehrerApp.Desktop.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
public sealed class SyncSettingsServiceTests
|
||||
{
|
||||
private static string BuildTempPath()
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), $"lehrerapp-syncsettingssvc-tests-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetServerUrl_PersistiertUeberNeueInstanz()
|
||||
{
|
||||
var path = BuildTempPath();
|
||||
new SyncSettingsService(path).SetServerUrl("https://sync.example.com");
|
||||
|
||||
var reloaded = new SyncSettingsService(path);
|
||||
|
||||
Assert.Equal("https://sync.example.com", reloaded.ServerUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetCredentialsAndToken_TokenIstVerschluesseltAbrufbar()
|
||||
{
|
||||
var service = new SyncSettingsService(BuildTempPath());
|
||||
|
||||
service.SetCredentialsAndToken("sebastian", "geheimes-token-123");
|
||||
|
||||
Assert.True(service.IsLoggedIn);
|
||||
Assert.Equal("sebastian", service.Username);
|
||||
Assert.Equal("geheimes-token-123", service.GetToken());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Token_UeberlebtNeueInstanzMitDemselbenPfad()
|
||||
{
|
||||
var path = BuildTempPath();
|
||||
new SyncSettingsService(path).SetCredentialsAndToken("sebastian", "token-abc");
|
||||
|
||||
var reloaded = new SyncSettingsService(path);
|
||||
|
||||
Assert.True(reloaded.IsLoggedIn);
|
||||
Assert.Equal("token-abc", reloaded.GetToken());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TokenDateiEnthaeltNichtDenKlartext()
|
||||
{
|
||||
var path = BuildTempPath();
|
||||
var service = new SyncSettingsService(path);
|
||||
service.SetCredentialsAndToken("sebastian", "geheimes-token-123");
|
||||
|
||||
var raw = File.ReadAllText(Path.Combine(path, "sync-settings.json"));
|
||||
|
||||
Assert.DoesNotContain("geheimes-token-123", raw);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Logout_EntferntTokenBehaeltAberServerUrlUndUsername()
|
||||
{
|
||||
var service = new SyncSettingsService(BuildTempPath());
|
||||
service.SetServerUrl("https://sync.example.com");
|
||||
service.SetCredentialsAndToken("sebastian", "token-abc");
|
||||
|
||||
service.Logout();
|
||||
|
||||
Assert.False(service.IsLoggedIn);
|
||||
Assert.Null(service.GetToken());
|
||||
Assert.Equal("https://sync.example.com", service.ServerUrl);
|
||||
Assert.Equal("sebastian", service.Username);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user