fix(mobile): URL changement mdp corrigée + v3.0 — multi-org, AppAuth, sécurité prod

Auth:
- profile_repository.dart: /api/auth/change-password → /api/membres/auth/change-password

Multi-org (Phase 3):
- OrgSelectorPage, OrgSwitcherBloc, OrgSwitcherEntry
- org_context_service.dart: headers X-Active-Organisation-Id + X-Active-Role

Navigation:
- MorePage: navigation conditionnelle par typeOrganisation
- Suppression adaptive_navigation (remplacé par main_navigation_layout)

Auth AppAuth:
- keycloak_webview_auth_service: fixes AppAuth Android
- AuthBloc: gestion REAUTH_REQUIS + premierLoginComplet

Onboarding:
- Nouveaux états: payment_method_page, onboarding_shared_widgets
- SouscriptionStatusModel mis à jour StatutValidationSouscription

Android:
- build.gradle: ProGuard/R8, network_security_config
- Gradle wrapper mis à jour
This commit is contained in:
dahoud
2026-04-07 20:56:03 +00:00
parent 22f9c7e9a1
commit 70cbd1c873
63 changed files with 9316 additions and 6122 deletions

View File

@@ -14,6 +14,7 @@ import 'package:unionflow_mobile_apps/features/members/domain/usecases/delete_me
import 'package:unionflow_mobile_apps/features/members/domain/usecases/search_members.dart';
import 'package:unionflow_mobile_apps/features/members/domain/usecases/get_member_stats.dart';
import 'package:unionflow_mobile_apps/features/members/domain/repositories/membre_repository.dart';
import 'package:unionflow_mobile_apps/features/members/data/models/membre_complete_model.dart';
import 'package:unionflow_mobile_apps/shared/models/membre_search_result.dart';
import 'package:unionflow_mobile_apps/shared/models/membre_search_criteria.dart';
@@ -292,6 +293,53 @@ void main() {
// MembresLoaded.copyWith
// ─────────────────────────────────────────────────────────────────────────
// ─────────────────────────────────────────────────────────────────────────
// ResetMotDePasse
// ─────────────────────────────────────────────────────────────────────────
group('ResetMotDePasse', () {
MembreCompletModel membreAvecPassword() => MembreCompletModel(
id: 'membre-id-1',
prenom: 'Jean',
nom: 'Dupont',
email: 'jean.dupont@test.com',
motDePasseTemporaire: 'NewP@ss1234',
);
blocTest<MembresBloc, MembresState>(
'émet [MembresLoading, MotDePasseReinitialise] en cas de succès',
build: () {
when(mockRepository.resetMotDePasse('membre-id-1'))
.thenAnswer((_) async => membreAvecPassword());
return bloc;
},
act: (b) => b.add(const ResetMotDePasse('membre-id-1')),
expect: () => [
const MembresLoading(),
isA<MotDePasseReinitialise>()
.having((s) => s.membre.id, 'id', 'membre-id-1')
.having((s) => s.membre.motDePasseTemporaire, 'password', 'NewP@ss1234'),
],
verify: (_) {
verify(mockRepository.resetMotDePasse('membre-id-1')).called(1);
},
);
blocTest<MembresBloc, MembresState>(
'émet [MembresLoading, MembresError] si le repository lève une exception',
build: () {
when(mockRepository.resetMotDePasse('membre-id-1'))
.thenThrow(Exception('Membre sans compte Keycloak'));
return bloc;
},
act: (b) => b.add(const ResetMotDePasse('membre-id-1')),
expect: () => [
const MembresLoading(),
isA<MembresError>(),
],
);
});
group('MembresLoaded.copyWith', () {
test('preserve organisationId si non fourni', () {
const state = MembresLoaded(