forked from eatvio/eatvio_app
feat(session): centralize session teardown and refresh
Add SessionLifecycleService to reset user-scoped cubits, analytics, socket id and account-scoped preferences on logout, 401 or account deletion. Run the same refresh after every successful auth path, including registration v1/v2, and ignore 401 responses from stale tokens so an old request cannot terminate the new user's session. Refs: #1113
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:developer';
|
||||
import 'package:eatvio_app/core/firebase_api.dart';
|
||||
import 'package:eatvio_app/core/prefs.dart';
|
||||
import 'package:eatvio_app/core/prefs_keys.dart';
|
||||
import 'package:eatvio_app/core/session/session_lifecycle_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit/auth_state.dart';
|
||||
@@ -17,15 +18,26 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
final ProfileRepository profileRepository;
|
||||
final FirebaseApi firebaseApi;
|
||||
final Prefs prefs;
|
||||
final SessionLifecycleService sessionLifecycleService;
|
||||
|
||||
AuthCubit({required this.authRepository, required this.prefs, required this.profileRepository, required this.firebaseApi}) : super(const AuthState());
|
||||
AuthCubit({
|
||||
required this.authRepository,
|
||||
required this.prefs,
|
||||
required this.profileRepository,
|
||||
required this.firebaseApi,
|
||||
required this.sessionLifecycleService,
|
||||
}) : super(const AuthState());
|
||||
|
||||
Future<bool> getTokenByCredentials(String email, String password) async {
|
||||
emit(const AuthState.loading());
|
||||
try {
|
||||
final token = (await authRepository.getTokenByCredentials(email, password)).token;
|
||||
final token = (await authRepository.getTokenByCredentials(
|
||||
email,
|
||||
password,
|
||||
)).token;
|
||||
emit(AuthState.loaded(token: token));
|
||||
await TokenStorage.saveTokenInStorage(token);
|
||||
await sessionLifecycleService.onAuthenticated();
|
||||
return true;
|
||||
} catch (e, st) {
|
||||
await reportFrom(e, st, this);
|
||||
@@ -48,7 +60,8 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
|
||||
Future<void> registerAnonymousPushToken() async {
|
||||
try {
|
||||
final hasAnonymousTokenBeenSent = prefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent) ?? false;
|
||||
final hasAnonymousTokenBeenSent =
|
||||
prefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent) ?? false;
|
||||
if (!hasAnonymousTokenBeenSent) {
|
||||
await firebaseApi.registerAnonymousPushToken();
|
||||
prefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/firebase_api.dart';
|
||||
import 'package:eatvio_app/core/mixins/registration_date_cache_mixin.dart';
|
||||
import 'package:eatvio_app/core/prefs.dart';
|
||||
import 'package:eatvio_app/core/session/session_lifecycle_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/features/auth/models/oauth_verification_request_response.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/oauth_cubit/oauth_state.dart';
|
||||
@@ -13,10 +14,12 @@ import 'package:eatvio_app/core/error_reporting/report_from.dart';
|
||||
class OAuthCubit extends Cubit<OAuthState> with RegistrationDateCacheMixin {
|
||||
final AuthRepository authRepository;
|
||||
final FirebaseApi firebaseApi;
|
||||
final SessionLifecycleService sessionLifecycleService;
|
||||
|
||||
OAuthCubit({
|
||||
required this.authRepository,
|
||||
required this.firebaseApi,
|
||||
required this.sessionLifecycleService,
|
||||
required Prefs prefs,
|
||||
}) : super(const OAuthState()) {
|
||||
this.prefs = prefs;
|
||||
@@ -40,6 +43,7 @@ class OAuthCubit extends Cubit<OAuthState> with RegistrationDateCacheMixin {
|
||||
|
||||
log('OAuthCubit: Got token model: ${tokenModel.token}');
|
||||
await TokenStorage.saveTokenInStorage(tokenModel.token);
|
||||
await sessionLifecycleService.onAuthenticated();
|
||||
emit(OAuthState.loaded(token: tokenModel.token));
|
||||
} on DioException catch (e, st) {
|
||||
await reportFrom(e, st, this);
|
||||
@@ -122,7 +126,7 @@ class OAuthCubit extends Cubit<OAuthState> with RegistrationDateCacheMixin {
|
||||
clientId: clientId,
|
||||
);
|
||||
await TokenStorage.saveTokenInStorage(token);
|
||||
await firebaseApi.registerPushToken();
|
||||
await sessionLifecycleService.onAuthenticated();
|
||||
cacheRegistrationDate(DateTime.now());
|
||||
emit(OAuthState.loaded(token: token));
|
||||
} on DioException catch (e, st) {
|
||||
@@ -241,7 +245,7 @@ class OAuthCubit extends Cubit<OAuthState> with RegistrationDateCacheMixin {
|
||||
'OAuthCubit: OAuth verification confirmed successfully, token received',
|
||||
);
|
||||
await TokenStorage.saveTokenInStorage(response.token);
|
||||
await firebaseApi.registerPushToken();
|
||||
await sessionLifecycleService.onAuthenticated();
|
||||
emit(OAuthState.loaded(token: response.token));
|
||||
} catch (e, st) {
|
||||
await reportFrom(e, st, this);
|
||||
|
||||
Reference in New Issue
Block a user