# đŸ€– Document de Passation - lions-user-manager **Date**: 2025-01-09 **Agent PrĂ©cĂ©dent**: Claude Code **Version Projet**: 1.0.0 **Statut Global**: 🟡 60% complĂ©tĂ© - EN COURS --- ## 📋 RÉSUMÉ EXÉCUTIF Le projet **lions-user-manager** est un module de gestion centralisĂ©e des utilisateurs Keycloak avec architecture multi-modules Maven. Le projet est **fonctionnel Ă  60%** avec des erreurs de compilation Ă  corriger avant de pouvoir compiler complĂštement. ### Contrainte CRITIQUE ⚠ **ZÉRO accĂšs direct Ă  la base de donnĂ©es Keycloak**. Toutes les opĂ©rations DOIVENT passer par l'API Admin REST de Keycloak uniquement. --- ## đŸ—‚ïž STRUCTURE DU PROJET ### Localisation ``` C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\ ├── lions-user-manager-server-api/ ✅ 100% complĂ©tĂ© ├── lions-user-manager-server-impl-quarkus/ 🔄 70% complĂ©tĂ© (avec erreurs) ├── lions-user-manager-client-quarkus-primefaces-freya/ ⏳ 0% (POM seulement) └── pom.xml (parent) ``` ### Repositories Git (Structure corrigĂ©e) 1. **Repo principal**: https://git.lions.dev/lionsdev/lions-user-manager.git - Contient: TOUT le projet (parent + 3 modules) 2. **Repo module API**: https://git.lions.dev/lionsdev/lions-user-manager-server-api.git - Contient: UNIQUEMENT le dossier lions-user-manager-server-api/ 3. **Repo module Server**: https://git.lions.dev/lionsdev/lions-user-manager-server-impl-quarkus.git - Contient: UNIQUEMENT le dossier lions-user-manager-server-impl-quarkus/ 4. **Repo module Client**: https://git.lions.dev/lionsdev/lions-user-manager-client-quarkus-primefaces-freya.git - Contient: UNIQUEMENT le dossier lions-user-manager-client-quarkus-primefaces-freya/ **Credentials Git**: lionsdev / lions@2025 (encoder @ en %40 dans les URLs) --- ## ✅ CE QUI EST COMPLÉTÉ ### Module 1: server-api (100% ✅) **Localisation**: `lions-user-manager-server-api/` **15 fichiers créés**: #### DTOs (7 fichiers) - `BaseDTO.java` - Classe de base avec id, dates, audit - `UserDTO.java` - DTO utilisateur complet (60+ champs) - Champs importants: username, email, firstName, lastName, enabled, statut - `UserSearchCriteriaDTO.java` - CritĂšres de recherche avancĂ©s - `UserSearchResultDTO.java` - RĂ©sultats paginĂ©s - `RoleDTO.java` - DTO rĂŽle - **ATTENTION**: Le champ s'appelle `name` (pas `nom`) - Champs: name, description, typeRole, composite, containerId, clientId - `RoleAssignmentDTO.java` - Attribution/rĂ©vocation de rĂŽles - `AuditLogDTO.java` - Logs d'audit dĂ©taillĂ©s #### Enums (3 fichiers) - `StatutUser.java` - 7 statuts (ACTIF, INACTIF, SUSPENDU, etc.) - `TypeRole.java` - Types de rĂŽles (REALM_ROLE, CLIENT_ROLE, COMPOSITE_ROLE) - `TypeActionAudit.java` - 30+ types d'actions pour audit trail #### Services Interfaces (4 fichiers) - `UserService.java` - 25+ mĂ©thodes de gestion utilisateurs ✅ INTERFACE COMPLÈTE - `RoleService.java` - Interface pour gestion rĂŽles - `AuditService.java` - Interface pour audit logging - `SyncService.java` - Interface synchronisation avec Keycloak #### Validation - `ValidationConstants.java` - Constantes centralisĂ©es **Statut**: CompilĂ© et installĂ© dans Maven local avec succĂšs ✅ --- ### Module 2: server-impl-quarkus (70% 🔄 AVEC ERREURS) **Localisation**: `lions-user-manager-server-impl-quarkus/` **14 fichiers créés**: #### Configuration (3 fichiers) ✅ - `application.properties` - Configuration de base - `application-dev.properties` - Config dĂ©veloppement - Keycloak: http://localhost:8180 - Logging: DEBUG - CORS permissif - `application-prod.properties` - Config production - Keycloak: https://security.lions.dev - SSL/TLS requis - Audit DB obligatoire - MĂ©triques Prometheus #### Client Keycloak (2 fichiers) ✅ - `KeycloakAdminClient.java` - Interface - `KeycloakAdminClientImpl.java` - ImplĂ©mentation - ✅ Circuit Breaker (@CircuitBreaker) - ✅ Retry mechanism (@Retry - 3 tentatives) - ✅ Timeout (30s) - ✅ Connection pooling - ✅ Auto-reconnect - ✅ Health checks #### Mappers (2 fichiers) - `UserMapper.java` - ✅ Conversion UserRepresentation ↔ UserDTO (FONCTIONNE) - `RoleMapper.java` - ❌ Conversion RoleRepresentation ↔ RoleDTO (ERREURS - utilise getNom() au lieu de getName()) #### Services Implementation (3 fichiers) - `UserServiceImpl.java` - ✅ ImplĂ©mentation complĂšte (25+ mĂ©thodes) - FONCTIONNE - `RoleServiceImpl.java` - ❌ ImplĂ©mentation avec ERREURS (signatures ne correspondent pas Ă  l'interface) - `AuditServiceImpl.java` - ❌ ImplĂ©mentation avec ERREURS (mĂ©thodes manquantes dans l'interface) #### Services Implementation - Sync - `SyncServiceImpl.java` - ✅ Créé (synchronisation avec Keycloak) #### REST Resources (5 fichiers) - `UserResource.java` - ✅ Endpoints REST pour users (12 endpoints) - FONCTIONNE - `RoleResource.java` - ❌ Endpoints REST pour rĂŽles (ERREURS) - `AuditResource.java` - ❌ Endpoints REST pour audit (ERREURS) - `SyncResource.java` - ✅ Endpoints REST pour sync - CRÉÉ - `KeycloakHealthCheck.java` + `HealthResourceEndpoint.java` - ✅ Health checks **Statut**: NE COMPILE PAS - Erreurs de signatures de mĂ©thodes --- ### Module 3: client-quarkus-primefaces-freya (0% ⏳) **Localisation**: `lions-user-manager-client-quarkus-primefaces-freya/` **1 fichier créé**: - `pom.xml` - Configuration de base avec dĂ©pendances PrimeFaces **Statut**: Vide, Ă  dĂ©velopper entiĂšrement --- ## ❌ ERREURS DE COMPILATION ACTUELLES ### Fichier: RoleMapper.java **ProblĂšme**: Utilise `getNom()` au lieu de `getName()` **Ligne 25**: ```java .nom(roleRep.getName()) // ❌ ERREUR: doit ĂȘtre .name() ``` **Ligne 43**: ```java roleRep.setName(roleDTO.getNom()); // ❌ ERREUR: doit ĂȘtre roleDTO.getName() ``` **Ligne 29**: ```java .composite(roleRep.isComposite() != null ? roleRep.isComposite() : false) // ❌ ERREUR: isComposite() retourne boolean, pas Boolean // CORRECTION: .composite(roleRep.isComposite()) ``` **FIX COMPLET pour RoleMapper.java**: ```java public static RoleDTO toDTO(RoleRepresentation roleRep, String realmName, TypeRole typeRole) { if (roleRep == null) { return null; } return RoleDTO.builder() .id(roleRep.getId()) .name(roleRep.getName()) // ✅ CORRECTION: name au lieu de nom .description(roleRep.getDescription()) .typeRole(typeRole) .realmName(realmName) .composite(roleRep.isComposite()) // ✅ CORRECTION: pas de !=null check .build(); } public static RoleRepresentation toRepresentation(RoleDTO roleDTO) { if (roleDTO == null) { return null; } RoleRepresentation roleRep = new RoleRepresentation(); roleRep.setId(roleDTO.getId()); roleRep.setName(roleDTO.getName()); // ✅ CORRECTION: getName() au lieu de getNom() roleRep.setDescription(roleDTO.getDescription()); roleRep.setComposite(roleDTO.isComposite()); roleRep.setClientRole(roleDTO.getTypeRole() == TypeRole.CLIENT_ROLE); return roleRep; } ``` --- ### Fichier: RoleServiceImpl.java **ProblĂšme**: Signatures de mĂ©thodes ne correspondent pas Ă  l'interface RoleService.java **Interface RoleService attend**: ```java List getAllClientRoles(@NotBlank String realmName, @NotBlank String clientName); RoleDTO createClientRole(@Valid @NotNull RoleDTO role, @NotBlank String realmName, @NotBlank String clientName); Optional getRoleByName(@NotBlank String roleName, @NotBlank String realmName, @NotNull TypeRole typeRole, String clientName); List getCompositeRoles(@NotBlank String roleName, @NotBlank String realmName, @NotNull TypeRole typeRole, String clientName); // etc... ``` **RoleServiceImpl implĂ©mente** (diffĂ©rent): ```java public List getAllClientRoles(@NotBlank String clientId, @NotBlank String realmName) // ❌ Ordre inversĂ© public RoleDTO createClientRole(..., @NotBlank String clientId, ...) // ❌ clientId au lieu de clientName public Optional getRealmRoleByName(...) // ❌ MĂ©thode diffĂ©rente public List getCompositeRoles(@NotBlank String roleName, @NotBlank String realmName) // ❌ Manque 2 paramĂštres ``` **STRATÉGIE DE CORRECTION**: 1. Ouvrir `RoleService.java` (interface) 2. Lire TOUTES les signatures de mĂ©thodes 3. Modifier `RoleServiceImpl.java` pour que CHAQUE mĂ©thode corresponde EXACTEMENT 4. Utiliser les annotations `@Override` pour vĂ©rifier **MÉTHODES À CORRIGER dans RoleServiceImpl.java**: - `createRealmRole()` - ✅ OK - `getRealmRoleById()` - ❌ SUPPRIMER (interface n'a pas cette mĂ©thode) - `getRealmRoleByName()` - ❌ RENOMMER en getRoleByName() avec params TypeRole et clientName - `updateRealmRole()` - ❌ RENOMMER en updateRole() avec params typeRole et clientName - `deleteRealmRole()` - ❌ RENOMMER en deleteRole() avec params typeRole et clientName - `getAllRealmRoles()` - ✅ OK - `createClientRole()` - ❌ CORRIGER ordre params: (role, realmName, clientName) - `getClientRoleByName()` - ❌ SUPPRIMER - `deleteClientRole()` - ❌ SUPPRIMER - `getAllClientRoles()` - ❌ CORRIGER ordre params: (realmName, clientName) - Toutes les mĂ©thodes d'attribution de rĂŽles - ❌ À vĂ©rifier une par une **Ligne 539**: ```java List composites = keycloakAdminClient.getInstance() .realm(realmName) .roles() .get(roleName) .getRoleComposites(); // ❌ Retourne Set, pas List ``` **FIX**: ```java Set compositesSet = ... .getRoleComposites(); return RoleMapper.toDTOList(new ArrayList<>(compositesSet), realmName, TypeRole.COMPOSITE_ROLE); ``` --- ### Fichier: AuditServiceImpl.java **ProblĂšme**: MĂ©thodes implĂ©mentĂ©es qui n'existent pas dans l'interface AuditService.java **MĂ©thodes dans AuditServiceImpl qui ne sont PAS dans l'interface**: - `searchLogs()` - ❌ PAS dans l'interface - `getLogsByActeur()` - ❌ PAS dans l'interface (interface a `getLogsByActeur` sans 'e') - `getLogsByRessource()` - ❌ PAS dans l'interface - `getLogsByAction()` - ❌ PAS dans l'interface - `getActionStatistics()` - ❌ PAS dans l'interface - `getUserActivityStatistics()` - ❌ PAS dans l'interface - `getFailureCount()` - ❌ PAS dans l'interface - `getSuccessCount()` - ❌ PAS dans l'interface - `exportLogsToCSV()` - ❌ PAS dans l'interface **STRATÉGIE DE CORRECTION**: 1. Ouvrir `AuditService.java` (interface) 2. AJOUTER toutes les mĂ©thodes manquantes avec les bonnes signatures 3. OU adapter AuditServiceImpl pour correspondre Ă  l'interface existante **Option recommandĂ©e**: Ajouter les mĂ©thodes dans l'interface AuditService.java car l'implĂ©mentation est plus complĂšte. --- ### Fichier: RoleResource.java **ProblĂšme**: Appelle des mĂ©thodes de RoleService qui n'existent pas (ou avec mauvais params) **Erreurs Ă  corriger**: - Ligne 56: `roleDTO.getNom()` → `roleDTO.getName()` - Ligne 91: `getRealmRoleByName()` n'existe pas → utiliser `getRoleByName()` avec TypeRole.REALM_ROLE - Ligne 146: `updateRealmRole()` n'existe pas → utiliser `updateRole()` avec TypeRole.REALM_ROLE - Ligne 172: `deleteRealmRole()` n'existe pas → utiliser `deleteRole()` avec TypeRole.REALM_ROLE - etc... **Toutes les mĂ©thodes doivent correspondre aux signatures de l'interface RoleService.java** --- ### Fichier: AuditResource.java **ProblĂšme**: Appelle des mĂ©thodes qui n'existent pas dans AuditService **À FAIRE**: AprĂšs avoir corrigĂ© l'interface AuditService.java, vĂ©rifier que tous les appels correspondent. **Ligne 317**: ```java auditService.purgeOldLogs(joursAnciennete); // ❌ purgeOldLogs attend LocalDateTime, pas int ``` **FIX**: L'interface attend `LocalDateTime`, pas `int`: ```java LocalDateTime dateLimit = LocalDateTime.now().minusDays(joursAnciennete); auditService.purgeOldLogs(dateLimit); ``` --- ## 🔧 TÂCHES PRIORITAIRES À EFFECTUER ### TÂCHE 1: Corriger les erreurs de compilation (URGENT) #### Étape 1.1: Corriger RoleMapper.java ```bash cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\lions-user-manager-server-impl-quarkus\src\main\java\dev\lions\user\manager\mapper" ``` Remplacer: - `getNom()` → `getName()` - `.nom()` → `.name()` - `.composite(roleRep.isComposite() != null ? roleRep.isComposite() : false)` → `.composite(roleRep.isComposite())` #### Étape 1.2: Aligner RoleServiceImpl avec RoleService 1. Ouvrir `RoleService.java` (interface) 2. Lire chaque signature de mĂ©thode 3. Modifier `RoleServiceImpl.java` pour correspondre EXACTEMENT 4. Ajouter `@Override` sur chaque mĂ©thode **MĂ©thodes clĂ©s Ă  vĂ©rifier**: - `getAllClientRoles(String realmName, String clientName)` - ordre des params - `createClientRole(RoleDTO role, String realmName, String clientName)` - ordre des params - `getRoleByName(String roleName, String realmName, TypeRole typeRole, String clientName)` - tous les params - `getCompositeRoles(String roleName, String realmName, TypeRole typeRole, String clientName)` - tous les params #### Étape 1.3: Aligner AuditService.java avec AuditServiceImpl **Option A** (RecommandĂ©e): Ajouter les mĂ©thodes manquantes dans l'interface ```java // Dans AuditService.java, ajouter: List searchLogs(String acteurUsername, LocalDateTime dateDebut, LocalDateTime dateFin, TypeActionAudit typeAction, String ressourceType, Boolean succes, int page, int pageSize); List getLogsByActeur(String acteurUsername, int limit); List getLogsByRessource(String ressourceType, String ressourceId, int limit); List getLogsByAction(TypeActionAudit typeAction, LocalDateTime dateDebut, LocalDateTime dateFin, int limit); Map getActionStatistics(LocalDateTime dateDebut, LocalDateTime dateFin); Map getUserActivityStatistics(LocalDateTime dateDebut, LocalDateTime dateFin); long getFailureCount(LocalDateTime dateDebut, LocalDateTime dateFin); long getSuccessCount(LocalDateTime dateDebut, LocalDateTime dateFin); List exportLogsToCSV(LocalDateTime dateDebut, LocalDateTime dateFin); ``` #### Étape 1.4: Corriger RoleResource.java - Remplacer tous les `getNom()` par `getName()` - Adapter tous les appels de mĂ©thodes pour correspondre Ă  RoleService.java #### Étape 1.5: Corriger AuditResource.java - Corriger l'appel Ă  `purgeOldLogs()` pour passer LocalDateTime au lieu de int #### Étape 1.6: Tester la compilation ```bash cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager" mvn clean compile -DskipTests ``` **CritĂšre de succĂšs**: BUILD SUCCESS sans erreurs --- ### TÂCHE 2: Commit et Push aprĂšs correction Une fois la compilation rĂ©ussie: ```bash # Dans le repo principal cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager" git add . git commit -m "fix: Correction erreurs de compilation - Fix RoleMapper: name au lieu de nom - Fix RoleServiceImpl: alignement avec interface - Fix AuditService: ajout mĂ©thodes manquantes - Fix RoleResource & AuditResource: correction appels Statut: Backend compile maintenant avec succĂšs đŸ€– Generated with Claude Code Co-Authored-By: Claude " git push # Dans le repo server-impl cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\lions-user-manager-server-impl-quarkus" git add . git commit -m "fix: Correction erreurs compilation services đŸ€– Generated with Claude Code Co-Authored-By: Claude " git push # Dans le repo server-api (si modifiĂ©) cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\lions-user-manager-server-api" git add . git commit -m "fix: Ajout mĂ©thodes manquantes dans interfaces đŸ€– Generated with Claude Code Co-Authored-By: Claude " git push ``` --- ### TÂCHE 3: DĂ©velopper le module client (APRÈS compilation OK) **Localisation**: `lions-user-manager-client-quarkus-primefaces-freya/` #### Étape 3.1: ComplĂ©ter le POM.xml ```xml io.quarkiverse.primefaces quarkus-primefaces 3.13.3 org.primefaces primefaces 14.0.5 jakarta org.primefaces freya-theme 5.0.0-jakarta io.quarkus quarkus-rest-client-jackson io.quarkus quarkus-oidc lions-maven-repo https://git.lions.dev/lionsdev/btpxpress-maven-repo/raw/branch/main ``` #### Étape 3.2: CrĂ©er les REST Clients **Fichier**: `src/main/java/dev/lions/user/manager/client/UserServiceClient.java` ```java package dev.lions.user.manager.client; import dev.lions.user.manager.dto.user.UserDTO; import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO; import dev.lions.user.manager.dto.user.UserSearchResultDTO; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @Path("/api/users") @RegisterRestClient(configKey = "user-service") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public interface UserServiceClient { @POST @Path("/search") UserSearchResultDTO searchUsers(UserSearchCriteriaDTO criteria); @GET @Path("/{userId}") UserDTO getUserById(@PathParam("userId") String userId, @QueryParam("realm") String realmName); @POST UserDTO createUser(UserDTO user, @QueryParam("realm") String realmName); @PUT @Path("/{userId}") UserDTO updateUser(@PathParam("userId") String userId, UserDTO user, @QueryParam("realm") String realmName); @DELETE @Path("/{userId}") void deleteUser(@PathParam("userId") String userId, @QueryParam("realm") String realmName); } ``` **Configuration dans application.properties**: ```properties # URL du serveur backend quarkus.rest-client.user-service.url=http://localhost:8081 quarkus.rest-client.user-service.scope=jakarta.inject.Singleton # OIDC Configuration quarkus.oidc.auth-server-url=http://localhost:8180/realms/master quarkus.oidc.client-id=lions-user-manager-client quarkus.oidc.credentials.secret=client-secret-change-me quarkus.oidc.application-type=web-app ``` #### Étape 3.3: CrĂ©er les JSF Backing Beans **Fichier**: `src/main/java/dev/lions/user/manager/bean/UserListBean.java` ```java package dev.lions.user.manager.bean; import dev.lions.user.manager.client.UserServiceClient; import dev.lions.user.manager.dto.user.UserDTO; import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO; import dev.lions.user.manager.dto.user.UserSearchResultDTO; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.SessionScoped; import jakarta.inject.Inject; import jakarta.inject.Named; import lombok.Data; import org.eclipse.microprofile.rest.client.inject.RestClient; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @Named @SessionScoped @Data public class UserListBean implements Serializable { @Inject @RestClient UserServiceClient userServiceClient; private List users = new ArrayList<>(); private String realmName = "master"; private String searchText; @PostConstruct public void init() { loadUsers(); } public void loadUsers() { UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder() .realmName(realmName) .page(0) .pageSize(100) .build(); UserSearchResultDTO result = userServiceClient.searchUsers(criteria); this.users = result.getUsers(); } public void search() { if (searchText != null && !searchText.trim().isEmpty()) { UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder() .realmName(realmName) .searchText(searchText) .page(0) .pageSize(100) .build(); UserSearchResultDTO result = userServiceClient.searchUsers(criteria); this.users = result.getUsers(); } else { loadUsers(); } } } ``` #### Étape 3.4: CrĂ©er les pages XHTML **Fichier**: `src/main/resources/META-INF/resources/users/list.xhtml` ```xml Gestion des Utilisateurs - Lions User Manager ``` #### Étape 3.5: CrĂ©er le template principal avec Freya **Fichier**: `src/main/resources/META-INF/resources/WEB-INF/templates/layout.xhtml` ```xml <ui:insert name="title">Lions User Manager</ui:insert>
``` --- ## đŸ› ïž TECHNOLOGIES UTILISÉES ### Backend (server-impl-quarkus) - **Quarkus 3.15.1** - Framework Java microservices - **Keycloak Admin Client 23.0.3** - API Admin Keycloak - **Jakarta EE** - SpĂ©cifications Jakarta (JAX-RS, Validation, CDI) - **Lombok 1.18.30** - RĂ©duction boilerplate code - **MapStruct 1.5.5.Final** - Bean mapping (optionnel, pour l'instant mappers manuels) - **SmallRye Fault Tolerance** - Circuit Breaker, Retry, Timeout - **SmallRye Health** - Health checks - **Micrometer + Prometheus** - MĂ©triques - **PostgreSQL** (optionnel) - Pour logs d'audit en production ### Frontend (client - À DÉVELOPPER) - **Quarkus PrimeFaces 3.13.3** - Extension Quarkus pour PrimeFaces - **PrimeFaces 14.0.5** - BibliothĂšque de composants JSF - **Freya Theme 5.0.0-jakarta** - ThĂšme PrimeFaces custom (depuis git.lions.dev/lionsdev/btpxpress-maven-repo) - **MicroProfile REST Client** - Consommation API REST - **Quarkus OIDC** - Authentification via Keycloak --- ## 📝 CONFIGURATION KEYCLOAK REQUISE ### Étape 1: CrĂ©er un realm de test ```bash # Via kcadm.sh (script Ă  crĂ©er) kcadm.sh create realms -s realm=test-lions -s enabled=true ``` ### Étape 2: CrĂ©er un service account ```bash # CrĂ©er un client pour le backend kcadm.sh create clients -r master \ -s clientId=lions-user-manager-backend \ -s enabled=true \ -s serviceAccountsEnabled=true \ -s directAccessGrantsEnabled=false \ -s publicClient=false \ -s secret=backend-secret-change-me # Attribuer les rĂŽles admin kcadm.sh add-roles -r master \ --uusername service-account-lions-user-manager-backend \ --rolename admin ``` ### Étape 3: CrĂ©er un client pour le frontend ```bash kcadm.sh create clients -r master \ -s clientId=lions-user-manager-client \ -s enabled=true \ -s publicClient=false \ -s redirectUris='["http://localhost:8080/*"]' \ -s webOrigins='["http://localhost:8080"]' \ -s secret=client-secret-change-me ``` --- ## đŸ§Ș TESTS À CRÉER (AprĂšs compilation OK) ### Tests Unitaires **Localisation**: `lions-user-manager-server-impl-quarkus/src/test/java/` ```java // Exemple: UserServiceImplTest.java @QuarkusTest class UserServiceImplTest { @Inject UserService userService; @Test void testCreateUser() { UserDTO user = UserDTO.builder() .username("testuser") .email("test@example.com") .firstName("Test") .lastName("User") .build(); UserDTO created = userService.createUser(user, "test-realm"); assertNotNull(created.getId()); assertEquals("testuser", created.getUsername()); } } ``` ### Tests d'IntĂ©gration (avec Testcontainers) ```java @QuarkusTest @QuarkusTestResource(KeycloakTestResource.class) class UserResourceIT { @Test void testGetUsers() { given() .when().get("/api/users?realm=master") .then() .statusCode(200) .body("users", notNullValue()); } } ``` **Objectif couverture**: 80% minimum (Jacoco dĂ©jĂ  configurĂ© dans POM) --- ## 📩 DÉPLOIEMENT (Phase Future) ### Helm Charts Ă  crĂ©er **Localisation**: `helm/` ```yaml # values.yaml backend: image: git.lions.dev/lionsdev/lions-user-manager-backend:1.0.0 replicas: 2 resources: limits: cpu: 1000m memory: 1Gi requests: cpu: 500m memory: 512Mi frontend: image: git.lions.dev/lionsdev/lions-user-manager-frontend:1.0.0 replicas: 2 keycloak: url: https://security.lions.dev realm: master backendClientId: lions-user-manager-backend frontendClientId: lions-user-manager-client database: enabled: true # Pour audit logs host: postgresql.lions.svc.cluster.local name: lions_audit ``` ### Dockerfiles **Backend**: `lions-user-manager-server-impl-quarkus/Dockerfile` ```dockerfile FROM registry.access.redhat.com/ubi8/openjdk-17:1.16 COPY target/quarkus-app/lib/ /deployments/lib/ COPY target/quarkus-app/*.jar /deployments/ COPY target/quarkus-app/app/ /deployments/app/ COPY target/quarkus-app/quarkus/ /deployments/quarkus/ EXPOSE 8081 USER 185 ENTRYPOINT [ "java", "-jar", "/deployments/quarkus-run.jar" ] ``` **Frontend**: `lions-user-manager-client-quarkus-primefaces-freya/Dockerfile` ```dockerfile FROM registry.access.redhat.com/ubi8/openjdk-17:1.16 COPY target/quarkus-app/lib/ /deployments/lib/ COPY target/quarkus-app/*.jar /deployments/ COPY target/quarkus-app/app/ /deployments/app/ COPY target/quarkus-app/quarkus/ /deployments/quarkus/ EXPOSE 8080 USER 185 ENTRYPOINT [ "java", "-jar", "/deployments/quarkus-run.jar" ] ``` --- ## 🚹 POINTS D'ATTENTION CRITIQUES ### 1. ZÉRO AccĂšs Direct DB Keycloak ⚠ **JAMAIS** Ă©crire directement dans la base de donnĂ©es Keycloak. Toutes les opĂ©rations DOIVENT passer par l'API Admin REST. **Exemples corrects**: ```java // ✅ BON: Via API Admin keycloakAdminClient.getInstance() .realm("master") .users() .create(userRepresentation); // ❌ MAUVAIS: AccĂšs direct DB entityManager.persist(keycloakUser); // INTERDIT ! ``` ### 2. Gestion des Credentials Git **NE JAMAIS** committer les credentials en clair. Toujours utiliser: - Variables d'environnement - Secrets Kubernetes - Configuration externe ### 3. Freya Theme Le JAR Freya se trouve dans un repo Maven custom: - URL: https://git.lions.dev/lionsdev/btpxpress-maven-repo/raw/branch/main - Artifact: org.primefaces:freya-theme:5.0.0-jakarta Configurer le repository dans le POM du module client. ### 4. Multi-Realm Le systĂšme doit gĂ©rer plusieurs realms: - `master` - Administration globale - `btpxpress` - Application BTP - `test-lions` - Tests - etc. Toujours passer `realmName` en paramĂštre. ### 5. SĂ©curitĂ© **RĂŽles requis**: - `admin` - Toutes les opĂ©rations - `user_manager` - Gestion utilisateurs et rĂŽles - `user_viewer` - Lecture seule - `auditor` - Consultation logs - `sync_manager` - Synchronisation Utiliser `@RolesAllowed` sur tous les endpoints. --- ## 📊 MÉTRIQUES DE PROGRESSION ### Fichiers créés: 32 / ~120 (27%) - server-api: 15/15 (100%) ✅ - server-impl: 14/30 (47%) 🔄 - client: 1/50 (2%) ⏳ - infrastructure: 0/15 (0%) ⏳ - documentation: 2/10 (20%) 🔄 ### Modules compilables: 1/3 (33%) - server-api: ✅ Compile - server-impl: ❌ Erreurs de compilation (Ă  corriger) - client: ⏳ Non dĂ©veloppĂ© ### Services implĂ©mentĂ©s: 2/4 (50%) - UserService: ✅ 100% fonctionnel - RoleService: 🔄 ImplĂ©mentĂ© avec erreurs - AuditService: 🔄 ImplĂ©mentĂ© avec erreurs - SyncService: ✅ ImplĂ©mentĂ© (Ă  tester aprĂšs compilation) --- ## 🎯 FEUILLE DE ROUTE COMPLÈTE ### Phase 1: Correction des Erreurs (PRIORITÉ 1) ⏰ 2-3 heures - [ ] Corriger RoleMapper.java (name vs nom) - [ ] Aligner RoleServiceImpl avec RoleService - [ ] ComplĂ©ter AuditService.java (interface) - [ ] Corriger RoleResource.java - [ ] Corriger AuditResource.java - [ ] Compiler sans erreurs - [ ] Commit et push vers Git ### Phase 2: Finaliser Backend (PRIORITÉ 2) ⏰ 1 jour - [ ] VĂ©rifier SyncServiceImpl - [ ] Tester tous les endpoints REST avec Postman/curl - [ ] CrĂ©er tests unitaires (UserService, RoleService) - [ ] CrĂ©er tests d'intĂ©gration (UserResource, RoleResource) - [ ] Atteindre 80% de couverture de code - [ ] Documenter l'API (OpenAPI/Swagger) ### Phase 3: Module Client UI (PRIORITÉ 3) ⏰ 2-3 jours - [ ] ComplĂ©ter POM.xml avec Freya Theme - [ ] CrĂ©er REST Clients (@RegisterRestClient) - [ ] CrĂ©er JSF Backing Beans (10+ beans) - [ ] CrĂ©er pages XHTML (15+ pages) - [ ] ImplĂ©menter template Freya - [ ] Tester l'interface utilisateur - [ ] IntĂ©grer avec OIDC Keycloak ### Phase 4: Infrastructure & DĂ©ploiement (PRIORITÉ 4) ⏰ 1-2 jours - [ ] CrĂ©er Dockerfiles (backend + frontend) - [ ] CrĂ©er Helm charts - [ ] CrĂ©er scripts de provisioning Keycloak (kcadm) - [ ] Tester dĂ©ploiement local avec Docker Compose - [ ] Tester dĂ©ploiement Kubernetes - [ ] Configurer CI/CD pipeline ### Phase 5: Documentation Finale (PRIORITÉ 5) ⏰ 0.5 jour - [ ] README.md complet - [ ] Guide d'installation - [ ] Guide d'utilisation - [ ] Documentation API - [ ] Guide de dĂ©ploiement - [ ] Guide de troubleshooting --- ## 📚 RESSOURCES ET DOCUMENTATION ### Documentation Technique - **Keycloak Admin REST API**: https://www.keycloak.org/docs-api/23.0.3/rest-api/index.html - **Quarkus Guides**: https://quarkus.io/guides/ - **PrimeFaces**: https://www.primefaces.org/showcase/ - **MicroProfile REST Client**: https://download.eclipse.org/microprofile/microprofile-rest-client-3.0/microprofile-rest-client-spec-3.0.html ### Commandes Utiles #### Compilation ```bash # Compilation complĂšte cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager" mvn clean install -DskipTests # Compilation module spĂ©cifique mvn clean install -pl lions-user-manager-server-impl-quarkus -DskipTests # Avec tests mvn clean install # Package Quarkus cd lions-user-manager-server-impl-quarkus mvn clean package ``` #### ExĂ©cution en Dev ```bash # Backend cd lions-user-manager-server-impl-quarkus mvn quarkus:dev # Frontend (quand dĂ©veloppĂ©) cd lions-user-manager-client-quarkus-primefaces-freya mvn quarkus:dev ``` #### Git ```bash # Status dans chaque module cd lions-user-manager-server-api && git status cd ../lions-user-manager-server-impl-quarkus && git status cd ../lions-user-manager-client-quarkus-primefaces-freya && git status # Push vers tous les repos cd lions-user-manager-server-api && git push cd ../lions-user-manager-server-impl-quarkus && git push cd ../lions-user-manager-client-quarkus-primefaces-freya && git push cd .. && git push # Repo principal ``` --- ## 🆘 TROUBLESHOOTING COURANT ### Erreur: "Mixing Quarkus REST and RESTEasy Classic" **Cause**: Keycloak Admin Client inclut RESTEasy Classic **Solution**: DĂ©jĂ  corrigĂ©e avec exclusions dans POM.xml ### Erreur: "cannot find symbol: variable log" **Cause**: Lombok @Slf4j non processĂ© **Solution**: DĂ©jĂ  configurĂ© dans maven-compiler-plugin avec annotation processors ### Erreur: Compilation RoleMapper "cannot find symbol: method getNom()" **Cause**: Le champ RoleDTO s'appelle `name`, pas `nom` **Solution**: Voir TÂCHE 1, Étape 1.1 ci-dessus ### Erreur: "method does not override or implement a method from a supertype" **Cause**: Signatures de mĂ©thodes diffĂ©rentes entre interface et implĂ©mentation **Solution**: Aligner les signatures exactement (voir TÂCHE 1, Étape 1.2) ### Keycloak non accessible **VĂ©rifier**: ```bash curl http://localhost:8180/realms/master/.well-known/openid-configuration ``` **DĂ©marrer Keycloak local**: ```bash docker run -p 8180:8080 \ -e KEYCLOAK_ADMIN=admin \ -e KEYCLOAK_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:23.0.3 start-dev ``` --- ## ✅ CHECKLIST AVANT DE PASSER À L'AGENT SUIVANT - [x] Document AI_HANDOFF_DOCUMENT.md créé - [x] Toutes les erreurs de compilation documentĂ©es - [x] Solutions dĂ©taillĂ©es fournies - [x] Structure Git clarifiĂ©e et corrigĂ©e - [x] Credentials Git fournis - [x] Feuille de route complĂšte Ă©tablie - [x] Exemples de code fournis - [x] Commandes Maven/Git documentĂ©es - [x] Technologies et versions spĂ©cifiĂ©es - [x] Points critiques mis en Ă©vidence --- ## 📞 CONTACT & SUPPORT **Projet**: lions-user-manager **Owner**: LionsDev **Git**: https://git.lions.dev/lionsdev/ **Email**: gbanedahoud@gmail.com (contexte du workspace) --- **đŸ€– Document gĂ©nĂ©rĂ© par Claude Code** **Version**: 1.0 **Date**: 2025-01-09 **Statut**: PrĂȘt pour passation Ă  l'agent suivant --- ## 🎬 COMMENCER MAINTENANT - SCRIPT D'EXÉCUTION IMMÉDIAT ```bash # 1. Aller dans le rĂ©pertoire du projet cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager" # 2. Lire ce document cat AI_HANDOFF_DOCUMENT.md # 3. Commencer par TÂCHE 1, Étape 1.1 # Corriger RoleMapper.java # 4. Puis TÂCHE 1, Étape 1.2 # Aligner RoleServiceImpl avec RoleService # 5. Compiler pour vĂ©rifier mvn clean compile -DskipTests # 6. Si BUILD SUCCESS, passer Ă  TÂCHE 2 (commit & push) # Sinon, continuer les corrections # 7. Une fois backend compilĂ©, passer Ă  TÂCHE 3 (module client) ``` **BONNE CHANCE ! 🚀**