Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts). Signed-off-by: lions dev Team
This commit is contained in:
139
lib/features/authentication/presentation/bloc/auth_bloc.dart
Normal file
139
lib/features/authentication/presentation/bloc/auth_bloc.dart
Normal file
@@ -0,0 +1,139 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import '../../data/models/user.dart';
|
||||
import '../../data/models/user_role.dart';
|
||||
import '../../data/datasources/keycloak_auth_service.dart';
|
||||
import '../../data/datasources/permission_engine.dart';
|
||||
import '../../../../core/storage/dashboard_cache_manager.dart';
|
||||
|
||||
// === ÉVÉNEMENTS ===
|
||||
abstract class AuthEvent extends Equatable {
|
||||
const AuthEvent();
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class AuthLoginRequested extends AuthEvent {
|
||||
final String email;
|
||||
final String password;
|
||||
const AuthLoginRequested(this.email, this.password);
|
||||
@override
|
||||
List<Object?> get props => [email, password];
|
||||
}
|
||||
|
||||
class AuthLogoutRequested extends AuthEvent { const AuthLogoutRequested(); }
|
||||
class AuthStatusChecked extends AuthEvent { const AuthStatusChecked(); }
|
||||
class AuthTokenRefreshRequested extends AuthEvent { const AuthTokenRefreshRequested(); }
|
||||
|
||||
// === ÉTATS ===
|
||||
abstract class AuthState extends Equatable {
|
||||
const AuthState();
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class AuthInitial extends AuthState {}
|
||||
class AuthLoading extends AuthState {}
|
||||
class AuthUnauthenticated extends AuthState {}
|
||||
|
||||
class AuthAuthenticated extends AuthState {
|
||||
final User user;
|
||||
final UserRole effectiveRole;
|
||||
final List<String> effectivePermissions;
|
||||
final String accessToken;
|
||||
|
||||
const AuthAuthenticated({
|
||||
required this.user,
|
||||
required this.effectiveRole,
|
||||
required this.effectivePermissions,
|
||||
required this.accessToken,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [user, effectiveRole, effectivePermissions, accessToken];
|
||||
}
|
||||
|
||||
class AuthError extends AuthState {
|
||||
final String message;
|
||||
const AuthError(this.message);
|
||||
@override
|
||||
List<Object?> get props => [message];
|
||||
}
|
||||
|
||||
// === BLOC ===
|
||||
@lazySingleton
|
||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
final KeycloakAuthService _authService;
|
||||
|
||||
AuthBloc(this._authService) : super(AuthInitial()) {
|
||||
on<AuthLoginRequested>(_onLoginRequested);
|
||||
on<AuthLogoutRequested>(_onLogoutRequested);
|
||||
on<AuthStatusChecked>(_onStatusChecked);
|
||||
on<AuthTokenRefreshRequested>(_onTokenRefreshRequested);
|
||||
}
|
||||
|
||||
Future<void> _onLoginRequested(AuthLoginRequested event, Emitter<AuthState> emit) async {
|
||||
emit(AuthLoading());
|
||||
try {
|
||||
final user = await _authService.login(event.email, event.password);
|
||||
if (user != null) {
|
||||
final permissions = await PermissionEngine.getEffectivePermissions(user);
|
||||
final token = await _authService.getValidToken();
|
||||
await DashboardCacheManager.invalidateForRole(user.primaryRole);
|
||||
|
||||
emit(AuthAuthenticated(
|
||||
user: user,
|
||||
effectiveRole: user.primaryRole,
|
||||
effectivePermissions: permissions,
|
||||
accessToken: token ?? '',
|
||||
));
|
||||
} else {
|
||||
emit(const AuthError('Identifiants incorrects.'));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(AuthError('Erreur de connexion: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLogoutRequested(AuthLogoutRequested event, Emitter<AuthState> emit) async {
|
||||
emit(AuthLoading());
|
||||
await _authService.logout();
|
||||
await DashboardCacheManager.clear();
|
||||
emit(AuthUnauthenticated());
|
||||
}
|
||||
|
||||
Future<void> _onStatusChecked(AuthStatusChecked event, Emitter<AuthState> emit) async {
|
||||
final tokenValid = await _authService.getValidToken();
|
||||
final isAuth = tokenValid != null;
|
||||
if (!isAuth) {
|
||||
emit(AuthUnauthenticated());
|
||||
return;
|
||||
}
|
||||
final user = await _authService.getCurrentUser();
|
||||
if (user == null) {
|
||||
emit(AuthUnauthenticated());
|
||||
return;
|
||||
}
|
||||
final permissions = await PermissionEngine.getEffectivePermissions(user);
|
||||
final token = await _authService.getValidToken();
|
||||
emit(AuthAuthenticated(
|
||||
user: user,
|
||||
effectiveRole: user.primaryRole,
|
||||
effectivePermissions: permissions,
|
||||
accessToken: token ?? '',
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> _onTokenRefreshRequested(AuthTokenRefreshRequested event, Emitter<AuthState> emit) async {
|
||||
if (state is AuthAuthenticated) {
|
||||
final newToken = await _authService.refreshToken();
|
||||
final success = newToken != null;
|
||||
if (success) {
|
||||
add(AuthStatusChecked());
|
||||
} else {
|
||||
add(AuthLogoutRequested());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user