Shuffle/app/lib/features/auth/data/auth_status_tracker.dart
cschlaefke 54337ffc59 feat(auth): add auth domain, repository, validators and router redirects
Refs #1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 00:09:47 +01:00

47 lines
1.7 KiB
Dart

import 'package:shuffle/features/auth/domain/auth_status.dart';
import 'package:shuffle/features/auth/domain/auth_user.dart';
// `AuthUser` heißt auch in supabase_flutter; hier ist die Domänenklasse gemeint.
import 'package:supabase_flutter/supabase_flutter.dart' hide AuthUser;
/// Bildet `AuthChangeEvent`s auf [AuthStatus] ab (Spec #1 § 5.5).
///
/// Abweichung von der Wortlaut-Zuordnung in § 5.5: Die Recovery bleibt
/// bestehen, bis `userUpdated` (Passwort geändert) oder `signedOut` eintrifft.
/// Ein `tokenRefreshed` oder `signedIn` während der Recovery hebt den Guard
/// nicht auf. Der Zustand lebt nur im Prozess (Spec #1 § 5.4, R12): Aus dem
/// `amr`-Claim lässt er sich nicht ableiten.
class AuthStatusTracker {
bool _recovery = false;
/// Status für [session] unter Berücksichtigung der laufenden Recovery.
AuthStatus statusFor(Session? session) {
final user = session?.user;
if (user == null) {
return const AuthStatus.signedOut();
}
final authUser = AuthUser(
id: user.id,
email: user.email,
emailConfirmed: user.emailConfirmedAt != null,
);
return _recovery
? AuthStatus.passwordRecovery(authUser)
: AuthStatus.signedIn(authUser);
}
/// Verarbeitet ein Ereignis und liefert den neuen Status.
AuthStatus handle(AuthChangeEvent event, Session? session) {
switch (event) {
case AuthChangeEvent.passwordRecovery:
_recovery = session != null;
case AuthChangeEvent.signedOut || AuthChangeEvent.userUpdated:
_recovery = false;
default:
break;
}
if (session == null) {
_recovery = false;
}
return statusFor(session);
}
}