feat: Logout-Warnung bei fehlendem Key-Backup (M1)

Beide Logout-Bestätigungsdialoge prüfen jetzt vorab per neuem
isKeyBackupMissing(client) (bootstrap_dialog.dart), ob Cross-Signing/
Key-Backup eingerichtet ist. Fehlt es, zeigt der Dialog eine
Klartext-Warnung: alte verschlüsselte Nachrichten wären nach dem
Logout auf keinem Gerät mehr lesbar. Ohne fehlendes Backup bleibt der
bisherige Text unverändert.
This commit is contained in:
Bernd Steckmeister
2026-07-03 09:59:10 +02:00
parent e8ab626c92
commit b5762ea08d
3 changed files with 40 additions and 6 deletions
+10
View File
@@ -1134,3 +1134,13 @@
2026-07-03 09:50 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
2026-07-03 09:50 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
2026-07-03 09:51 [Edit] /home/steggi/pyramid/lib/features/auth/login_notifier.dart
2026-07-03 09:51 [Edit] /home/steggi/pyramid/ROADMAP.md
2026-07-03 09:52 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-03 09:55 [Edit] /home/steggi/pyramid/ROADMAP.md
2026-07-03 09:55 [Edit] /home/steggi/pyramid/PROGRESS.md
2026-07-03 09:57 [Edit] /home/steggi/pyramid/lib/features/auth/bootstrap_dialog.dart
2026-07-03 09:58 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
2026-07-03 09:58 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
2026-07-03 09:58 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
2026-07-03 09:58 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
2026-07-03 09:58 [Edit] /home/steggi/pyramid/lib/widgets/settings_modal.dart
+9
View File
@@ -3,6 +3,15 @@ import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart';
import 'package:pyramid/core/theme.dart';
/// Ob Cross-Signing/Key-Backup fehlt oder nicht entsperrt ist — wenn ja, würde
/// ein Logout den Zugriff auf ältere verschlüsselte Nachrichten kosten.
Future<bool> isKeyBackupMissing(Client client) async {
final enc = client.encryption;
if (enc == null) return true;
if (!enc.crossSigning.enabled) return true;
return !(await enc.keyManager.isCached().catchError((_) => false));
}
Future<void> showBootstrapDialog(
BuildContext context,
Client client, {
+21 -6
View File
@@ -23,6 +23,7 @@ import 'package:pointycastle/export.dart' as pc;
import 'package:pyramid/core/app_state.dart';
import 'package:pyramid/core/auth_log.dart';
import 'package:pyramid/core/e2ee_diagnostics.dart';
import 'package:pyramid/features/auth/bootstrap_dialog.dart' show isKeyBackupMissing;
import 'package:pyramid/core/livekit_call_manager.dart';
import 'package:pyramid/core/matrix_client.dart';
import 'package:pyramid/core/voip_manager.dart';
@@ -567,6 +568,9 @@ class _LogoutNavButtonState extends ConsumerState<_LogoutNavButton> {
Future<void> _logout() async {
final pt = widget.pt;
final client = await ref.read(matrixClientProvider.future);
final backupMissing = await isKeyBackupMissing(client);
if (!mounted) return;
final confirmed = await showDialog<bool>(
context: context,
builder: (ctx) => AlertDialog(
@@ -575,8 +579,14 @@ class _LogoutNavButtonState extends ConsumerState<_LogoutNavButton> {
borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)),
title: Text('Abmelden?',
style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)),
content: Text('Du wirst von diesem Gerät abgemeldet.',
style: TextStyle(color: pt.fgMuted, fontSize: 13)),
content: Text(
backupMissing
? 'Du wirst von diesem Gerät abgemeldet. Es ist kein Schlüssel-Backup eingerichtet — '
'ältere verschlüsselte Nachrichten sind danach auf keinem Gerät mehr lesbar.'
: 'Du wirst von diesem Gerät abgemeldet.',
style: TextStyle(
color: backupMissing ? pt.danger : pt.fgMuted, fontSize: 13, height: 1.4),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx, false),
@@ -596,7 +606,6 @@ class _LogoutNavButtonState extends ConsumerState<_LogoutNavButton> {
setState(() => _loading = true);
try {
widget.onClose();
final client = await ref.read(matrixClientProvider.future);
unawaited(AuthLog.write('User-initiated logout (Settings-Sidebar)'));
await client.logout();
} catch (_) {}
@@ -5108,6 +5117,9 @@ class _AboutSection extends ConsumerWidget {
}
Future<void> _confirmLogout(BuildContext context, WidgetRef ref) async {
final client = await ref.read(matrixClientProvider.future);
final backupMissing = await isKeyBackupMissing(client);
if (!context.mounted) return;
final confirm = await showDialog<bool>(
context: context,
builder: (ctx) => AlertDialog(
@@ -5118,8 +5130,12 @@ class _AboutSection extends ConsumerWidget {
title: Text('Abmelden?',
style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)),
content: Text(
'Du wirst auf diesem Gerät abgemeldet. Deine Nachrichten bleiben erhalten.',
style: TextStyle(color: pt.fgMuted, fontSize: 13),
backupMissing
? 'Du wirst auf diesem Gerät abgemeldet. Es ist kein Schlüssel-Backup eingerichtet — '
'ältere verschlüsselte Nachrichten sind danach auf keinem Gerät mehr lesbar.'
: 'Du wirst auf diesem Gerät abgemeldet. Deine Nachrichten bleiben erhalten.',
style: TextStyle(
color: backupMissing ? pt.danger : pt.fgMuted, fontSize: 13, height: 1.4),
),
actions: [
TextButton(
@@ -5139,7 +5155,6 @@ class _AboutSection extends ConsumerWidget {
),
);
if (confirm == true) {
final client = await ref.read(matrixClientProvider.future);
unawaited(AuthLog.write('User-initiated logout (Settings)'));
await client.logout().catchError((_) {});
}