import 'dart:developer'; import '../../../session/session.dart'; import '../../../session/session_lifecycle.dart'; import '../../../session/session_manager.dart'; import '../../errors/auth_exception.dart'; import '../queries/auth_me/auth_me.dart'; import '../queries/auth_verify/auth_verify.dart'; /// Credential probe. For password accounts a server-side password rotation /// forces a re-login on the next cold start even when the bearer token would /// still be accepted; for guardians it confirms a rejected token before the /// session is dropped. class SessionValidator { static Future probeStored({ required Future Function() onInvalidated, }) async { final session = SessionManager().current; // The probes use their own dio (bypassing the demo interceptor), so a demo // session must be skipped or its missing token would 401 into a logout. if (session == null || session.isDemo) return; try { switch (session) { case CredentialSession(:final username, :final password): await AuthVerify().run(username: username, password: password); case GuardianSession(): await AuthMe().run(); } } on AuthException catch (e) { if (e.statusCode != 401) return; log('MC: stored session rejected — forcing re-login'); await SessionLifecycle.signOut( notice: switch (session) { CredentialSession() => 'Deine Zugangsdaten wurden vom Server abgelehnt. Vermutlich ' 'wurde dein Passwort geändert. Bitte melde dich erneut an.', GuardianSession() => 'Deine Anmeldung ist abgelaufen. Bitte melde dich erneut an.', }, ); await onInvalidated(); } catch (e) { log('MC: background session check failed (transient): $e'); } } }