ForgotPasswordScreen with neutral reaction (F12), CheckEmail reset mode on its own path, recovery link handling and ResetPasswordScreen with the recovery guard held until the user confirms the success message. Carries the from parameter between login, register and forgot password. Removes the route placeholders. Refs #1 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
72 lines
2.4 KiB
Dart
72 lines
2.4 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 [finishRecovery] oder `signedOut` eintrifft. Ein
|
|
/// `tokenRefreshed` oder `signedIn` während der Recovery hebt den Guard nicht
|
|
/// auf. `userUpdated` (Passwort geändert) beendet ihn ebenfalls **nicht**
|
|
/// mehr, sondern setzt nur `passwordChanged`: Sonst würde der Router den
|
|
/// Nutzer von `/reset-password` wegleiten, bevor die Erfolgsmeldung
|
|
/// (KTO-01 Kriterium 9) zu sehen ist. Erst die ausdrückliche Bestätigung des
|
|
/// Nutzers beendet den Guard. 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;
|
|
bool _passwordChanged = 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,
|
|
passwordChanged: _passwordChanged,
|
|
)
|
|
: 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;
|
|
_passwordChanged = false;
|
|
case AuthChangeEvent.userUpdated:
|
|
// The password change itself: stay in the guard (see class doc).
|
|
if (_recovery) {
|
|
_passwordChanged = true;
|
|
}
|
|
case AuthChangeEvent.signedOut:
|
|
_end();
|
|
default:
|
|
break;
|
|
}
|
|
if (session == null) {
|
|
_end();
|
|
}
|
|
return statusFor(session);
|
|
}
|
|
|
|
/// Ends the recovery after the user confirmed the success message.
|
|
AuthStatus finishRecovery(Session? session) {
|
|
_end();
|
|
return statusFor(session);
|
|
}
|
|
|
|
void _end() {
|
|
_recovery = false;
|
|
_passwordChanged = false;
|
|
}
|
|
}
|