Files
adminandClaude Sonnet 5 48d07a2b99 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>
2026-08-13 13:07:36 +02:00

72 lines
2.0 KiB
C#

using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LehrerApp.Core.Services;
namespace LehrerApp.Desktop.ViewModels;
/// <summary>
/// Sperrbildschirm nach Inaktivität (13.3.5). Läuft unabhängig von einer eventuellen
/// Datenbank-Verschlüsselung — eigenes Passwort über <see cref="AppLockService"/>.
/// </summary>
public partial class AppLockViewModel : ObservableObject
{
private readonly AppLockService _appLock;
private System.Timers.Timer? _idleTimer;
[ObservableProperty] private bool _isLocked;
[ObservableProperty] private string _passwordAttempt = "";
[ObservableProperty] private string _unlockError = "";
public AppLockViewModel(AppLockService appLock) => _appLock = appLock;
/// Wird bei jeder Nutzereingabe (Maus/Tastatur) im Hauptfenster aufgerufen.
public void NotifyActivity()
{
if (!IsLocked) ResetIdleTimer();
}
/// Nach dem Start bzw. nach Änderungen in den Einstellungen aufrufen.
public void ApplyConfig()
{
_idleTimer?.Stop();
_idleTimer = null;
if (!_appLock.IsEnabled || !_appLock.HasPassword) return;
_idleTimer = new System.Timers.Timer(_appLock.TimeoutMinutes * 60_000) { AutoReset = false };
_idleTimer.Elapsed += (_, _) => Dispatcher.UIThread.Post(Lock);
_idleTimer.Start();
}
private void ResetIdleTimer()
{
if (_idleTimer is null) return;
_idleTimer.Stop();
_idleTimer.Start();
}
private void Lock()
{
if (!_appLock.IsEnabled || !_appLock.HasPassword) return;
PasswordAttempt = "";
UnlockError = "";
IsLocked = true;
}
[RelayCommand]
private void Unlock()
{
if (_appLock.VerifyPassword(PasswordAttempt))
{
IsLocked = false;
UnlockError = "";
ResetIdleTimer();
}
else
{
UnlockError = "Falsches Passwort.";
}
PasswordAttempt = "";
}
}