feat(mobile): Implement Keycloak WebView authentication with HTTP callback
- Replace flutter_appauth with custom WebView implementation to resolve deep link issues - Add KeycloakWebViewAuthService with integrated WebView for seamless authentication - Configure Android manifest for HTTP cleartext traffic support - Add network security config for development environment (192.168.1.11) - Update Keycloak client to use HTTP callback endpoint (http://192.168.1.11:8080/auth/callback) - Remove obsolete keycloak_auth_service.dart and temporary scripts - Clean up dependencies and regenerate injection configuration - Tested successfully on multiple Android devices (Xiaomi 2201116TG, SM A725F) BREAKING CHANGE: Authentication flow now uses WebView instead of external browser - Users will see Keycloak login page within the app instead of browser redirect - Resolves ERR_CLEARTEXT_NOT_PERMITTED and deep link state management issues - Maintains full OIDC compliance with PKCE flow and secure token storage Technical improvements: - WebView with custom navigation delegate for callback handling - Automatic token extraction and user info parsing from JWT - Proper error handling and user feedback - Consistent authentication state management across app lifecycle
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import '../../../../core/models/evenement_model.dart';
|
||||
|
||||
/// Événements du BLoC Evenement
|
||||
abstract class EvenementEvent extends Equatable {
|
||||
const EvenementEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Charge les événements à venir
|
||||
class LoadEvenementsAVenir extends EvenementEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
final bool refresh;
|
||||
|
||||
const LoadEvenementsAVenir({
|
||||
this.page = 0,
|
||||
this.size = 10,
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size, refresh];
|
||||
}
|
||||
|
||||
/// Charge les événements publics
|
||||
class LoadEvenementsPublics extends EvenementEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
final bool refresh;
|
||||
|
||||
const LoadEvenementsPublics({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size, refresh];
|
||||
}
|
||||
|
||||
/// Charge tous les événements
|
||||
class LoadEvenements extends EvenementEvent {
|
||||
final int page;
|
||||
final int size;
|
||||
final String sortField;
|
||||
final String sortDirection;
|
||||
final bool refresh;
|
||||
|
||||
const LoadEvenements({
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.sortField = 'dateDebut',
|
||||
this.sortDirection = 'asc',
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [page, size, sortField, sortDirection, refresh];
|
||||
}
|
||||
|
||||
/// Charge un événement par ID
|
||||
class LoadEvenementById extends EvenementEvent {
|
||||
final String id;
|
||||
|
||||
const LoadEvenementById(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Recherche d'événements
|
||||
class SearchEvenements extends EvenementEvent {
|
||||
final String terme;
|
||||
final int page;
|
||||
final int size;
|
||||
final bool refresh;
|
||||
|
||||
const SearchEvenements({
|
||||
required this.terme,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [terme, page, size, refresh];
|
||||
}
|
||||
|
||||
/// Filtre par type d'événement
|
||||
class FilterEvenementsByType extends EvenementEvent {
|
||||
final TypeEvenement type;
|
||||
final int page;
|
||||
final int size;
|
||||
final bool refresh;
|
||||
|
||||
const FilterEvenementsByType({
|
||||
required this.type,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.refresh = false,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [type, page, size, refresh];
|
||||
}
|
||||
|
||||
/// Crée un nouvel événement
|
||||
class CreateEvenement extends EvenementEvent {
|
||||
final EvenementModel evenement;
|
||||
|
||||
const CreateEvenement(this.evenement);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [evenement];
|
||||
}
|
||||
|
||||
/// Met à jour un événement
|
||||
class UpdateEvenement extends EvenementEvent {
|
||||
final String id;
|
||||
final EvenementModel evenement;
|
||||
|
||||
const UpdateEvenement(this.id, this.evenement);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, evenement];
|
||||
}
|
||||
|
||||
/// Supprime un événement
|
||||
class DeleteEvenement extends EvenementEvent {
|
||||
final String id;
|
||||
|
||||
const DeleteEvenement(this.id);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id];
|
||||
}
|
||||
|
||||
/// Change le statut d'un événement
|
||||
class ChangeStatutEvenement extends EvenementEvent {
|
||||
final String id;
|
||||
final StatutEvenement nouveauStatut;
|
||||
|
||||
const ChangeStatutEvenement(this.id, this.nouveauStatut);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, nouveauStatut];
|
||||
}
|
||||
|
||||
/// Charge les statistiques
|
||||
class LoadStatistiquesEvenements extends EvenementEvent {
|
||||
const LoadStatistiquesEvenements();
|
||||
}
|
||||
|
||||
/// Réinitialise l'état
|
||||
class ResetEvenementState extends EvenementEvent {
|
||||
const ResetEvenementState();
|
||||
}
|
||||
Reference in New Issue
Block a user