- 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>
93 lines
3.3 KiB
C#
93 lines
3.3 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using LehrerApp.Core.Interfaces;
|
|
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Data;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels.Planning;
|
|
using LehrerApp.Sync;
|
|
using LehrerApp.Sync.Crypto;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Security.Cryptography;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace LehrerApp.Desktop.ViewModels.Settings;
|
|
|
|
public partial class SettingsViewModel
|
|
{
|
|
// ── Sicherheit: Datensicherung (13.3.1/13.3.2) ───────────────────────────
|
|
|
|
[ObservableProperty] private string _backupStatus = "";
|
|
[ObservableProperty] private string _secondaryBackupDirectory = "";
|
|
public ObservableCollection<BackupListItem> Backups { get; } = [];
|
|
|
|
/// Vom Code-Behind gesetzt: zeigt einen Bestätigungsdialog vor dem Wiederherstellen.
|
|
public Func<BackupListItem, Task<bool>>? OnConfirmRestore { get; set; }
|
|
|
|
/// Vom Code-Behind gesetzt: öffnet einen Ordnerauswahl-Dialog für das zweite Sicherungsziel.
|
|
public Func<Task<string?>>? OnPickBackupDirectory { get; set; }
|
|
|
|
// ── Datensicherung: Laden / Erstellen / Wiederherstellen ─────────────────
|
|
|
|
private void LoadBackups()
|
|
{
|
|
Backups.Clear();
|
|
foreach (var b in _backups.ListBackups()) Backups.Add(new BackupListItem(b));
|
|
SecondaryBackupDirectory = _backupSettings.LoadSecondaryDirectory() ?? "";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void CreateBackupNow()
|
|
{
|
|
var path = _backups.CreateBackup(AppBootstrapper.DbPath);
|
|
LoadBackups();
|
|
if (path is null) { BackupStatus = "Kein Backup erstellt (Datenbankdatei fehlt)."; return; }
|
|
|
|
BackupStatus = _dbEncryption.CanOpenAndRead(path, AppBootstrapper.DbPassword)
|
|
? "Backup erstellt und geprüft."
|
|
: "Backup erstellt — Prüfung fehlgeschlagen, Datei könnte beschädigt sein!";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task PickBackupDirectory()
|
|
{
|
|
if (OnPickBackupDirectory is null) return;
|
|
var path = await OnPickBackupDirectory();
|
|
if (path is null) return;
|
|
|
|
_backupSettings.SaveSecondaryDirectory(path);
|
|
_backups.SecondaryBackupDirectory = path;
|
|
SecondaryBackupDirectory = path;
|
|
BackupStatus = "Zweiter Sicherungsordner gespeichert.";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void ClearBackupDirectory()
|
|
{
|
|
_backupSettings.SaveSecondaryDirectory(null);
|
|
_backups.SecondaryBackupDirectory = null;
|
|
SecondaryBackupDirectory = "";
|
|
BackupStatus = "Zweiter Sicherungsordner entfernt.";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task RestoreBackup(BackupListItem? item)
|
|
{
|
|
if (item is null) return;
|
|
if (OnConfirmRestore is not null && !await OnConfirmRestore(item)) return;
|
|
|
|
_dbContext.Dispose();
|
|
_backups.RestoreBackup(item.Path, AppBootstrapper.DbPath);
|
|
AppBootstrapper.RestartApplication();
|
|
}
|
|
}
|
|
|
|
public class BackupListItem(BackupInfo info)
|
|
{
|
|
public string Path { get; } = info.Path;
|
|
public string Display { get; } = $"{info.CreatedAt:dd.MM.yyyy HH:mm} · {info.SizeBytes / 1024.0:0} KB";
|
|
}
|