Authentification stable - WIP

This commit is contained in:
DahoudG
2025-09-19 12:35:46 +00:00
parent 63fe107f98
commit 098894bdc1
383 changed files with 13072 additions and 93334 deletions

View File

@@ -1,115 +0,0 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
/// Interceptor pour gérer l'authentification automatique
@singleton
class AuthInterceptor extends Interceptor {
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
// Callback pour déclencher le refresh token
void Function()? onTokenRefreshNeeded;
// Callback pour déconnecter l'utilisateur
void Function()? onAuthenticationFailed;
AuthInterceptor();
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
// Ignorer l'authentification pour certaines routes
if (_shouldSkipAuth(options)) {
handler.next(options);
return;
}
try {
// Récupérer le token d'accès
final accessToken = await _secureStorage.read(key: 'access_token');
if (accessToken != null) {
// Ajouter le token à l'en-tête Authorization
options.headers['Authorization'] = 'Bearer $accessToken';
}
handler.next(options);
} catch (e) {
// En cas d'erreur, continuer sans token
print('Erreur lors de la récupération du token: $e');
handler.next(options);
}
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
// Traitement des réponses réussies
handler.next(response);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) async {
// Gestion des erreurs d'authentification
if (err.response?.statusCode == 401) {
await _handle401Error(err, handler);
} else if (err.response?.statusCode == 403) {
await _handle403Error(err, handler);
} else {
handler.next(err);
}
}
/// Gère les erreurs 401 (Non autorisé)
Future<void> _handle401Error(DioException err, ErrorInterceptorHandler handler) async {
try {
// Déclencher la déconnexion automatique
onAuthenticationFailed?.call();
// Nettoyer les tokens
await _secureStorage.deleteAll();
} catch (e) {
print('Erreur lors de la gestion de l\'erreur 401: $e');
}
handler.next(err);
}
/// Gère les erreurs 403 (Interdit)
Future<void> _handle403Error(DioException err, ErrorInterceptorHandler handler) async {
// L'utilisateur n'a pas les permissions suffisantes
// On peut logger cela ou rediriger vers une page d'erreur
print('Accès interdit (403) pour: ${err.requestOptions.path}');
handler.next(err);
}
/// Détermine si l'authentification doit être ignorée pour une requête
bool _shouldSkipAuth(RequestOptions options) {
// Ignorer l'auth pour les routes publiques
final publicPaths = [
'/api/auth/login',
'/api/auth/refresh',
'/api/auth/info',
'/api/auth/register',
'/api/health',
];
// Vérifier si le path est dans la liste des routes publiques
final isPublicPath = publicPaths.any((path) => options.path.contains(path));
// Vérifier si l'option skipAuth est activée
final skipAuth = options.extra['skipAuth'] == true;
return isPublicPath || skipAuth;
}
/// Configuration des callbacks
void setCallbacks({
void Function()? onTokenRefreshNeeded,
void Function()? onAuthenticationFailed,
}) {
this.onTokenRefreshNeeded = onTokenRefreshNeeded;
this.onAuthenticationFailed = onAuthenticationFailed;
}
}

View File

@@ -1,113 +0,0 @@
import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import 'auth_interceptor.dart';
/// Configuration centralisée du client HTTP Dio
@singleton
class DioClient {
late final Dio _dio;
DioClient() {
_dio = Dio();
_setupInterceptors();
_configureOptions();
}
Dio get dio => _dio;
void _configureOptions() {
_dio.options = BaseOptions(
// URL de base de l'API
baseUrl: 'http://192.168.1.11:8080', // Adresse de votre API Quarkus
// Timeouts
connectTimeout: const Duration(seconds: 30),
receiveTimeout: const Duration(seconds: 30),
sendTimeout: const Duration(seconds: 30),
// Headers par défaut
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'UnionFlow-Mobile/1.0.0',
},
// Validation des codes de statut
validateStatus: (status) {
return status != null && status < 500;
},
// Suivre les redirections
followRedirects: true,
maxRedirects: 3,
// Politique de persistance des cookies
persistentConnection: true,
// Format de réponse par défaut
responseType: ResponseType.json,
);
}
void _setupInterceptors() {
// Interceptor de logging (seulement en debug)
_dio.interceptors.add(
PrettyDioLogger(
requestHeader: true,
requestBody: true,
responseBody: true,
responseHeader: false,
error: true,
compact: true,
maxWidth: 90,
filter: (options, args) {
// Ne pas logger les mots de passe
if (options.path.contains('/auth/login')) {
return false;
}
return true;
},
),
);
// Interceptor d'authentification (sera injecté plus tard)
// Il sera ajouté dans AuthService pour éviter les dépendances circulaires
}
/// Ajoute l'interceptor d'authentification
void addAuthInterceptor(AuthInterceptor authInterceptor) {
_dio.interceptors.add(authInterceptor);
}
/// Configure l'URL de base
void setBaseUrl(String baseUrl) {
_dio.options.baseUrl = baseUrl;
}
/// Ajoute un header global
void addHeader(String key, String value) {
_dio.options.headers[key] = value;
}
/// Supprime un header global
void removeHeader(String key) {
_dio.options.headers.remove(key);
}
/// Configure les timeouts
void setTimeout({
Duration? connect,
Duration? receive,
Duration? send,
}) {
if (connect != null) _dio.options.connectTimeout = connect;
if (receive != null) _dio.options.receiveTimeout = receive;
if (send != null) _dio.options.sendTimeout = send;
}
/// Nettoie et ferme le client
void dispose() {
_dio.close();
}
}