first commit

This commit is contained in:
DahoudG
2025-08-20 21:00:35 +00:00
commit b2a23bdf89
583 changed files with 243074 additions and 0 deletions

View File

@@ -0,0 +1,203 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import '../models/auth_state.dart';
import '../services/auth_service.dart';
import '../services/auth_api_service.dart';
import 'auth_event.dart';
/// BLoC pour gérer l'authentification
@singleton
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final AuthService _authService;
late StreamSubscription<AuthState> _authStateSubscription;
AuthBloc(this._authService) : super(const AuthState.unknown()) {
// Écouter les changements d'état du service
_authStateSubscription = _authService.authStateStream.listen(
(authState) => add(AuthStateChanged(authState)),
);
// Gestionnaires d'événements
on<AuthInitializeRequested>(_onInitializeRequested);
on<AuthLoginRequested>(_onLoginRequested);
on<AuthLogoutRequested>(_onLogoutRequested);
on<AuthTokenRefreshRequested>(_onTokenRefreshRequested);
on<AuthSessionExpired>(_onSessionExpired);
on<AuthStatusCheckRequested>(_onStatusCheckRequested);
on<AuthErrorCleared>(_onErrorCleared);
on<AuthStateChanged>(_onStateChanged);
}
/// Initialisation de l'authentification
Future<void> _onInitializeRequested(
AuthInitializeRequested event,
Emitter<AuthState> emit,
) async {
emit(const AuthState.checking());
try {
await _authService.initialize();
} catch (e) {
emit(AuthState.error('Erreur d\'initialisation: $e'));
}
}
/// Gestion de la connexion
Future<void> _onLoginRequested(
AuthLoginRequested event,
Emitter<AuthState> emit,
) async {
emit(state.copyWith(isLoading: true, errorMessage: null));
try {
await _authService.login(event.loginRequest);
// L'état sera mis à jour par le stream du service
} on AuthApiException catch (e) {
emit(state.copyWith(
isLoading: false,
errorMessage: e.message,
));
} catch (e) {
emit(state.copyWith(
isLoading: false,
errorMessage: 'Erreur de connexion: $e',
));
}
}
/// Gestion de la déconnexion
Future<void> _onLogoutRequested(
AuthLogoutRequested event,
Emitter<AuthState> emit,
) async {
emit(state.copyWith(isLoading: true));
try {
await _authService.logout();
// L'état sera mis à jour par le stream du service
} catch (e) {
// Même en cas d'erreur, on considère que la déconnexion locale a réussi
emit(const AuthState.unauthenticated());
}
}
/// Gestion du rafraîchissement de token
Future<void> _onTokenRefreshRequested(
AuthTokenRefreshRequested event,
Emitter<AuthState> emit,
) async {
// Le rafraîchissement est géré automatiquement par le service
// Cet événement peut être utilisé pour forcer un rafraîchissement manuel
try {
// Le service gère déjà le rafraîchissement automatique
// On peut ajouter ici une logique spécifique si nécessaire
} catch (e) {
emit(AuthState.error('Erreur lors du rafraîchissement: $e'));
}
}
/// Gestion de l'expiration de session
Future<void> _onSessionExpired(
AuthSessionExpired event,
Emitter<AuthState> emit,
) async {
emit(const AuthState.expired());
// Optionnel: essayer un rafraîchissement automatique
try {
await _authService.logout();
} catch (e) {
// Ignorer les erreurs de déconnexion lors de l'expiration
}
}
/// Vérification du statut d'authentification
Future<void> _onStatusCheckRequested(
AuthStatusCheckRequested event,
Emitter<AuthState> emit,
) async {
// Utiliser l'état actuel du service
final currentServiceState = _authService.currentState;
if (currentServiceState != state) {
emit(currentServiceState);
}
}
/// Nettoyage des erreurs
void _onErrorCleared(
AuthErrorCleared event,
Emitter<AuthState> emit,
) {
if (state.errorMessage != null) {
emit(state.copyWith(errorMessage: null));
}
}
/// Mise à jour depuis le service d'authentification
void _onStateChanged(
AuthStateChanged event,
Emitter<AuthState> emit,
) {
final newState = event.authState as AuthState;
// Émettre le nouvel état seulement s'il a changé
if (newState != state) {
emit(newState);
}
}
/// Vérifie si l'utilisateur est connecté
bool get isAuthenticated => state.isAuthenticated;
/// Récupère l'utilisateur actuel
get currentUser => state.user;
/// Vérifie si l'utilisateur a un rôle spécifique
bool hasRole(String role) {
return _authService.hasRole(role);
}
/// Vérifie si l'utilisateur a un des rôles spécifiés
bool hasAnyRole(List<String> roles) {
return _authService.hasAnyRole(roles);
}
/// Vérifie si la session expire bientôt
bool get isSessionExpiringSoon => state.isExpiringSoon;
/// Récupère le message d'erreur formaté
String? get errorMessage {
final error = state.errorMessage;
if (error == null) return null;
// Formatage des messages d'erreur pour l'utilisateur
if (error.contains('network') || error.contains('connexion')) {
return 'Problème de connexion. Vérifiez votre réseau.';
}
if (error.contains('401') || error.contains('Identifiants')) {
return 'Email ou mot de passe incorrect.';
}
if (error.contains('403')) {
return 'Accès non autorisé.';
}
if (error.contains('timeout')) {
return 'Délai d\'attente dépassé. Réessayez.';
}
if (error.contains('server') || error.contains('500')) {
return 'Erreur serveur temporaire. Réessayez plus tard.';
}
return error;
}
@override
Future<void> close() {
_authStateSubscription.cancel();
return super.close();
}
}

View File

@@ -0,0 +1,60 @@
import 'package:equatable/equatable.dart';
import '../models/login_request.dart';
/// Événements d'authentification
abstract class AuthEvent extends Equatable {
const AuthEvent();
@override
List<Object?> get props => [];
}
/// Initialiser l'authentification
class AuthInitializeRequested extends AuthEvent {
const AuthInitializeRequested();
}
/// Demande de connexion
class AuthLoginRequested extends AuthEvent {
final LoginRequest loginRequest;
const AuthLoginRequested(this.loginRequest);
@override
List<Object> get props => [loginRequest];
}
/// Demande de déconnexion
class AuthLogoutRequested extends AuthEvent {
const AuthLogoutRequested();
}
/// Demande de rafraîchissement de token
class AuthTokenRefreshRequested extends AuthEvent {
const AuthTokenRefreshRequested();
}
/// Session expirée
class AuthSessionExpired extends AuthEvent {
const AuthSessionExpired();
}
/// Vérification de l'état d'authentification
class AuthStatusCheckRequested extends AuthEvent {
const AuthStatusCheckRequested();
}
/// Réinitialisation de l'erreur
class AuthErrorCleared extends AuthEvent {
const AuthErrorCleared();
}
/// Changement d'état depuis le service
class AuthStateChanged extends AuthEvent {
final dynamic authState;
const AuthStateChanged(this.authState);
@override
List<Object?> get props => [authState];
}

View File

@@ -0,0 +1,74 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../models/auth_state.dart';
import '../services/temp_auth_service.dart';
import 'auth_event.dart';
/// BLoC temporaire pour test sans injection de dépendances
class TempAuthBloc extends Bloc<AuthEvent, AuthState> {
final TempAuthService _authService;
late StreamSubscription<AuthState> _authStateSubscription;
TempAuthBloc(this._authService) : super(const AuthState.unknown()) {
_authStateSubscription = _authService.authStateStream.listen(
(authState) => add(AuthStateChanged(authState)),
);
on<AuthInitializeRequested>(_onInitializeRequested);
on<AuthLoginRequested>(_onLoginRequested);
on<AuthLogoutRequested>(_onLogoutRequested);
on<AuthErrorCleared>(_onErrorCleared);
on<AuthStateChanged>(_onStateChanged);
}
Future<void> _onInitializeRequested(
AuthInitializeRequested event,
Emitter<AuthState> emit,
) async {
await _authService.initialize();
}
Future<void> _onLoginRequested(
AuthLoginRequested event,
Emitter<AuthState> emit,
) async {
try {
await _authService.login(event.loginRequest);
} catch (e) {
emit(AuthState.error(e.toString()));
}
}
Future<void> _onLogoutRequested(
AuthLogoutRequested event,
Emitter<AuthState> emit,
) async {
await _authService.logout();
}
void _onErrorCleared(
AuthErrorCleared event,
Emitter<AuthState> emit,
) {
if (state.errorMessage != null) {
emit(state.copyWith(errorMessage: null));
}
}
void _onStateChanged(
AuthStateChanged event,
Emitter<AuthState> emit,
) {
final newState = event.authState as AuthState;
if (newState != state) {
emit(newState);
}
}
@override
Future<void> close() {
_authStateSubscription.cancel();
_authService.dispose();
return super.close();
}
}