diff --git a/.gitignore b/.gitignore
index ef93977..eb78596 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,114 +1,114 @@
-# ====================================
-# GITIGNORE POUR SERVER API (Maven Library)
-# ====================================
-
-# ===== MAVEN =====
-target/
-pom.xml.tag
-pom.xml.releaseBackup
-pom.xml.versionsBackup
-pom.xml.next
-release.properties
-dependency-reduced-pom.xml
-buildNumber.properties
-.mvn/timing.properties
-.mvn/wrapper/maven-wrapper.jar
-.flattened-pom.xml
-
-# ===== JAVA COMPILED FILES =====
-*.class
-*.jar
-*.war
-*.ear
-*.nar
-*.zip
-*.tar.gz
-*.rar
-
-# ===== IDE - ECLIPSE =====
-.project
-.classpath
-.settings/
-.factorypath
-.metadata/
-bin/
-.apt_generated
-.springBeans
-.sts4-cache
-
-# ===== IDE - INTELLIJ IDEA =====
-.idea/
-*.iml
-*.ipr
-*.iws
-out/
-
-# ===== IDE - NETBEANS =====
-nbproject/
-nbbuild/
-nbdist/
-.nb-gradle/
-nb-configuration.xml
-nbactions.xml
-
-# ===== IDE - VS CODE =====
-.vscode/
-*.code-workspace
-
-# ===== OS SPECIFIC =====
-.DS_Store
-Thumbs.db
-ehthumbs.db
-Desktop.ini
-$RECYCLE.BIN/
-*~
-
-# ===== LOGS =====
-*.log
-*.log.*
-logs/
-log/
-
-# ===== TEMPORARY FILES =====
-*.tmp
-*.temp
-*.bak
-*.backup
-*.old
-*.swp
-*.swo
-*.orig
-*.rej
-
-# ===== ENVIRONMENT & CONFIGURATION =====
-.env
-.env.local
-.env.*
-*.local
-application-local.properties
-
-# ===== SECURITY - KEYS & CERTIFICATES =====
-*.key
-*.pem
-*.crt
-*.p12
-*.jks
-*.keystore
-.certs/
-.certificates/
-
-# ===== TEST COVERAGE =====
-.jacoco/
-jacoco.exec
-coverage/
-.nyc_output/
-
-# ===== GENERATED SOURCES =====
-src/gen/
-generated-sources/
-generated-test-sources/
-
-# ===== BUILD ARTIFACTS =====
-dist/
-build/
-out/
+# ====================================
+# GITIGNORE POUR SERVER API (Maven Library)
+# ====================================
+
+# ===== MAVEN =====
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+.flattened-pom.xml
+
+# ===== JAVA COMPILED FILES =====
+*.class
+*.jar
+*.war
+*.ear
+*.nar
+*.zip
+*.tar.gz
+*.rar
+
+# ===== IDE - ECLIPSE =====
+.project
+.classpath
+.settings/
+.factorypath
+.metadata/
+bin/
+.apt_generated
+.springBeans
+.sts4-cache
+
+# ===== IDE - INTELLIJ IDEA =====
+.idea/
+*.iml
+*.ipr
+*.iws
+out/
+
+# ===== IDE - NETBEANS =====
+nbproject/
+nbbuild/
+nbdist/
+.nb-gradle/
+nb-configuration.xml
+nbactions.xml
+
+# ===== IDE - VS CODE =====
+.vscode/
+*.code-workspace
+
+# ===== OS SPECIFIC =====
+.DS_Store
+Thumbs.db
+ehthumbs.db
+Desktop.ini
+$RECYCLE.BIN/
+*~
+
+# ===== LOGS =====
+*.log
+*.log.*
+logs/
+log/
+
+# ===== TEMPORARY FILES =====
+*.tmp
+*.temp
+*.bak
+*.backup
+*.old
+*.swp
+*.swo
+*.orig
+*.rej
+
+# ===== ENVIRONMENT & CONFIGURATION =====
+.env
+.env.local
+.env.*
+*.local
+application-local.properties
+
+# ===== SECURITY - KEYS & CERTIFICATES =====
+*.key
+*.pem
+*.crt
+*.p12
+*.jks
+*.keystore
+.certs/
+.certificates/
+
+# ===== TEST COVERAGE =====
+.jacoco/
+jacoco.exec
+coverage/
+.nyc_output/
+
+# ===== GENERATED SOURCES =====
+src/gen/
+generated-sources/
+generated-test-sources/
+
+# ===== BUILD ARTIFACTS =====
+dist/
+build/
+out/
diff --git a/README.md b/README.md
index dcf9930..6a7f7b5 100644
--- a/README.md
+++ b/README.md
@@ -1,124 +1,124 @@
-# lions-user-manager-server-api
-
-> Contrats partagés entre le serveur et le client — DTOs, interfaces de services, enums, validations
-
-## Rôle
-
-Ce module constitue la couche de contrats (API layer) du projet Lions User Manager. Il est compilé en JAR et publié sur le **Gitea Package Registry** pour être consommé par `server-impl` et `client` comme dépendance Maven.
-
----
-
-## Contenu
-
-### DTOs
-
-| DTO | Description |
-|-----|-------------|
-| `UserDTO` | Représentation complète d'un utilisateur Keycloak |
-| `UserCreationDTO` | Données de création d'un utilisateur |
-| `UserUpdateDTO` | Données de mise à jour |
-| `RoleDTO` | Rôle Keycloak |
-| `RealmDTO` | Realm Keycloak |
-| `RealmAssignmentDTO` | Assignation d'un utilisateur à un realm |
-| `AuditLogDTO` | Entrée de journal d'audit |
-| `SyncHistoryDTO` | Historique de synchronisation |
-| `SyncConsistencyDTO` | Rapport de cohérence sync |
-| `ImportResultDTO` | Résultat d'import CSV |
-
-### Interfaces de services
-
-| Interface | Responsabilité |
-|-----------|----------------|
-| `UserService` | CRUD utilisateurs, export/import CSV |
-| `RoleService` | Gestion des rôles par realm |
-| `AuditService` | Consultation et export des logs d'audit |
-| `SyncService` | Synchronisation Keycloak ↔ base de données |
-| `RealmAuthorizationService` | Gestion des realms autorisés |
-
-### Interfaces de ressources (JAX-RS)
-
-| Interface | Path |
-|-----------|------|
-| `UserResourceApi` | `/api/users` |
-| `RoleResourceApi` | `/api/roles` |
-| `AuditResourceApi` | `/api/audit` |
-| `SyncResourceApi` | `/api/sync` |
-| `RealmResourceApi` | `/api/realms` |
-| `RealmAssignmentResourceApi` | `/api/realm-assignments` |
-
-### Enums
-
-- `StatutUser` — ACTIF, INACTIF, SUSPENDU
-- `TypeRole` — ADMIN, USER, VIEWER
-- `TypeActionAudit` — CREATE, UPDATE, DELETE, LOGIN, LOGOUT, SYNC
-
-### Validations
-
-- `ValidationConstants` — Constantes partagées (longueurs, patterns regex)
-
----
-
-## Dépôt Git
-
-`https://git.lions.dev/lionsdev/lions-user-manager-server-api`
-
----
-
-## Maven Registry
-
-Le jar est disponible sur le **Gitea Package Registry** :
-
-```
-groupId : dev.lions.user.manager
-artifactId : lions-user-manager-server-api
-version : 1.0.0
-registry : https://git.lions.dev/api/packages/lionsdev/maven
-```
-
-### Consommer ce module (server-impl / client)
-
-```xml
-
- dev.lions.user.manager
- lions-user-manager-server-api
- 1.0.0
-
-```
-
-```xml
-
-
- gitea-lionsdev
- https://git.lions.dev/api/packages/lionsdev/maven
-
-
-```
-
----
-
-## Publier une nouvelle version
-
-1. Incrémenter la version dans `../pom.xml` (parent)
-2. Exécuter depuis la racine du monorepo :
-
-```bash
-# Windows
-script\publish-api.bat
-
-# Linux / macOS
-./script/publish-api.sh
-```
-
----
-
-## Build local
-
-```bash
-mvn clean install -DskipTests
-```
-
----
-
-## Licence
-
-Propriétaire — Lions Dev © 2025
+# lions-user-manager-server-api
+
+> Contrats partagés entre le serveur et le client — DTOs, interfaces de services, enums, validations
+
+## Rôle
+
+Ce module constitue la couche de contrats (API layer) du projet Lions User Manager. Il est compilé en JAR et publié sur le **Gitea Package Registry** pour être consommé par `server-impl` et `client` comme dépendance Maven.
+
+---
+
+## Contenu
+
+### DTOs
+
+| DTO | Description |
+|-----|-------------|
+| `UserDTO` | Représentation complète d'un utilisateur Keycloak |
+| `UserCreationDTO` | Données de création d'un utilisateur |
+| `UserUpdateDTO` | Données de mise à jour |
+| `RoleDTO` | Rôle Keycloak |
+| `RealmDTO` | Realm Keycloak |
+| `RealmAssignmentDTO` | Assignation d'un utilisateur à un realm |
+| `AuditLogDTO` | Entrée de journal d'audit |
+| `SyncHistoryDTO` | Historique de synchronisation |
+| `SyncConsistencyDTO` | Rapport de cohérence sync |
+| `ImportResultDTO` | Résultat d'import CSV |
+
+### Interfaces de services
+
+| Interface | Responsabilité |
+|-----------|----------------|
+| `UserService` | CRUD utilisateurs, export/import CSV |
+| `RoleService` | Gestion des rôles par realm |
+| `AuditService` | Consultation et export des logs d'audit |
+| `SyncService` | Synchronisation Keycloak ↔ base de données |
+| `RealmAuthorizationService` | Gestion des realms autorisés |
+
+### Interfaces de ressources (JAX-RS)
+
+| Interface | Path |
+|-----------|------|
+| `UserResourceApi` | `/api/users` |
+| `RoleResourceApi` | `/api/roles` |
+| `AuditResourceApi` | `/api/audit` |
+| `SyncResourceApi` | `/api/sync` |
+| `RealmResourceApi` | `/api/realms` |
+| `RealmAssignmentResourceApi` | `/api/realm-assignments` |
+
+### Enums
+
+- `StatutUser` — ACTIF, INACTIF, SUSPENDU
+- `TypeRole` — ADMIN, USER, VIEWER
+- `TypeActionAudit` — CREATE, UPDATE, DELETE, LOGIN, LOGOUT, SYNC
+
+### Validations
+
+- `ValidationConstants` — Constantes partagées (longueurs, patterns regex)
+
+---
+
+## Dépôt Git
+
+`https://git.lions.dev/lionsdev/lions-user-manager-server-api`
+
+---
+
+## Maven Registry
+
+Le jar est disponible sur le **Gitea Package Registry** :
+
+```
+groupId : dev.lions.user.manager
+artifactId : lions-user-manager-server-api
+version : 1.0.0
+registry : https://git.lions.dev/api/packages/lionsdev/maven
+```
+
+### Consommer ce module (server-impl / client)
+
+```xml
+
+ dev.lions.user.manager
+ lions-user-manager-server-api
+ 1.0.0
+
+```
+
+```xml
+
+
+ gitea-lionsdev
+ https://git.lions.dev/api/packages/lionsdev/maven
+
+
+```
+
+---
+
+## Publier une nouvelle version
+
+1. Incrémenter la version dans `../pom.xml` (parent)
+2. Exécuter depuis la racine du monorepo :
+
+```bash
+# Windows
+script\publish-api.bat
+
+# Linux / macOS
+./script/publish-api.sh
+```
+
+---
+
+## Build local
+
+```bash
+mvn clean install -DskipTests
+```
+
+---
+
+## Licence
+
+Propriétaire — Lions Dev © 2025
diff --git a/lombok.config b/lombok.config
index 2b45606..b4edc26 100644
--- a/lombok.config
+++ b/lombok.config
@@ -1,6 +1,6 @@
-# This file configures Lombok for the project
-# See https://projectlombok.org/features/configuration
-
-# Add @Generated annotation to all generated code
-# This allows JaCoCo to automatically exclude Lombok-generated code from coverage
-lombok.addLombokGeneratedAnnotation = true
+# This file configures Lombok for the project
+# See https://projectlombok.org/features/configuration
+
+# Add @Generated annotation to all generated code
+# This allows JaCoCo to automatically exclude Lombok-generated code from coverage
+lombok.addLombokGeneratedAnnotation = true
diff --git a/parent-pom.xml b/parent-pom.xml
index 4e9abcc..56c5d5d 100644
--- a/parent-pom.xml
+++ b/parent-pom.xml
@@ -1,265 +1,266 @@
-
-
- 4.0.0
-
- dev.lions.user.manager
- lions-user-manager-parent
- 1.0.0
- pom
-
- Lions User Manager - Parent
- Module de gestion centralisée des utilisateurs via Keycloak Admin API
-
-
-
- gitea-lionsdev
- https://git.lions.dev/api/packages/lionsdev/maven
-
-
- gitea-lionsdev
- https://git.lions.dev/api/packages/lionsdev/maven
-
-
-
-
-
- gitea-lionsdev
- https://git.lions.dev/api/packages/lionsdev/maven
- true
- true
-
-
-
-
- 21
- 21
- 21
- UTF-8
- UTF-8
-
-
- 3.20.0
- 3.15.1
- 14.0.5
- 1.0.0
- 26.0.7
- 1.18.36
- 1.6.3
-
-
- 5.11.4
- 5.14.2
- 1.20.6
- 5.5.0
-
-
- 3.13.0
- 3.5.2
- 3.5.2
- 0.8.12
-
-
-
- lions-user-manager-server-api
- lions-user-manager-server-impl-quarkus
- lions-user-manager-client-quarkus-primefaces-freya
-
-
-
-
-
-
- io.quarkus.platform
- quarkus-bom
- ${quarkus.version}
- pom
- import
-
-
-
-
- dev.lions.user.manager
- lions-user-manager-server-api
- ${project.version}
-
-
-
-
- dev.lions
- primefaces-freya-extension
- ${primefaces-freya-extension.version}
-
-
-
-
- org.projectlombok
- lombok
- ${lombok.version}
- provided
-
-
-
-
- org.mapstruct
- mapstruct
- ${mapstruct.version}
-
-
-
-
- org.junit.jupiter
- junit-jupiter
- ${junit.version}
- test
-
-
-
- org.testcontainers
- testcontainers-bom
- ${testcontainers.version}
- pom
- import
-
-
-
- io.rest-assured
- rest-assured
- ${rest-assured.version}
- test
-
-
-
- org.mockito
- mockito-core
- ${mockito.version}
- test
-
-
-
- org.mockito
- mockito-junit-jupiter
- ${mockito.version}
-
-
-
-
-
-
-
-
- dev
-
- true
-
-
- dev
-
-
-
- prod
-
- prod
-
-
-
- native
-
- prod
- native
-
-
-
- io.quarkus
- quarkus-junit5
- test
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- ${maven-compiler-plugin.version}
-
-
-
- org.projectlombok
- lombok
- ${lombok.version}
-
-
- org.mapstruct
- mapstruct-processor
- ${mapstruct.version}
-
-
-
-
-
-
- io.quarkus.platform
- quarkus-maven-plugin
- ${quarkus.version}
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- ${maven-surefire-plugin.version}
-
-
-
- org.apache.maven.plugins
- maven-failsafe-plugin
- ${maven-failsafe-plugin.version}
-
-
-
- org.jacoco
- jacoco-maven-plugin
- ${jacoco-maven-plugin.version}
-
-
-
- prepare-agent
-
-
-
- report
- test
-
- report
-
-
-
- jacoco-check
-
- check
-
-
-
-
- PACKAGE
-
-
- LINE
- COVEREDRATIO
- 0.80
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ 4.0.0
+
+ dev.lions.user.manager
+ lions-user-manager-parent
+ 1.1.0
+ pom
+
+ Lions User Manager - Parent
+ Module de gestion centralisée des utilisateurs via Keycloak Admin API
+
+
+
+ gitea-lionsdev
+ https://git.lions.dev/api/packages/lionsdev/maven
+
+
+ gitea-lionsdev
+ https://git.lions.dev/api/packages/lionsdev/maven
+
+
+
+
+
+ gitea-lionsdev
+ https://git.lions.dev/api/packages/lionsdev/maven
+ true
+ true
+
+
+
+
+ 21
+ 21
+ 21
+ UTF-8
+ UTF-8
+
+
+ 3.27.3
+ 3.15.1
+ 14.0.5
+ 1.0.0
+ 26.0.7
+ 1.18.38
+ 1.6.3
+
+
+ 5.11.4
+ 5.14.2
+ 1.21.4
+ 3.4.2
+ 5.5.0
+
+
+ 3.13.0
+ 3.5.2
+ 3.5.2
+ 0.8.12
+
+
+
+ lions-user-manager-server-api
+ lions-user-manager-server-impl-quarkus
+ lions-user-manager-client-quarkus-primefaces-freya
+
+
+
+
+
+
+ io.quarkus.platform
+ quarkus-bom
+ ${quarkus.version}
+ pom
+ import
+
+
+
+
+ dev.lions.user.manager
+ lions-user-manager-server-api
+ ${project.version}
+
+
+
+
+ dev.lions
+ primefaces-freya-extension
+ ${primefaces-freya-extension.version}
+
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+ org.mapstruct
+ mapstruct
+ ${mapstruct.version}
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.version}
+ test
+
+
+
+ org.testcontainers
+ testcontainers-bom
+ ${testcontainers.version}
+ pom
+ import
+
+
+
+ io.rest-assured
+ rest-assured
+ ${rest-assured.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
+
+
+
+
+
+
+
+
+ dev
+
+ true
+
+
+ dev
+
+
+
+ prod
+
+ prod
+
+
+
+ native
+
+ prod
+ native
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+
+
+
+
+ io.quarkus.platform
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ ${maven-failsafe-plugin.version}
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
+
+
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+
+ jacoco-check
+
+ check
+
+
+
+
+ PACKAGE
+
+
+ LINE
+ COVEREDRATIO
+ 0.80
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 5d2ce73..806c9ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,91 +1,134 @@
-
-
- 4.0.0
-
-
- dev.lions.user.manager
- lions-user-manager-parent
- 1.0.0
-
-
- lions-user-manager-server-api
- jar
-
- Lions User Manager - Server API
- Contrats API: DTOs, interfaces de services, enums et validations
-
-
-
-
- org.projectlombok
- lombok
-
-
-
-
- jakarta.validation
- jakarta.validation-api
-
-
-
- jakarta.ws.rs
- jakarta.ws.rs-api
-
-
-
-
- com.fasterxml.jackson.core
- jackson-annotations
-
-
-
-
- org.eclipse.microprofile.openapi
- microprofile-openapi-api
-
-
-
-
- io.quarkus
- quarkus-core
- provided
- true
-
-
-
-
- org.junit.jupiter
- junit-jupiter
- test
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 21
-
-
-
-
-
- io.smallrye
- jandex-maven-plugin
- 3.2.4
-
-
- make-index
-
- jandex
-
-
-
-
-
-
-
+
+
+ 4.0.0
+
+ dev.lions.user.manager
+ 1.1.0
+
+
+ 21
+ ${java.version}
+ ${java.version}
+ UTF-8
+ 3.27.3
+ 1.18.38
+
+
+ lions-user-manager-server-api
+ jar
+
+ Lions User Manager - Server API
+ Contrats API: DTOs, interfaces de services, enums et validations
+
+
+
+ gitea-lionsdev
+ https://git.lions.dev/api/packages/lionsdev/maven
+
+
+
+
+
+ gitea-lionsdev
+ https://git.lions.dev/api/packages/lionsdev/maven
+ true
+ true
+
+
+
+
+
+
+
+ io.quarkus.platform
+ quarkus-bom
+ ${quarkus.platform.version}
+ pom
+ import
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+ jakarta.validation
+ jakarta.validation-api
+
+
+
+ jakarta.ws.rs
+ jakarta.ws.rs-api
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+
+ org.eclipse.microprofile.openapi
+ microprofile-openapi-api
+
+
+
+
+ io.quarkus
+ quarkus-core
+ provided
+ true
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.13.0
+
+ 21
+
+
+
+
+
+ io.smallrye
+ jandex-maven-plugin
+ 3.2.4
+
+
+ make-index
+
+ jandex
+
+
+
+
+
+
+
diff --git a/script/publish-api.bat b/script/publish-api.bat
index 3ae7c10..f185071 100644
--- a/script/publish-api.bat
+++ b/script/publish-api.bat
@@ -1,30 +1,30 @@
-@echo off
-REM Publie le parent pom + server-api sur le Gitea Package Registry
-REM Usage : script\publish-api.bat
-REM Depuis : n'importe où dans le repo server-api
-REM Prérequis: credentials dans %USERPROFILE%\.m2\settings.xml (server id: gitea-lionsdev)
-
-set REGISTRY_URL=https://git.lions.dev/api/packages/lionsdev/maven
-set REGISTRY_ID=gitea-lionsdev
-
-cd /d "%~dp0.."
-
-echo.
-echo [1/2] Publication du parent pom...
-call mvn deploy:deploy-file ^
- -DgroupId=dev.lions.user.manager ^
- -DartifactId=lions-user-manager-parent ^
- -Dversion=1.0.0 ^
- -Dpackaging=pom ^
- -Dfile=parent-pom.xml ^
- -DrepositoryId=%REGISTRY_ID% ^
- -Durl=%REGISTRY_URL%
-if %errorlevel% neq 0 echo [WARN] Parent pom deja publie pour cette version (409), on continue.
-
-echo.
-echo [2/2] Publication du server-api...
-call mvn deploy -DskipTests
-if %errorlevel% neq 0 echo [WARN] Server-api deja publie pour cette version (409) - incrementer la version pour republier.
-
-echo.
-echo Done -- https://git.lions.dev/lionsdev/-/packages
+@echo off
+REM Publie le parent pom + server-api sur le Gitea Package Registry
+REM Usage : script\publish-api.bat
+REM Depuis : n'importe où dans le repo server-api
+REM Prérequis: credentials dans %USERPROFILE%\.m2\settings.xml (server id: gitea-lionsdev)
+
+set REGISTRY_URL=https://git.lions.dev/api/packages/lionsdev/maven
+set REGISTRY_ID=gitea-lionsdev
+
+cd /d "%~dp0.."
+
+echo.
+echo [1/2] Publication du parent pom...
+call mvn deploy:deploy-file ^
+ -DgroupId=dev.lions.user.manager ^
+ -DartifactId=lions-user-manager-parent ^
+ -Dversion=1.0.0 ^
+ -Dpackaging=pom ^
+ -Dfile=parent-pom.xml ^
+ -DrepositoryId=%REGISTRY_ID% ^
+ -Durl=%REGISTRY_URL%
+if %errorlevel% neq 0 echo [WARN] Parent pom deja publie pour cette version (409), on continue.
+
+echo.
+echo [2/2] Publication du server-api...
+call mvn deploy -DskipTests
+if %errorlevel% neq 0 echo [WARN] Server-api deja publie pour cette version (409) - incrementer la version pour republier.
+
+echo.
+echo Done -- https://git.lions.dev/lionsdev/-/packages
diff --git a/script/publish-api.sh b/script/publish-api.sh
index de5106a..a52cffc 100644
--- a/script/publish-api.sh
+++ b/script/publish-api.sh
@@ -1,32 +1,32 @@
-#!/bin/bash
-# Publie le parent pom + server-api sur le Gitea Package Registry
-# Usage : ./script/publish-api.sh
-# Depuis : n'importe où dans le repo server-api
-# Prérequis: credentials dans ~/.m2/settings.xml (server id: gitea-lionsdev)
-
-set -e
-
-REGISTRY_URL="https://git.lions.dev/api/packages/lionsdev/maven"
-REGISTRY_ID="gitea-lionsdev"
-
-cd "$(dirname "$0")/.."
-
-echo ""
-echo "[1/2] Publication du parent pom..."
-mvn deploy:deploy-file \
- -DgroupId=dev.lions.user.manager \
- -DartifactId=lions-user-manager-parent \
- -Dversion=1.0.0 \
- -Dpackaging=pom \
- -Dfile=parent-pom.xml \
- -DrepositoryId="${REGISTRY_ID}" \
- -Durl="${REGISTRY_URL}" \
-|| echo "[WARN] Parent pom deja publie pour cette version (409), on continue."
-
-echo ""
-echo "[2/2] Publication du server-api..."
-mvn deploy -DskipTests \
-|| echo "[WARN] Server-api deja publie pour cette version (409) - incrementer la version pour republier."
-
-echo ""
-echo "Done -- https://git.lions.dev/lionsdev/-/packages"
+#!/bin/bash
+# Publie le parent pom + server-api sur le Gitea Package Registry
+# Usage : ./script/publish-api.sh
+# Depuis : n'importe où dans le repo server-api
+# Prérequis: credentials dans ~/.m2/settings.xml (server id: gitea-lionsdev)
+
+set -e
+
+REGISTRY_URL="https://git.lions.dev/api/packages/lionsdev/maven"
+REGISTRY_ID="gitea-lionsdev"
+
+cd "$(dirname "$0")/.."
+
+echo ""
+echo "[1/2] Publication du parent pom..."
+mvn deploy:deploy-file \
+ -DgroupId=dev.lions.user.manager \
+ -DartifactId=lions-user-manager-parent \
+ -Dversion=1.1.0 \
+ -Dpackaging=pom \
+ -Dfile=parent-pom.xml \
+ -DrepositoryId="${REGISTRY_ID}" \
+ -Durl="${REGISTRY_URL}" \
+|| echo "[WARN] Parent pom deja publie pour cette version (409), on continue."
+
+echo ""
+echo "[2/2] Publication du server-api..."
+mvn deploy -DskipTests \
+|| echo "[WARN] Server-api deja publie pour cette version (409) - incrementer la version pour republier."
+
+echo ""
+echo "Done -- https://git.lions.dev/lionsdev/-/packages"
diff --git a/src/main/java/dev/lions/user/manager/api/AuditResourceApi.java b/src/main/java/dev/lions/user/manager/api/AuditResourceApi.java
index a9d04e2..eb85d21 100644
--- a/src/main/java/dev/lions/user/manager/api/AuditResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/AuditResourceApi.java
@@ -1,111 +1,111 @@
-package dev.lions.user.manager.api;
-
-import dev.lions.user.manager.dto.audit.AuditLogDTO;
-import dev.lions.user.manager.dto.common.CountDTO;
-import dev.lions.user.manager.enums.audit.TypeActionAudit;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.media.Content;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Interface JAX-RS pour l'API d'audit.
- */
-@Path("/api/audit")
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-@Tag(name = "Audit", description = "Consultation des logs d'audit et statistiques")
-public interface AuditResourceApi {
-
- @POST
- @Path("/search")
- @Operation(summary = "Rechercher des logs d'audit", description = "Recherche avancée de logs selon critères")
- @APIResponses({
- @APIResponse(responseCode = "200", description = "Résultats de recherche", content = @Content(schema = @Schema(implementation = AuditLogDTO.class, type = org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY))),
- @APIResponse(responseCode = "500", description = "Erreur serveur")
- })
- List searchLogs(
- @QueryParam("acteur") String acteurUsername,
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin,
- @QueryParam("typeAction") TypeActionAudit typeAction,
- @QueryParam("ressourceType") String ressourceType,
- @QueryParam("succes") Boolean succes,
- @QueryParam("page") @DefaultValue("0") int page,
- @QueryParam("pageSize") @DefaultValue("50") int pageSize);
-
- @GET
- @Path("/actor/{acteurUsername}")
- @Operation(summary = "Récupérer les logs d'un acteur", description = "Liste les derniers logs d'un utilisateur")
- List getLogsByActor(
- @Parameter(description = "Username de l'acteur") @PathParam("acteurUsername") String acteurUsername,
- @Parameter(description = "Nombre de logs à retourner") @QueryParam("limit") @DefaultValue("100") int limit);
-
- @GET
- @Path("/resource/{ressourceType}/{ressourceId}")
- @Operation(summary = "Récupérer les logs d'une ressource", description = "Liste les derniers logs d'une ressource spécifique")
- List getLogsByResource(
- @PathParam("ressourceType") String ressourceType,
- @PathParam("ressourceId") String ressourceId,
- @QueryParam("limit") @DefaultValue("100") int limit);
-
- @GET
- @Path("/action/{typeAction}")
- @Operation(summary = "Récupérer les logs par type d'action", description = "Liste les logs d'un type d'action spécifique")
- List getLogsByAction(
- @PathParam("typeAction") TypeActionAudit typeAction,
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin,
- @QueryParam("limit") @DefaultValue("100") int limit);
-
- @GET
- @Path("/stats/actions")
- @Operation(summary = "Statistiques par type d'action", description = "Retourne le nombre de logs par type d'action")
- Map getActionStatistics(
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin);
-
- @GET
- @Path("/stats/users")
- @Operation(summary = "Statistiques par utilisateur", description = "Retourne le nombre d'actions par utilisateur")
- Map getUserActivityStatistics(
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin);
-
- @GET
- @Path("/stats/failures")
- @Operation(summary = "Comptage des échecs", description = "Retourne le nombre d'échecs sur une période")
- CountDTO getFailureCount(
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin);
-
- @GET
- @Path("/stats/success")
- @Operation(summary = "Comptage des succès", description = "Retourne le nombre de succès sur une période")
- CountDTO getSuccessCount(
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin);
-
- @GET
- @Path("/export/csv")
- @Produces(MediaType.TEXT_PLAIN)
- @Operation(summary = "Exporter les logs en CSV", description = "Génère un fichier CSV des logs d'audit")
- Response exportLogsToCSV(
- @QueryParam("dateDebut") String dateDebut,
- @QueryParam("dateFin") String dateFin);
-
- @DELETE
- @Path("/purge")
- @Operation(summary = "Purger les anciens logs", description = "Supprime les logs de plus de X jours")
- void purgeOldLogs(
- @QueryParam("joursAnciennete") @DefaultValue("90") int joursAnciennete);
-}
+package dev.lions.user.manager.api;
+
+import dev.lions.user.manager.dto.audit.AuditLogDTO;
+import dev.lions.user.manager.dto.common.CountDTO;
+import dev.lions.user.manager.enums.audit.TypeActionAudit;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.media.Content;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Interface JAX-RS pour l'API d'audit.
+ */
+@Path("/api/audit")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@Tag(name = "Audit", description = "Consultation des logs d'audit et statistiques")
+public interface AuditResourceApi {
+
+ @POST
+ @Path("/search")
+ @Operation(summary = "Rechercher des logs d'audit", description = "Recherche avancée de logs selon critères")
+ @APIResponses({
+ @APIResponse(responseCode = "200", description = "Résultats de recherche", content = @Content(schema = @Schema(implementation = AuditLogDTO.class, type = org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY))),
+ @APIResponse(responseCode = "500", description = "Erreur serveur")
+ })
+ List searchLogs(
+ @QueryParam("acteur") String acteurUsername,
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin,
+ @QueryParam("typeAction") TypeActionAudit typeAction,
+ @QueryParam("ressourceType") String ressourceType,
+ @QueryParam("succes") Boolean succes,
+ @QueryParam("page") @DefaultValue("0") int page,
+ @QueryParam("pageSize") @DefaultValue("50") int pageSize);
+
+ @GET
+ @Path("/actor/{acteurUsername}")
+ @Operation(summary = "Récupérer les logs d'un acteur", description = "Liste les derniers logs d'un utilisateur")
+ List getLogsByActor(
+ @Parameter(description = "Username de l'acteur") @PathParam("acteurUsername") String acteurUsername,
+ @Parameter(description = "Nombre de logs à retourner") @QueryParam("limit") @DefaultValue("100") int limit);
+
+ @GET
+ @Path("/resource/{ressourceType}/{ressourceId}")
+ @Operation(summary = "Récupérer les logs d'une ressource", description = "Liste les derniers logs d'une ressource spécifique")
+ List getLogsByResource(
+ @PathParam("ressourceType") String ressourceType,
+ @PathParam("ressourceId") String ressourceId,
+ @QueryParam("limit") @DefaultValue("100") int limit);
+
+ @GET
+ @Path("/action/{typeAction}")
+ @Operation(summary = "Récupérer les logs par type d'action", description = "Liste les logs d'un type d'action spécifique")
+ List getLogsByAction(
+ @PathParam("typeAction") TypeActionAudit typeAction,
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin,
+ @QueryParam("limit") @DefaultValue("100") int limit);
+
+ @GET
+ @Path("/stats/actions")
+ @Operation(summary = "Statistiques par type d'action", description = "Retourne le nombre de logs par type d'action")
+ Map getActionStatistics(
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin);
+
+ @GET
+ @Path("/stats/users")
+ @Operation(summary = "Statistiques par utilisateur", description = "Retourne le nombre d'actions par utilisateur")
+ Map getUserActivityStatistics(
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin);
+
+ @GET
+ @Path("/stats/failures")
+ @Operation(summary = "Comptage des échecs", description = "Retourne le nombre d'échecs sur une période")
+ CountDTO getFailureCount(
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin);
+
+ @GET
+ @Path("/stats/success")
+ @Operation(summary = "Comptage des succès", description = "Retourne le nombre de succès sur une période")
+ CountDTO getSuccessCount(
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin);
+
+ @GET
+ @Path("/export/csv")
+ @Produces(MediaType.TEXT_PLAIN)
+ @Operation(summary = "Exporter les logs en CSV", description = "Génère un fichier CSV des logs d'audit")
+ Response exportLogsToCSV(
+ @QueryParam("dateDebut") String dateDebut,
+ @QueryParam("dateFin") String dateFin);
+
+ @DELETE
+ @Path("/purge")
+ @Operation(summary = "Purger les anciens logs", description = "Supprime les logs de plus de X jours")
+ void purgeOldLogs(
+ @QueryParam("joursAnciennete") @DefaultValue("90") int joursAnciennete);
+}
diff --git a/src/main/java/dev/lions/user/manager/api/RealmAssignmentResourceApi.java b/src/main/java/dev/lions/user/manager/api/RealmAssignmentResourceApi.java
index 5cde415..6e1b82d 100644
--- a/src/main/java/dev/lions/user/manager/api/RealmAssignmentResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/RealmAssignmentResourceApi.java
@@ -1,103 +1,103 @@
-package dev.lions.user.manager.api;
-
-import dev.lions.user.manager.dto.realm.AuthorizedRealmsDTO;
-import dev.lions.user.manager.dto.realm.RealmAccessCheckDTO;
-import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotNull;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.media.Content;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-import java.util.List;
-
-/**
- * Interface JAX-RS pour l'API de gestion des affectations de realms.
- */
-@Path("/api/realm-assignments")
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-@Tag(name = "Realm Assignments", description = "Gestion des affectations de realms (contrôle d'accès multi-tenant)")
-public interface RealmAssignmentResourceApi {
-
- @GET
- @Operation(summary = "Lister toutes les affectations", description = "Liste toutes les affectations de realms")
- List getAllAssignments();
-
- @GET
- @Path("/user/{userId}")
- @Operation(summary = "Affectations par utilisateur", description = "Liste les realms assignés à un utilisateur")
- List getAssignmentsByUser(
- @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId);
-
- @GET
- @Path("/realm/{realmName}")
- @Operation(summary = "Affectations par realm", description = "Liste les utilisateurs ayant accès à un realm")
- List getAssignmentsByRealm(
- @Parameter(description = "Nom du realm") @PathParam("realmName") String realmName);
-
- @GET
- @Path("/{assignmentId}")
- @Operation(summary = "Récupérer une affectation", description = "Récupère une affectation par son ID")
- RealmAssignmentDTO getAssignmentById(
- @Parameter(description = "ID de l'affectation") @PathParam("assignmentId") String assignmentId);
-
- @GET
- @Path("/check")
- @Operation(summary = "Vérifier l'accès", description = "Vérifie si un utilisateur peut gérer un realm")
- RealmAccessCheckDTO canManageRealm(
- @Parameter(description = "ID de l'utilisateur") @QueryParam("userId") String userId,
- @Parameter(description = "Nom du realm") @QueryParam("realmName") String realmName);
-
- @GET
- @Path("/authorized-realms/{userId}")
- @Operation(summary = "Realms autorisés", description = "Liste les realms qu'un utilisateur peut gérer")
- AuthorizedRealmsDTO getAuthorizedRealms(
- @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId);
-
- @POST
- @Operation(summary = "Assigner un realm", description = "Assigne un realm à un utilisateur")
- @APIResponses({
- @APIResponse(responseCode = "201", description = "Affectation créée", content = @Content(schema = @Schema(implementation = RealmAssignmentDTO.class)))
- })
- Response assignRealmToUser(@Valid @NotNull RealmAssignmentDTO assignment);
-
- @DELETE
- @Path("/user/{userId}/realm/{realmName}")
- @Operation(summary = "Révoquer un realm", description = "Retire l'accès d'un utilisateur à un realm")
- void revokeRealmFromUser(
- @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId,
- @Parameter(description = "Nom du realm") @PathParam("realmName") String realmName);
-
- @DELETE
- @Path("/user/{userId}")
- @Operation(summary = "Révoquer tous les realms", description = "Retire tous les accès d'un utilisateur")
- void revokeAllRealmsFromUser(
- @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId);
-
- @PUT
- @Path("/{assignmentId}/deactivate")
- @Operation(summary = "Désactiver une affectation", description = "Désactive une affectation sans la supprimer")
- void deactivateAssignment(
- @Parameter(description = "ID de l'affectation") @PathParam("assignmentId") String assignmentId);
-
- @PUT
- @Path("/{assignmentId}/activate")
- @Operation(summary = "Activer une affectation", description = "Réactive une affectation")
- void activateAssignment(
- @Parameter(description = "ID de l'affectation") @PathParam("assignmentId") String assignmentId);
-
- @PUT
- @Path("/super-admin/{userId}")
- @Operation(summary = "Définir super admin", description = "Définit ou retire le statut de super admin")
- void setSuperAdmin(
- @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId,
- @Parameter(description = "Super admin (true/false)") @QueryParam("superAdmin") @NotNull Boolean superAdmin);
-}
+package dev.lions.user.manager.api;
+
+import dev.lions.user.manager.dto.realm.AuthorizedRealmsDTO;
+import dev.lions.user.manager.dto.realm.RealmAccessCheckDTO;
+import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.media.Content;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+import java.util.List;
+
+/**
+ * Interface JAX-RS pour l'API de gestion des affectations de realms.
+ */
+@Path("/api/realm-assignments")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@Tag(name = "Realm Assignments", description = "Gestion des affectations de realms (contrôle d'accès multi-tenant)")
+public interface RealmAssignmentResourceApi {
+
+ @GET
+ @Operation(summary = "Lister toutes les affectations", description = "Liste toutes les affectations de realms")
+ List getAllAssignments();
+
+ @GET
+ @Path("/user/{userId}")
+ @Operation(summary = "Affectations par utilisateur", description = "Liste les realms assignés à un utilisateur")
+ List getAssignmentsByUser(
+ @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId);
+
+ @GET
+ @Path("/realm/{realmName}")
+ @Operation(summary = "Affectations par realm", description = "Liste les utilisateurs ayant accès à un realm")
+ List getAssignmentsByRealm(
+ @Parameter(description = "Nom du realm") @PathParam("realmName") String realmName);
+
+ @GET
+ @Path("/{assignmentId}")
+ @Operation(summary = "Récupérer une affectation", description = "Récupère une affectation par son ID")
+ RealmAssignmentDTO getAssignmentById(
+ @Parameter(description = "ID de l'affectation") @PathParam("assignmentId") String assignmentId);
+
+ @GET
+ @Path("/check")
+ @Operation(summary = "Vérifier l'accès", description = "Vérifie si un utilisateur peut gérer un realm")
+ RealmAccessCheckDTO canManageRealm(
+ @Parameter(description = "ID de l'utilisateur") @QueryParam("userId") String userId,
+ @Parameter(description = "Nom du realm") @QueryParam("realmName") String realmName);
+
+ @GET
+ @Path("/authorized-realms/{userId}")
+ @Operation(summary = "Realms autorisés", description = "Liste les realms qu'un utilisateur peut gérer")
+ AuthorizedRealmsDTO getAuthorizedRealms(
+ @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId);
+
+ @POST
+ @Operation(summary = "Assigner un realm", description = "Assigne un realm à un utilisateur")
+ @APIResponses({
+ @APIResponse(responseCode = "201", description = "Affectation créée", content = @Content(schema = @Schema(implementation = RealmAssignmentDTO.class)))
+ })
+ Response assignRealmToUser(@Valid @NotNull RealmAssignmentDTO assignment);
+
+ @DELETE
+ @Path("/user/{userId}/realm/{realmName}")
+ @Operation(summary = "Révoquer un realm", description = "Retire l'accès d'un utilisateur à un realm")
+ void revokeRealmFromUser(
+ @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId,
+ @Parameter(description = "Nom du realm") @PathParam("realmName") String realmName);
+
+ @DELETE
+ @Path("/user/{userId}")
+ @Operation(summary = "Révoquer tous les realms", description = "Retire tous les accès d'un utilisateur")
+ void revokeAllRealmsFromUser(
+ @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId);
+
+ @PUT
+ @Path("/{assignmentId}/deactivate")
+ @Operation(summary = "Désactiver une affectation", description = "Désactive une affectation sans la supprimer")
+ void deactivateAssignment(
+ @Parameter(description = "ID de l'affectation") @PathParam("assignmentId") String assignmentId);
+
+ @PUT
+ @Path("/{assignmentId}/activate")
+ @Operation(summary = "Activer une affectation", description = "Réactive une affectation")
+ void activateAssignment(
+ @Parameter(description = "ID de l'affectation") @PathParam("assignmentId") String assignmentId);
+
+ @PUT
+ @Path("/super-admin/{userId}")
+ @Operation(summary = "Définir super admin", description = "Définit ou retire le statut de super admin")
+ void setSuperAdmin(
+ @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId,
+ @Parameter(description = "Super admin (true/false)") @QueryParam("superAdmin") @NotNull Boolean superAdmin);
+}
diff --git a/src/main/java/dev/lions/user/manager/api/RealmResourceApi.java b/src/main/java/dev/lions/user/manager/api/RealmResourceApi.java
index 0b86bd3..f9c474d 100644
--- a/src/main/java/dev/lions/user/manager/api/RealmResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/RealmResourceApi.java
@@ -1,44 +1,44 @@
-package dev.lions.user.manager.api;
-
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.PathParam;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.media.Content;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-import java.util.List;
-
-/**
- * Interface JAX-RS pour la gestion des realms Keycloak.
- */
-@Path("/api/realms")
-@Produces(MediaType.APPLICATION_JSON)
-@Tag(name = "Realms", description = "Gestion des realms Keycloak")
-public interface RealmResourceApi {
-
- @GET
- @Path("/list")
- @Operation(summary = "Lister tous les realms", description = "Récupère la liste de tous les realms disponibles dans Keycloak")
- @APIResponses({
- @APIResponse(responseCode = "200", description = "Liste des realms", content = @Content(schema = @Schema(type = org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY, implementation = String.class))),
- @APIResponse(responseCode = "500", description = "Erreur serveur")
- })
- List getAllRealms();
-
- @GET
- @Path("/{realm}/clients")
- @Operation(summary = "Lister les clients d'un realm", description = "Récupère la liste des clientId de tous les clients d'un realm")
- @APIResponses({
- @APIResponse(responseCode = "200", description = "Liste des clients"),
- @APIResponse(responseCode = "500", description = "Erreur serveur")
- })
- List getRealmClients(
- @Parameter(description = "Nom du realm") @PathParam("realm") String realmName);
-}
+package dev.lions.user.manager.api;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.media.Content;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+import java.util.List;
+
+/**
+ * Interface JAX-RS pour la gestion des realms Keycloak.
+ */
+@Path("/api/realms")
+@Produces(MediaType.APPLICATION_JSON)
+@Tag(name = "Realms", description = "Gestion des realms Keycloak")
+public interface RealmResourceApi {
+
+ @GET
+ @Path("/list")
+ @Operation(summary = "Lister tous les realms", description = "Récupère la liste de tous les realms disponibles dans Keycloak")
+ @APIResponses({
+ @APIResponse(responseCode = "200", description = "Liste des realms", content = @Content(schema = @Schema(type = org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY, implementation = String.class))),
+ @APIResponse(responseCode = "500", description = "Erreur serveur")
+ })
+ List getAllRealms();
+
+ @GET
+ @Path("/{realm}/clients")
+ @Operation(summary = "Lister les clients d'un realm", description = "Récupère la liste des clientId de tous les clients d'un realm")
+ @APIResponses({
+ @APIResponse(responseCode = "200", description = "Liste des clients"),
+ @APIResponse(responseCode = "500", description = "Erreur serveur")
+ })
+ List getRealmClients(
+ @Parameter(description = "Nom du realm") @PathParam("realm") String realmName);
+}
diff --git a/src/main/java/dev/lions/user/manager/api/RoleResourceApi.java b/src/main/java/dev/lions/user/manager/api/RoleResourceApi.java
index 3e4b60b..423328a 100644
--- a/src/main/java/dev/lions/user/manager/api/RoleResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/RoleResourceApi.java
@@ -1,163 +1,163 @@
-package dev.lions.user.manager.api;
-
-import dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO;
-import dev.lions.user.manager.dto.role.RoleDTO;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotNull;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.media.Content;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-import java.util.List;
-
-/**
- * Interface JAX-RS pour la gestion des rôles Keycloak.
- */
-@Path("/api/roles")
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-@Tag(name = "Roles", description = "Gestion des rôles Keycloak (realm et client)")
-public interface RoleResourceApi {
-
- // ==================== Endpoints Realm Roles ====================
-
- @POST
- @Path("/realm")
- @Operation(summary = "Créer un rôle realm", description = "Crée un nouveau rôle au niveau du realm")
- @APIResponses({
- @APIResponse(responseCode = "201", description = "Rôle créé", content = @Content(schema = @Schema(implementation = RoleDTO.class)))
- })
- Response createRealmRole(
- @Valid @NotNull RoleDTO roleDTO,
- @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
-
- @GET
- @Path("/realm/{roleName}")
- @Operation(summary = "Récupérer un rôle realm par nom", description = "Récupère les détails d'un rôle realm")
- RoleDTO getRealmRole(
- @Parameter(description = "Nom du rôle") @PathParam("roleName") String roleName,
- @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
-
- @GET
- @Path("/realm")
- @Operation(summary = "Lister tous les rôles realm", description = "Liste tous les rôles du realm")
- List getAllRealmRoles(
- @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
-
- @PUT
- @Path("/realm/{roleName}")
- @Operation(summary = "Mettre à jour un rôle realm", description = "Met à jour les informations d'un rôle realm")
- RoleDTO updateRealmRole(
- @PathParam("roleName") String roleName,
- @Valid @NotNull RoleDTO roleDTO,
- @QueryParam("realm") String realmName);
-
- @DELETE
- @Path("/realm/{roleName}")
- @Operation(summary = "Supprimer un rôle realm", description = "Supprime un rôle realm")
- void deleteRealmRole(
- @PathParam("roleName") String roleName,
- @QueryParam("realm") String realmName);
-
- // ==================== Endpoints Client Roles ====================
-
- @POST
- @Path("/client/{clientId}")
- @Operation(summary = "Créer un rôle client", description = "Crée un nouveau rôle pour un client spécifique")
- @APIResponses({
- @APIResponse(responseCode = "201", description = "Rôle créé", content = @Content(schema = @Schema(implementation = RoleDTO.class)))
- })
- Response createClientRole(
- @PathParam("clientId") String clientId,
- @Valid @NotNull RoleDTO roleDTO,
- @QueryParam("realm") String realmName);
-
- @GET
- @Path("/client/{clientId}/{roleName}")
- @Operation(summary = "Récupérer un rôle client par nom", description = "Récupère les détails d'un rôle client")
- RoleDTO getClientRole(
- @PathParam("clientId") String clientId,
- @PathParam("roleName") String roleName,
- @QueryParam("realm") String realmName);
-
- @GET
- @Path("/client/{clientId}")
- @Operation(summary = "Lister tous les rôles d'un client", description = "Liste tous les rôles d'un client spécifique")
- List getAllClientRoles(
- @PathParam("clientId") String clientId,
- @QueryParam("realm") String realmName);
-
- @DELETE
- @Path("/client/{clientId}/{roleName}")
- @Operation(summary = "Supprimer un rôle client", description = "Supprime un rôle d'un client")
- void deleteClientRole(
- @PathParam("clientId") String clientId,
- @PathParam("roleName") String roleName,
- @QueryParam("realm") String realmName);
-
- // ==================== Endpoints Attribution de rôles ====================
-
- @POST
- @Path("/assign/realm/{userId}")
- @Operation(summary = "Attribuer des rôles realm à un utilisateur", description = "Assigne un ou plusieurs rôles realm à un utilisateur")
- void assignRealmRoles(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName,
- @NotNull RoleAssignmentRequestDTO request);
-
- @POST
- @Path("/revoke/realm/{userId}")
- @Operation(summary = "Révoquer des rôles realm d'un utilisateur", description = "Révoque un ou plusieurs rôles realm d'un utilisateur")
- void revokeRealmRoles(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName,
- @NotNull RoleAssignmentRequestDTO request);
-
- @POST
- @Path("/assign/client/{clientId}/{userId}")
- @Operation(summary = "Attribuer des rôles client à un utilisateur", description = "Assigne un ou plusieurs rôles client à un utilisateur")
- void assignClientRoles(
- @PathParam("clientId") String clientId,
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName,
- @NotNull RoleAssignmentRequestDTO request);
-
- @GET
- @Path("/user/realm/{userId}")
- @Operation(summary = "Récupérer les rôles realm d'un utilisateur", description = "Liste tous les rôles realm d'un utilisateur")
- List getUserRealmRoles(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName);
-
- @GET
- @Path("/user/client/{clientId}/{userId}")
- @Operation(summary = "Récupérer les rôles client d'un utilisateur", description = "Liste tous les rôles client d'un utilisateur")
- List getUserClientRoles(
- @PathParam("clientId") String clientId,
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName);
-
- // ==================== Endpoints Rôles composites ====================
-
- @POST
- @Path("/composite/{roleName}/add")
- @Operation(summary = "Ajouter des rôles composites", description = "Ajoute des rôles composites à un rôle")
- void addComposites(
- @PathParam("roleName") String roleName,
- @QueryParam("realm") String realmName,
- @NotNull RoleAssignmentRequestDTO request);
-
- @GET
- @Path("/composite/{roleName}")
- @Operation(summary = "Récupérer les rôles composites", description = "Liste tous les rôles composites d'un rôle")
- List getComposites(
- @PathParam("roleName") String roleName,
- @QueryParam("realm") String realmName);
-}
+package dev.lions.user.manager.api;
+
+import dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO;
+import dev.lions.user.manager.dto.role.RoleDTO;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.media.Content;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+import java.util.List;
+
+/**
+ * Interface JAX-RS pour la gestion des rôles Keycloak.
+ */
+@Path("/api/roles")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@Tag(name = "Roles", description = "Gestion des rôles Keycloak (realm et client)")
+public interface RoleResourceApi {
+
+ // ==================== Endpoints Realm Roles ====================
+
+ @POST
+ @Path("/realm")
+ @Operation(summary = "Créer un rôle realm", description = "Crée un nouveau rôle au niveau du realm")
+ @APIResponses({
+ @APIResponse(responseCode = "201", description = "Rôle créé", content = @Content(schema = @Schema(implementation = RoleDTO.class)))
+ })
+ Response createRealmRole(
+ @Valid @NotNull RoleDTO roleDTO,
+ @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/realm/{roleName}")
+ @Operation(summary = "Récupérer un rôle realm par nom", description = "Récupère les détails d'un rôle realm")
+ RoleDTO getRealmRole(
+ @Parameter(description = "Nom du rôle") @PathParam("roleName") String roleName,
+ @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/realm")
+ @Operation(summary = "Lister tous les rôles realm", description = "Liste tous les rôles du realm")
+ List getAllRealmRoles(
+ @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
+
+ @PUT
+ @Path("/realm/{roleName}")
+ @Operation(summary = "Mettre à jour un rôle realm", description = "Met à jour les informations d'un rôle realm")
+ RoleDTO updateRealmRole(
+ @PathParam("roleName") String roleName,
+ @Valid @NotNull RoleDTO roleDTO,
+ @QueryParam("realm") String realmName);
+
+ @DELETE
+ @Path("/realm/{roleName}")
+ @Operation(summary = "Supprimer un rôle realm", description = "Supprime un rôle realm")
+ void deleteRealmRole(
+ @PathParam("roleName") String roleName,
+ @QueryParam("realm") String realmName);
+
+ // ==================== Endpoints Client Roles ====================
+
+ @POST
+ @Path("/client/{clientId}")
+ @Operation(summary = "Créer un rôle client", description = "Crée un nouveau rôle pour un client spécifique")
+ @APIResponses({
+ @APIResponse(responseCode = "201", description = "Rôle créé", content = @Content(schema = @Schema(implementation = RoleDTO.class)))
+ })
+ Response createClientRole(
+ @PathParam("clientId") String clientId,
+ @Valid @NotNull RoleDTO roleDTO,
+ @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/client/{clientId}/{roleName}")
+ @Operation(summary = "Récupérer un rôle client par nom", description = "Récupère les détails d'un rôle client")
+ RoleDTO getClientRole(
+ @PathParam("clientId") String clientId,
+ @PathParam("roleName") String roleName,
+ @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/client/{clientId}")
+ @Operation(summary = "Lister tous les rôles d'un client", description = "Liste tous les rôles d'un client spécifique")
+ List getAllClientRoles(
+ @PathParam("clientId") String clientId,
+ @QueryParam("realm") String realmName);
+
+ @DELETE
+ @Path("/client/{clientId}/{roleName}")
+ @Operation(summary = "Supprimer un rôle client", description = "Supprime un rôle d'un client")
+ void deleteClientRole(
+ @PathParam("clientId") String clientId,
+ @PathParam("roleName") String roleName,
+ @QueryParam("realm") String realmName);
+
+ // ==================== Endpoints Attribution de rôles ====================
+
+ @POST
+ @Path("/assign/realm/{userId}")
+ @Operation(summary = "Attribuer des rôles realm à un utilisateur", description = "Assigne un ou plusieurs rôles realm à un utilisateur")
+ void assignRealmRoles(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName,
+ @NotNull RoleAssignmentRequestDTO request);
+
+ @POST
+ @Path("/revoke/realm/{userId}")
+ @Operation(summary = "Révoquer des rôles realm d'un utilisateur", description = "Révoque un ou plusieurs rôles realm d'un utilisateur")
+ void revokeRealmRoles(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName,
+ @NotNull RoleAssignmentRequestDTO request);
+
+ @POST
+ @Path("/assign/client/{clientId}/{userId}")
+ @Operation(summary = "Attribuer des rôles client à un utilisateur", description = "Assigne un ou plusieurs rôles client à un utilisateur")
+ void assignClientRoles(
+ @PathParam("clientId") String clientId,
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName,
+ @NotNull RoleAssignmentRequestDTO request);
+
+ @GET
+ @Path("/user/realm/{userId}")
+ @Operation(summary = "Récupérer les rôles realm d'un utilisateur", description = "Liste tous les rôles realm d'un utilisateur")
+ List getUserRealmRoles(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/user/client/{clientId}/{userId}")
+ @Operation(summary = "Récupérer les rôles client d'un utilisateur", description = "Liste tous les rôles client d'un utilisateur")
+ List getUserClientRoles(
+ @PathParam("clientId") String clientId,
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName);
+
+ // ==================== Endpoints Rôles composites ====================
+
+ @POST
+ @Path("/composite/{roleName}/add")
+ @Operation(summary = "Ajouter des rôles composites", description = "Ajoute des rôles composites à un rôle")
+ void addComposites(
+ @PathParam("roleName") String roleName,
+ @QueryParam("realm") String realmName,
+ @NotNull RoleAssignmentRequestDTO request);
+
+ @GET
+ @Path("/composite/{roleName}")
+ @Operation(summary = "Récupérer les rôles composites", description = "Liste tous les rôles composites d'un rôle")
+ List getComposites(
+ @PathParam("roleName") String roleName,
+ @QueryParam("realm") String realmName);
+}
diff --git a/src/main/java/dev/lions/user/manager/api/SyncResourceApi.java b/src/main/java/dev/lions/user/manager/api/SyncResourceApi.java
index 45d4670..8bf0717 100644
--- a/src/main/java/dev/lions/user/manager/api/SyncResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/SyncResourceApi.java
@@ -1,54 +1,54 @@
-package dev.lions.user.manager.api;
-
-import dev.lions.user.manager.dto.sync.HealthStatusDTO;
-import dev.lions.user.manager.dto.sync.SyncConsistencyDTO;
-import dev.lions.user.manager.dto.sync.SyncHistoryDTO;
-import dev.lions.user.manager.dto.sync.SyncResultDTO;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-/**
- * Interface JAX-RS définissant le contrat de l'API de synchronisation.
- * Cette interface doit être implémentée par le serveur et utilisée par le
- * client (via MicroProfile Rest Client).
- */
-@Path("/api/sync")
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-@Tag(name = "Sync", description = "Synchronisation avec Keycloak et health checks")
-public interface SyncResourceApi {
-
- @GET
- @Path("/health/keycloak")
- @Operation(summary = "Vérifier la santé de Keycloak", description = "Retourne le statut de santé de Keycloak")
- HealthStatusDTO checkKeycloakHealth();
-
- @POST
- @Path("/users")
- @Operation(summary = "Synchroniser les utilisateurs", description = "Synchronise tous les utilisateurs depuis Keycloak")
- SyncResultDTO syncUsers(@QueryParam("realm") String realmName);
-
- @POST
- @Path("/roles")
- @Operation(summary = "Synchroniser les rôles", description = "Synchronise les rôles (realm et/ou client)")
- SyncResultDTO syncRoles(
- @QueryParam("realm") String realmName,
- @QueryParam("clientName") String clientName);
-
- @GET
- @Path("/consistency")
- @Operation(summary = "Vérifier la cohérence des données", description = "Compare le cache local et Keycloak pour un realm")
- SyncConsistencyDTO checkDataConsistency(@QueryParam("realm") String realmName);
-
- @GET
- @Path("/status")
- @Operation(summary = "Statut de la dernière synchro", description = "Retourne le statut de la dernière synchronisation du realm")
- SyncHistoryDTO getLastSyncStatus(@QueryParam("realm") String realmName);
-
- @POST
- @Path("/force")
- @Operation(summary = "Forcer une synchro", description = "Lance une synchronisation complète du realm (users + roles)")
- SyncHistoryDTO forceSyncRealm(@QueryParam("realm") String realmName);
-}
+package dev.lions.user.manager.api;
+
+import dev.lions.user.manager.dto.sync.HealthStatusDTO;
+import dev.lions.user.manager.dto.sync.SyncConsistencyDTO;
+import dev.lions.user.manager.dto.sync.SyncHistoryDTO;
+import dev.lions.user.manager.dto.sync.SyncResultDTO;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+/**
+ * Interface JAX-RS définissant le contrat de l'API de synchronisation.
+ * Cette interface doit être implémentée par le serveur et utilisée par le
+ * client (via MicroProfile Rest Client).
+ */
+@Path("/api/sync")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@Tag(name = "Sync", description = "Synchronisation avec Keycloak et health checks")
+public interface SyncResourceApi {
+
+ @GET
+ @Path("/health/keycloak")
+ @Operation(summary = "Vérifier la santé de Keycloak", description = "Retourne le statut de santé de Keycloak")
+ HealthStatusDTO checkKeycloakHealth();
+
+ @POST
+ @Path("/users")
+ @Operation(summary = "Synchroniser les utilisateurs", description = "Synchronise tous les utilisateurs depuis Keycloak")
+ SyncResultDTO syncUsers(@QueryParam("realm") String realmName);
+
+ @POST
+ @Path("/roles")
+ @Operation(summary = "Synchroniser les rôles", description = "Synchronise les rôles (realm et/ou client)")
+ SyncResultDTO syncRoles(
+ @QueryParam("realm") String realmName,
+ @QueryParam("clientName") String clientName);
+
+ @GET
+ @Path("/consistency")
+ @Operation(summary = "Vérifier la cohérence des données", description = "Compare le cache local et Keycloak pour un realm")
+ SyncConsistencyDTO checkDataConsistency(@QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/status")
+ @Operation(summary = "Statut de la dernière synchro", description = "Retourne le statut de la dernière synchronisation du realm")
+ SyncHistoryDTO getLastSyncStatus(@QueryParam("realm") String realmName);
+
+ @POST
+ @Path("/force")
+ @Operation(summary = "Forcer une synchro", description = "Lance une synchronisation complète du realm (users + roles)")
+ SyncHistoryDTO forceSyncRealm(@QueryParam("realm") String realmName);
+}
diff --git a/src/main/java/dev/lions/user/manager/api/UserMetricsResourceApi.java b/src/main/java/dev/lions/user/manager/api/UserMetricsResourceApi.java
index 90e5d80..0bf4fda 100644
--- a/src/main/java/dev/lions/user/manager/api/UserMetricsResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/UserMetricsResourceApi.java
@@ -1,32 +1,32 @@
-package dev.lions.user.manager.api;
-
-import dev.lions.user.manager.dto.common.UserSessionStatsDTO;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.QueryParam;
-import jakarta.ws.rs.core.MediaType;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-/**
- * API de métriques liées aux utilisateurs (sessions, utilisateurs en ligne, etc.).
- */
-@Path("/api/metrics/users")
-@Produces(MediaType.APPLICATION_JSON)
-@Tag(name = "User Metrics", description = "Statistiques sur les utilisateurs et leurs sessions")
-public interface UserMetricsResourceApi {
-
- @GET
- @Path("/sessions")
- @Operation(summary = "Statistiques de sessions utilisateurs",
- description = "Retourne des statistiques agrégées sur les utilisateurs et leurs sessions pour un realm")
- @APIResponses({
- @APIResponse(responseCode = "200", description = "Statistiques retournées avec succès"),
- @APIResponse(responseCode = "500", description = "Erreur serveur")
- })
- UserSessionStatsDTO getUserSessionStats(@QueryParam("realm") String realmName);
-}
-
+package dev.lions.user.manager.api;
+
+import dev.lions.user.manager.dto.common.UserSessionStatsDTO;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.MediaType;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+/**
+ * API de métriques liées aux utilisateurs (sessions, utilisateurs en ligne, etc.).
+ */
+@Path("/api/metrics/users")
+@Produces(MediaType.APPLICATION_JSON)
+@Tag(name = "User Metrics", description = "Statistiques sur les utilisateurs et leurs sessions")
+public interface UserMetricsResourceApi {
+
+ @GET
+ @Path("/sessions")
+ @Operation(summary = "Statistiques de sessions utilisateurs",
+ description = "Retourne des statistiques agrégées sur les utilisateurs et leurs sessions pour un realm")
+ @APIResponses({
+ @APIResponse(responseCode = "200", description = "Statistiques retournées avec succès"),
+ @APIResponse(responseCode = "500", description = "Erreur serveur")
+ })
+ UserSessionStatsDTO getUserSessionStats(@QueryParam("realm") String realmName);
+}
+
diff --git a/src/main/java/dev/lions/user/manager/api/UserResourceApi.java b/src/main/java/dev/lions/user/manager/api/UserResourceApi.java
index f1124aa..a5526f4 100644
--- a/src/main/java/dev/lions/user/manager/api/UserResourceApi.java
+++ b/src/main/java/dev/lions/user/manager/api/UserResourceApi.java
@@ -1,138 +1,138 @@
-package dev.lions.user.manager.api;
-
-import dev.lions.user.manager.dto.importexport.ImportResultDTO;
-import dev.lions.user.manager.dto.user.*;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotNull;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.openapi.annotations.Operation;
-import org.eclipse.microprofile.openapi.annotations.media.Content;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
-import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
-import org.eclipse.microprofile.openapi.annotations.tags.Tag;
-
-import java.util.List;
-
-/**
- * Interface JAX-RS pour la gestion des utilisateurs.
- */
-@Path("/api/users")
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-@Tag(name = "Users", description = "Gestion des utilisateurs Keycloak")
-public interface UserResourceApi {
-
- @POST
- @Path("/search")
- @Operation(summary = "Rechercher des utilisateurs", description = "Recherche d'utilisateurs selon des critères")
- UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria);
-
- @GET
- @Path("/{userId}")
- @Operation(summary = "Récupérer un utilisateur par ID", description = "Récupère les détails d'un utilisateur")
- UserDTO getUserById(
- @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId,
- @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
-
- @GET
- @Operation(summary = "Lister tous les utilisateurs", description = "Liste paginée de tous les utilisateurs")
- UserSearchResultDTO getAllUsers(
- @QueryParam("realm") String realmName,
- @QueryParam("page") @DefaultValue("0") int page,
- @QueryParam("pageSize") @DefaultValue("20") int pageSize);
-
- @POST
- @Operation(summary = "Créer un utilisateur", description = "Crée un nouvel utilisateur dans Keycloak")
- @APIResponses({
- @APIResponse(responseCode = "201", description = "Utilisateur créé", content = @Content(schema = @Schema(implementation = UserDTO.class)))
- })
- Response createUser(
- @Valid @NotNull UserDTO user,
- @QueryParam("realm") String realmName);
-
- @PUT
- @Path("/{userId}")
- @Operation(summary = "Mettre à jour un utilisateur", description = "Met à jour les informations d'un utilisateur")
- UserDTO updateUser(
- @PathParam("userId") String userId,
- @Valid @NotNull UserDTO user,
- @QueryParam("realm") String realmName);
-
- @DELETE
- @Path("/{userId}")
- @Operation(summary = "Supprimer un utilisateur", description = "Supprime un utilisateur (soft ou hard delete)")
- void deleteUser(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName,
- @QueryParam("hardDelete") @DefaultValue("false") boolean hardDelete);
-
- @POST
- @Path("/{userId}/activate")
- @Operation(summary = "Activer un utilisateur", description = "Active un utilisateur désactivé")
- void activateUser(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName);
-
- @POST
- @Path("/{userId}/deactivate")
- @Operation(summary = "Désactiver un utilisateur", description = "Désactive un utilisateur")
- void deactivateUser(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName,
- @QueryParam("raison") String raison);
-
- @POST
- @Path("/{userId}/reset-password")
- @Operation(summary = "Réinitialiser le mot de passe", description = "Définit un nouveau mot de passe pour l'utilisateur")
- void resetPassword(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName,
- @NotNull PasswordResetRequestDTO request);
-
- @POST
- @Path("/{userId}/send-verification-email")
- @Operation(summary = "Envoyer email de vérification", description = "Envoie un email de vérification à l'utilisateur")
- @APIResponses({
- @APIResponse(responseCode = "202", description = "Demande acceptée (email envoyé ou tentative effectuée)"),
- @APIResponse(responseCode = "404", description = "Utilisateur non trouvé")
- })
- Response sendVerificationEmail(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName);
-
- @POST
- @Path("/{userId}/logout-sessions")
- @Operation(summary = "Déconnecter toutes les sessions", description = "Révoque toutes les sessions actives de l'utilisateur")
- SessionsRevokedDTO logoutAllSessions(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName);
-
- @GET
- @Path("/{userId}/sessions")
- @Operation(summary = "Récupérer les sessions actives", description = "Liste les sessions actives de l'utilisateur")
- @APIResponses({
- @APIResponse(responseCode = "200", description = "Liste des sessions", content = @Content(schema = @Schema(type = org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY, implementation = String.class)))
- })
- List getActiveSessions(
- @PathParam("userId") String userId,
- @QueryParam("realm") String realmName);
-
- @GET
- @Path("/export/csv")
- @Produces("text/csv")
- @Operation(summary = "Exporter les utilisateurs en CSV", description = "Exporte la liste des utilisateurs du realm au format CSV")
- Response exportUsersToCSV(@QueryParam("realm") String realmName);
-
- @POST
- @Path("/import/csv")
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces(MediaType.APPLICATION_JSON)
- @Operation(summary = "Importer des utilisateurs depuis un CSV", description = "Importe des utilisateurs à partir d'un fichier CSV")
- ImportResultDTO importUsersFromCSV(
- @QueryParam("realm") String realmName,
- String csvContent);
-}
+package dev.lions.user.manager.api;
+
+import dev.lions.user.manager.dto.importexport.ImportResultDTO;
+import dev.lions.user.manager.dto.user.*;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.media.Content;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+import java.util.List;
+
+/**
+ * Interface JAX-RS pour la gestion des utilisateurs.
+ */
+@Path("/api/users")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@Tag(name = "Users", description = "Gestion des utilisateurs Keycloak")
+public interface UserResourceApi {
+
+ @POST
+ @Path("/search")
+ @Operation(summary = "Rechercher des utilisateurs", description = "Recherche d'utilisateurs selon des critères")
+ UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria);
+
+ @GET
+ @Path("/{userId}")
+ @Operation(summary = "Récupérer un utilisateur par ID", description = "Récupère les détails d'un utilisateur")
+ UserDTO getUserById(
+ @Parameter(description = "ID de l'utilisateur") @PathParam("userId") String userId,
+ @Parameter(description = "Nom du realm") @QueryParam("realm") String realmName);
+
+ @GET
+ @Operation(summary = "Lister tous les utilisateurs", description = "Liste paginée de tous les utilisateurs")
+ UserSearchResultDTO getAllUsers(
+ @QueryParam("realm") String realmName,
+ @QueryParam("page") @DefaultValue("0") int page,
+ @QueryParam("pageSize") @DefaultValue("20") int pageSize);
+
+ @POST
+ @Operation(summary = "Créer un utilisateur", description = "Crée un nouvel utilisateur dans Keycloak")
+ @APIResponses({
+ @APIResponse(responseCode = "201", description = "Utilisateur créé", content = @Content(schema = @Schema(implementation = UserDTO.class)))
+ })
+ Response createUser(
+ @Valid @NotNull UserDTO user,
+ @QueryParam("realm") String realmName);
+
+ @PUT
+ @Path("/{userId}")
+ @Operation(summary = "Mettre à jour un utilisateur", description = "Met à jour les informations d'un utilisateur")
+ UserDTO updateUser(
+ @PathParam("userId") String userId,
+ @Valid @NotNull UserDTO user,
+ @QueryParam("realm") String realmName);
+
+ @DELETE
+ @Path("/{userId}")
+ @Operation(summary = "Supprimer un utilisateur", description = "Supprime un utilisateur (soft ou hard delete)")
+ void deleteUser(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName,
+ @QueryParam("hardDelete") @DefaultValue("false") boolean hardDelete);
+
+ @POST
+ @Path("/{userId}/activate")
+ @Operation(summary = "Activer un utilisateur", description = "Active un utilisateur désactivé")
+ void activateUser(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName);
+
+ @POST
+ @Path("/{userId}/deactivate")
+ @Operation(summary = "Désactiver un utilisateur", description = "Désactive un utilisateur")
+ void deactivateUser(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName,
+ @QueryParam("raison") String raison);
+
+ @POST
+ @Path("/{userId}/reset-password")
+ @Operation(summary = "Réinitialiser le mot de passe", description = "Définit un nouveau mot de passe pour l'utilisateur")
+ void resetPassword(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName,
+ @NotNull PasswordResetRequestDTO request);
+
+ @POST
+ @Path("/{userId}/send-verification-email")
+ @Operation(summary = "Envoyer email de vérification", description = "Envoie un email de vérification à l'utilisateur")
+ @APIResponses({
+ @APIResponse(responseCode = "202", description = "Demande acceptée (email envoyé ou tentative effectuée)"),
+ @APIResponse(responseCode = "404", description = "Utilisateur non trouvé")
+ })
+ Response sendVerificationEmail(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName);
+
+ @POST
+ @Path("/{userId}/logout-sessions")
+ @Operation(summary = "Déconnecter toutes les sessions", description = "Révoque toutes les sessions actives de l'utilisateur")
+ SessionsRevokedDTO logoutAllSessions(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/{userId}/sessions")
+ @Operation(summary = "Récupérer les sessions actives", description = "Liste les sessions actives de l'utilisateur")
+ @APIResponses({
+ @APIResponse(responseCode = "200", description = "Liste des sessions", content = @Content(schema = @Schema(type = org.eclipse.microprofile.openapi.annotations.enums.SchemaType.ARRAY, implementation = String.class)))
+ })
+ List getActiveSessions(
+ @PathParam("userId") String userId,
+ @QueryParam("realm") String realmName);
+
+ @GET
+ @Path("/export/csv")
+ @Produces("text/csv")
+ @Operation(summary = "Exporter les utilisateurs en CSV", description = "Exporte la liste des utilisateurs du realm au format CSV")
+ Response exportUsersToCSV(@QueryParam("realm") String realmName);
+
+ @POST
+ @Path("/import/csv")
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Operation(summary = "Importer des utilisateurs depuis un CSV", description = "Importe des utilisateurs à partir d'un fichier CSV")
+ ImportResultDTO importUsersFromCSV(
+ @QueryParam("realm") String realmName,
+ String csvContent);
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/audit/AuditLogDTO.java b/src/main/java/dev/lions/user/manager/dto/audit/AuditLogDTO.java
index 5c42f39..51b7f15 100644
--- a/src/main/java/dev/lions/user/manager/dto/audit/AuditLogDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/audit/AuditLogDTO.java
@@ -1,178 +1,178 @@
-package dev.lions.user.manager.dto.audit;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.user.manager.dto.base.BaseDTO;
-import dev.lions.user.manager.enums.audit.TypeActionAudit;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-import lombok.experimental.SuperBuilder;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.time.LocalDateTime;
-import java.util.Map;
-
-/**
- * DTO représentant une entrée d'audit
- * Enregistre toutes les actions effectuées via l'API de gestion
- */
-@Data
-@SuperBuilder
-@NoArgsConstructor
-@AllArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Entrée d'audit des actions utilisateur")
-public class AuditLogDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- // Qui a fait l'action
- @Schema(description = "ID de l'utilisateur qui a effectué l'action", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479")
- private String acteurUserId;
-
- @Schema(description = "Username de l'utilisateur qui a effectué l'action", example = "admin@lions.dev")
- private String acteurUsername;
-
- @Schema(description = "Nom complet de l'acteur", example = "Admin Principal")
- private String acteurNomComplet;
-
- @Schema(description = "Rôles de l'acteur au moment de l'action")
- private String acteurRoles;
-
- // Quand
- @Schema(description = "Date et heure de l'action", example = "2025-01-15T10:30:00")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime dateAction;
-
- // Quoi
- @Schema(description = "Type d'action effectuée", example = "USER_CREATE")
- private TypeActionAudit typeAction;
-
- @Schema(description = "Type de ressource affectée", example = "USER")
- private String ressourceType;
-
- @Schema(description = "ID de la ressource affectée", example = "a1b2c3d4-e5f6-7890-1234-567890abcdef")
- private String ressourceId;
-
- @Schema(description = "Nom/Identifiant de la ressource", example = "jdupont")
- private String ressourceName;
-
- // Où
- @Schema(description = "Nom du Realm", example = "btpxpress")
- private String realmName;
-
- @Schema(description = "Adresse IP de l'acteur", example = "192.168.1.100")
- private String ipAddress;
-
- @Schema(description = "User-Agent du client", example = "Mozilla/5.0...")
- private String userAgent;
-
- @Schema(description = "Localisation géographique", example = "Abidjan, Côte d'Ivoire")
- private String geolocation;
-
- // Comment
- @Schema(description = "Endpoint API appelé", example = "/api/users/create")
- private String apiEndpoint;
-
- @Schema(description = "Méthode HTTP", example = "POST")
- private String httpMethod;
-
- // Détails
- @Schema(description = "Description de l'action", example = "Création d'un nouvel utilisateur")
- private String description;
-
- @Schema(description = "Détails de l'action au format JSON")
- private String detailsJson;
-
- @Schema(description = "Ancienne valeur (avant modification)")
- private String oldValue;
-
- @Schema(description = "Nouvelle valeur (après modification)")
- private String newValue;
-
- @Schema(description = "Différences entre ancienne et nouvelle valeur")
- private String diff;
-
- // Résultat
- @Schema(description = "Succès de l'opération", example = "true")
- private Boolean success;
-
- @Schema(description = "Code d'erreur (si échec)", example = "USER_ALREADY_EXISTS")
- private String errorCode;
-
- @Schema(description = "Message d'erreur (si échec)")
- private String errorMessage;
-
- @Schema(description = "Trace d'erreur complète (si échec)")
- private String stackTrace;
-
- // Métadonnées
- @Schema(description = "Durée d'exécution en millisecondes", example = "145")
- private Long executionTimeMs;
-
- @Schema(description = "ID de session/transaction", example = "sess_abc123")
- private String sessionId;
-
- @Schema(description = "ID de corrélation (pour tracer requêtes liées)", example = "corr_xyz789")
- private String correlationId;
-
- @Schema(description = "Raison de l'action", example = "Demande du manager")
- private String raison;
-
- @Schema(description = "Commentaires administratifs", example = "Promotion suite à évaluation annuelle")
- private String commentaires;
-
- @Schema(description = "Métadonnées supplémentaires")
- private Map metadata;
-
- // Flags
- @Schema(description = "Indique si l'action est critique", example = "false")
- private Boolean critique;
-
- @Schema(description = "Indique si l'action nécessite une alerte", example = "false")
- private Boolean requiresAlert;
-
- @Schema(description = "Indique si l'action a été notifiée", example = "true")
- private Boolean notified;
-
- /**
- * Détermine si l'action a réussi
- * @return true si success = true
- */
- public boolean isSuccessful() {
- return Boolean.TRUE.equals(success);
- }
-
- /**
- * Détermine si l'action a échoué
- * @return true si success = false
- */
- public boolean isFailed() {
- return Boolean.FALSE.equals(success);
- }
-
- /**
- * Détermine si l'action est critique
- * @return true si critique = true ou si typeAction est critique
- */
- public boolean isCritique() {
- return Boolean.TRUE.equals(critique) || (typeAction != null && typeAction.isCritical());
- }
-
- /**
- * Retourne un résumé court de l'action
- * @return résumé
- */
- public String getSummary() {
- return String.format("%s: %s effectué par %s sur %s %s",
- dateAction,
- typeAction != null ? typeAction.getLibelle() : "Action inconnue",
- acteurUsername != null ? acteurUsername : "Inconnu",
- ressourceType != null ? ressourceType : "Ressource",
- ressourceName != null ? ressourceName : ressourceId
- );
- }
-}
+package dev.lions.user.manager.dto.audit;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.user.manager.dto.base.BaseDTO;
+import dev.lions.user.manager.enums.audit.TypeActionAudit;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.time.LocalDateTime;
+import java.util.Map;
+
+/**
+ * DTO représentant une entrée d'audit
+ * Enregistre toutes les actions effectuées via l'API de gestion
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Entrée d'audit des actions utilisateur")
+public class AuditLogDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ // Qui a fait l'action
+ @Schema(description = "ID de l'utilisateur qui a effectué l'action", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479")
+ private String acteurUserId;
+
+ @Schema(description = "Username de l'utilisateur qui a effectué l'action", example = "admin@lions.dev")
+ private String acteurUsername;
+
+ @Schema(description = "Nom complet de l'acteur", example = "Admin Principal")
+ private String acteurNomComplet;
+
+ @Schema(description = "Rôles de l'acteur au moment de l'action")
+ private String acteurRoles;
+
+ // Quand
+ @Schema(description = "Date et heure de l'action", example = "2025-01-15T10:30:00")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime dateAction;
+
+ // Quoi
+ @Schema(description = "Type d'action effectuée", example = "USER_CREATE")
+ private TypeActionAudit typeAction;
+
+ @Schema(description = "Type de ressource affectée", example = "USER")
+ private String ressourceType;
+
+ @Schema(description = "ID de la ressource affectée", example = "a1b2c3d4-e5f6-7890-1234-567890abcdef")
+ private String ressourceId;
+
+ @Schema(description = "Nom/Identifiant de la ressource", example = "jdupont")
+ private String ressourceName;
+
+ // Où
+ @Schema(description = "Nom du Realm", example = "btpxpress")
+ private String realmName;
+
+ @Schema(description = "Adresse IP de l'acteur", example = "192.168.1.100")
+ private String ipAddress;
+
+ @Schema(description = "User-Agent du client", example = "Mozilla/5.0...")
+ private String userAgent;
+
+ @Schema(description = "Localisation géographique", example = "Abidjan, Côte d'Ivoire")
+ private String geolocation;
+
+ // Comment
+ @Schema(description = "Endpoint API appelé", example = "/api/users/create")
+ private String apiEndpoint;
+
+ @Schema(description = "Méthode HTTP", example = "POST")
+ private String httpMethod;
+
+ // Détails
+ @Schema(description = "Description de l'action", example = "Création d'un nouvel utilisateur")
+ private String description;
+
+ @Schema(description = "Détails de l'action au format JSON")
+ private String detailsJson;
+
+ @Schema(description = "Ancienne valeur (avant modification)")
+ private String oldValue;
+
+ @Schema(description = "Nouvelle valeur (après modification)")
+ private String newValue;
+
+ @Schema(description = "Différences entre ancienne et nouvelle valeur")
+ private String diff;
+
+ // Résultat
+ @Schema(description = "Succès de l'opération", example = "true")
+ private Boolean success;
+
+ @Schema(description = "Code d'erreur (si échec)", example = "USER_ALREADY_EXISTS")
+ private String errorCode;
+
+ @Schema(description = "Message d'erreur (si échec)")
+ private String errorMessage;
+
+ @Schema(description = "Trace d'erreur complète (si échec)")
+ private String stackTrace;
+
+ // Métadonnées
+ @Schema(description = "Durée d'exécution en millisecondes", example = "145")
+ private Long executionTimeMs;
+
+ @Schema(description = "ID de session/transaction", example = "sess_abc123")
+ private String sessionId;
+
+ @Schema(description = "ID de corrélation (pour tracer requêtes liées)", example = "corr_xyz789")
+ private String correlationId;
+
+ @Schema(description = "Raison de l'action", example = "Demande du manager")
+ private String raison;
+
+ @Schema(description = "Commentaires administratifs", example = "Promotion suite à évaluation annuelle")
+ private String commentaires;
+
+ @Schema(description = "Métadonnées supplémentaires")
+ private Map metadata;
+
+ // Flags
+ @Schema(description = "Indique si l'action est critique", example = "false")
+ private Boolean critique;
+
+ @Schema(description = "Indique si l'action nécessite une alerte", example = "false")
+ private Boolean requiresAlert;
+
+ @Schema(description = "Indique si l'action a été notifiée", example = "true")
+ private Boolean notified;
+
+ /**
+ * Détermine si l'action a réussi
+ * @return true si success = true
+ */
+ public boolean isSuccessful() {
+ return Boolean.TRUE.equals(success);
+ }
+
+ /**
+ * Détermine si l'action a échoué
+ * @return true si success = false
+ */
+ public boolean isFailed() {
+ return Boolean.FALSE.equals(success);
+ }
+
+ /**
+ * Détermine si l'action est critique
+ * @return true si critique = true ou si typeAction est critique
+ */
+ public boolean isCritique() {
+ return Boolean.TRUE.equals(critique) || (typeAction != null && typeAction.isCritical());
+ }
+
+ /**
+ * Retourne un résumé court de l'action
+ * @return résumé
+ */
+ public String getSummary() {
+ return String.format("%s: %s effectué par %s sur %s %s",
+ dateAction,
+ typeAction != null ? typeAction.getLibelle() : "Action inconnue",
+ acteurUsername != null ? acteurUsername : "Inconnu",
+ ressourceType != null ? ressourceType : "Ressource",
+ ressourceName != null ? ressourceName : ressourceId
+ );
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/base/BaseDTO.java b/src/main/java/dev/lions/user/manager/dto/base/BaseDTO.java
index cbfae0b..39825ff 100644
--- a/src/main/java/dev/lions/user/manager/dto/base/BaseDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/base/BaseDTO.java
@@ -1,47 +1,47 @@
-package dev.lions.user.manager.dto.base;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.experimental.SuperBuilder;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * DTO de base pour tous les objets métier
- * Contient les attributs communs (id, dates, audit)
- */
-@Data
-@SuperBuilder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "DTO de base contenant les attributs communs à tous les objets")
-public abstract class BaseDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "Identifiant unique (UUID Keycloak)", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479")
- private String id;
-
- @Schema(description = "Date de création", example = "2025-01-15T10:30:00")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime dateCreation;
-
- @Schema(description = "Date de dernière modification", example = "2025-01-15T14:20:00")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime dateModification;
-
- @Schema(description = "Utilisateur ayant créé l'entité", example = "admin@lions.dev")
- private String creeParUsername;
-
- @Schema(description = "Utilisateur ayant modifié l'entité", example = "superadmin@lions.dev")
- private String modifieParUsername;
-
- @Schema(description = "Numéro de version pour gestion optimiste", example = "1")
- private Long version;
-}
+package dev.lions.user.manager.dto.base;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * DTO de base pour tous les objets métier
+ * Contient les attributs communs (id, dates, audit)
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "DTO de base contenant les attributs communs à tous les objets")
+public abstract class BaseDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "Identifiant unique (UUID Keycloak)", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479")
+ private String id;
+
+ @Schema(description = "Date de création", example = "2025-01-15T10:30:00")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime dateCreation;
+
+ @Schema(description = "Date de dernière modification", example = "2025-01-15T14:20:00")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime dateModification;
+
+ @Schema(description = "Utilisateur ayant créé l'entité", example = "admin@lions.dev")
+ private String creeParUsername;
+
+ @Schema(description = "Utilisateur ayant modifié l'entité", example = "superadmin@lions.dev")
+ private String modifieParUsername;
+
+ @Schema(description = "Numéro de version pour gestion optimiste", example = "1")
+ private Long version;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/common/ApiErrorDTO.java b/src/main/java/dev/lions/user/manager/dto/common/ApiErrorDTO.java
index 79ae915..ddbddcf 100644
--- a/src/main/java/dev/lions/user/manager/dto/common/ApiErrorDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/common/ApiErrorDTO.java
@@ -1,21 +1,21 @@
-package dev.lions.user.manager.dto.common;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Réponse d'erreur standard")
-public class ApiErrorDTO implements Serializable {
- @Schema(description = "Message d'erreur")
- private String message;
-}
+package dev.lions.user.manager.dto.common;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Réponse d'erreur standard")
+public class ApiErrorDTO implements Serializable {
+ @Schema(description = "Message d'erreur")
+ private String message;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/common/CountDTO.java b/src/main/java/dev/lions/user/manager/dto/common/CountDTO.java
index de80897..55f47e2 100644
--- a/src/main/java/dev/lions/user/manager/dto/common/CountDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/common/CountDTO.java
@@ -1,21 +1,21 @@
-package dev.lions.user.manager.dto.common;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Réponse de comptage générique")
-public class CountDTO implements Serializable {
- @Schema(description = "Nombre d'éléments")
- private long count;
-}
+package dev.lions.user.manager.dto.common;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Réponse de comptage générique")
+public class CountDTO implements Serializable {
+ @Schema(description = "Nombre d'éléments")
+ private long count;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/common/UserSessionStatsDTO.java b/src/main/java/dev/lions/user/manager/dto/common/UserSessionStatsDTO.java
index 01840e2..fe810ce 100644
--- a/src/main/java/dev/lions/user/manager/dto/common/UserSessionStatsDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/common/UserSessionStatsDTO.java
@@ -1,32 +1,32 @@
-package dev.lions.user.manager.dto.common;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Statistiques de sessions et d'utilisateurs en ligne pour un realm")
-public class UserSessionStatsDTO implements Serializable {
-
- @Schema(description = "Nom du realm concerné")
- private String realmName;
-
- @Schema(description = "Nombre total d'utilisateurs dans le realm")
- private long totalUsers;
-
- @Schema(description = "Nombre total de sessions actives (approximation)")
- private long activeSessions;
-
- @Schema(description = "Nombre d'utilisateurs considérés comme en ligne (approximation)")
- private long onlineUsers;
-}
-
+package dev.lions.user.manager.dto.common;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Statistiques de sessions et d'utilisateurs en ligne pour un realm")
+public class UserSessionStatsDTO implements Serializable {
+
+ @Schema(description = "Nom du realm concerné")
+ private String realmName;
+
+ @Schema(description = "Nombre total d'utilisateurs dans le realm")
+ private long totalUsers;
+
+ @Schema(description = "Nombre total de sessions actives (approximation)")
+ private long activeSessions;
+
+ @Schema(description = "Nombre d'utilisateurs considérés comme en ligne (approximation)")
+ private long onlineUsers;
+}
+
diff --git a/src/main/java/dev/lions/user/manager/dto/importexport/ImportResultDTO.java b/src/main/java/dev/lions/user/manager/dto/importexport/ImportResultDTO.java
index 27b2c72..026b966 100644
--- a/src/main/java/dev/lions/user/manager/dto/importexport/ImportResultDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/importexport/ImportResultDTO.java
@@ -1,123 +1,123 @@
-package dev.lions.user.manager.dto.importexport;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * DTO représentant le résultat d'un import CSV d'utilisateurs
- * Contient les statistiques et le détail des erreurs rencontrées
- *
- * @author Lions Development Team
- * @version 1.0.0
- * @since 2026-01-02
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Résultat d'un import CSV d'utilisateurs")
-public class ImportResultDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "Nombre total de lignes traitées", example = "100")
- private int totalLines;
-
- @Schema(description = "Nombre d'utilisateurs créés avec succès", example = "95")
- private int successCount;
-
- @Schema(description = "Nombre d'erreurs rencontrées", example = "5")
- private int errorCount;
-
- @Schema(description = "Message de statut global", example = "Import terminé: 95 utilisateurs créés, 5 erreurs")
- private String message;
-
- @Schema(description = "Liste des erreurs détaillées")
- @Builder.Default
- private List errors = new ArrayList<>();
-
- /**
- * Ajoute une erreur au rapport
- */
- public void addError(ImportErrorDTO error) {
- if (errors == null) {
- errors = new ArrayList<>();
- }
- errors.add(error);
- errorCount = errors.size();
- }
-
- /**
- * Génère le message de statut
- */
- public void generateMessage() {
- if (errorCount == 0) {
- message = String.format("✅ Import réussi: %d utilisateur(s) créé(s)", successCount);
- } else {
- message = String.format("⚠️ Import terminé avec erreurs: %d utilisateur(s) créé(s), %d erreur(s)",
- successCount, errorCount);
- }
- }
-
- /**
- * DTO représentant une erreur d'import sur une ligne
- */
- @Data
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- @JsonInclude(JsonInclude.Include.NON_NULL)
- @Schema(description = "Détail d'une erreur d'import")
- public static class ImportErrorDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "Numéro de ligne (1-indexed)", example = "42")
- private int lineNumber;
-
- @Schema(description = "Contenu de la ligne en erreur", example = "john.doe,invalid-email,John,Doe,true")
- private String lineContent;
-
- @Schema(description = "Type d'erreur", example = "VALIDATION_ERROR")
- private ErrorType errorType;
-
- @Schema(description = "Champ concerné par l'erreur", example = "email")
- private String field;
-
- @Schema(description = "Message d'erreur descriptif", example = "Format d'email invalide")
- private String message;
-
- @Schema(description = "Détails techniques de l'erreur")
- private String details;
- }
-
- /**
- * Types d'erreurs possibles lors de l'import
- */
- @Schema(description = "Type d'erreur d'import")
- public enum ErrorType {
- @Schema(description = "Ligne mal formée ou nombre de colonnes incorrect")
- INVALID_FORMAT,
-
- @Schema(description = "Erreur de validation des données")
- VALIDATION_ERROR,
-
- @Schema(description = "Utilisateur déjà existant")
- DUPLICATE_USER,
-
- @Schema(description = "Erreur lors de la création de l'utilisateur")
- CREATION_ERROR,
-
- @Schema(description = "Erreur interne du système")
- SYSTEM_ERROR
- }
-}
+package dev.lions.user.manager.dto.importexport;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * DTO représentant le résultat d'un import CSV d'utilisateurs
+ * Contient les statistiques et le détail des erreurs rencontrées
+ *
+ * @author Lions Development Team
+ * @version 1.0.0
+ * @since 2026-01-02
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Résultat d'un import CSV d'utilisateurs")
+public class ImportResultDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "Nombre total de lignes traitées", example = "100")
+ private int totalLines;
+
+ @Schema(description = "Nombre d'utilisateurs créés avec succès", example = "95")
+ private int successCount;
+
+ @Schema(description = "Nombre d'erreurs rencontrées", example = "5")
+ private int errorCount;
+
+ @Schema(description = "Message de statut global", example = "Import terminé: 95 utilisateurs créés, 5 erreurs")
+ private String message;
+
+ @Schema(description = "Liste des erreurs détaillées")
+ @Builder.Default
+ private List errors = new ArrayList<>();
+
+ /**
+ * Ajoute une erreur au rapport
+ */
+ public void addError(ImportErrorDTO error) {
+ if (errors == null) {
+ errors = new ArrayList<>();
+ }
+ errors.add(error);
+ errorCount = errors.size();
+ }
+
+ /**
+ * Génère le message de statut
+ */
+ public void generateMessage() {
+ if (errorCount == 0) {
+ message = String.format("✅ Import réussi: %d utilisateur(s) créé(s)", successCount);
+ } else {
+ message = String.format("⚠️ Import terminé avec erreurs: %d utilisateur(s) créé(s), %d erreur(s)",
+ successCount, errorCount);
+ }
+ }
+
+ /**
+ * DTO représentant une erreur d'import sur une ligne
+ */
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ @Schema(description = "Détail d'une erreur d'import")
+ public static class ImportErrorDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "Numéro de ligne (1-indexed)", example = "42")
+ private int lineNumber;
+
+ @Schema(description = "Contenu de la ligne en erreur", example = "john.doe,invalid-email,John,Doe,true")
+ private String lineContent;
+
+ @Schema(description = "Type d'erreur", example = "VALIDATION_ERROR")
+ private ErrorType errorType;
+
+ @Schema(description = "Champ concerné par l'erreur", example = "email")
+ private String field;
+
+ @Schema(description = "Message d'erreur descriptif", example = "Format d'email invalide")
+ private String message;
+
+ @Schema(description = "Détails techniques de l'erreur")
+ private String details;
+ }
+
+ /**
+ * Types d'erreurs possibles lors de l'import
+ */
+ @Schema(description = "Type d'erreur d'import")
+ public enum ErrorType {
+ @Schema(description = "Ligne mal formée ou nombre de colonnes incorrect")
+ INVALID_FORMAT,
+
+ @Schema(description = "Erreur de validation des données")
+ VALIDATION_ERROR,
+
+ @Schema(description = "Utilisateur déjà existant")
+ DUPLICATE_USER,
+
+ @Schema(description = "Erreur lors de la création de l'utilisateur")
+ CREATION_ERROR,
+
+ @Schema(description = "Erreur interne du système")
+ SYSTEM_ERROR
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/realm/AuthorizedRealmsDTO.java b/src/main/java/dev/lions/user/manager/dto/realm/AuthorizedRealmsDTO.java
index 3b3f92c..76471f7 100644
--- a/src/main/java/dev/lions/user/manager/dto/realm/AuthorizedRealmsDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/realm/AuthorizedRealmsDTO.java
@@ -1,25 +1,25 @@
-package dev.lions.user.manager.dto.realm;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-import java.util.List;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Liste des realms autorisés pour un utilisateur")
-public class AuthorizedRealmsDTO implements Serializable {
- @Schema(description = "Liste des realms (peut être vide si super admin)")
- private List realms;
-
- @Schema(description = "L'utilisateur est super admin")
- private boolean isSuperAdmin;
-}
+package dev.lions.user.manager.dto.realm;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Liste des realms autorisés pour un utilisateur")
+public class AuthorizedRealmsDTO implements Serializable {
+ @Schema(description = "Liste des realms (peut être vide si super admin)")
+ private List realms;
+
+ @Schema(description = "L'utilisateur est super admin")
+ private boolean isSuperAdmin;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/realm/RealmAccessCheckDTO.java b/src/main/java/dev/lions/user/manager/dto/realm/RealmAccessCheckDTO.java
index e9ac4ab..363cd3b 100644
--- a/src/main/java/dev/lions/user/manager/dto/realm/RealmAccessCheckDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/realm/RealmAccessCheckDTO.java
@@ -1,27 +1,27 @@
-package dev.lions.user.manager.dto.realm;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Réponse de vérification d'accès au realm")
-public class RealmAccessCheckDTO implements Serializable {
- @Schema(description = "L'utilisateur peut gérer le realm")
- private boolean canManage;
-
- @Schema(description = "ID de l'utilisateur")
- private String userId;
-
- @Schema(description = "Nom du realm")
- private String realmName;
-}
+package dev.lions.user.manager.dto.realm;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Réponse de vérification d'accès au realm")
+public class RealmAccessCheckDTO implements Serializable {
+ @Schema(description = "L'utilisateur peut gérer le realm")
+ private boolean canManage;
+
+ @Schema(description = "ID de l'utilisateur")
+ private String userId;
+
+ @Schema(description = "Nom du realm")
+ private String realmName;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTO.java b/src/main/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTO.java
index 1ec3c49..3e72979 100644
--- a/src/main/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTO.java
@@ -1,119 +1,119 @@
-package dev.lions.user.manager.dto.realm;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.user.manager.dto.base.BaseDTO;
-import jakarta.validation.constraints.NotBlank;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-import lombok.experimental.SuperBuilder;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import io.quarkus.runtime.annotations.RegisterForReflection;
-
-import java.time.LocalDateTime;
-
-/**
- * DTO pour assigner ou révoquer l'accès d'un utilisateur à un realm
- * Permet de gérer les permissions multi-tenant
- */
-@Data
-@SuperBuilder
-@NoArgsConstructor
-@AllArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Attribution ou révocation d'accès à un realm")
-@RegisterForReflection
-public class RealmAssignmentDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- @NotBlank(message = "L'ID utilisateur est obligatoire")
- @Schema(description = "ID de l'utilisateur Keycloak", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479", required = true)
- private String userId;
-
- @Schema(description = "Username de l'utilisateur", example = "jdupont")
- private String username;
-
- @Schema(description = "Email de l'utilisateur", example = "jdupont@example.com")
- private String email;
-
- @NotBlank(message = "Le nom du realm est obligatoire")
- @Schema(description = "Nom du realm assigné", example = "btpxpress", required = true)
- private String realmName;
-
- @Schema(description = "Indique si l'utilisateur est super admin (peut gérer tous les realms)", example = "false")
- private Boolean isSuperAdmin;
-
- @Schema(description = "Date d'assignation", example = "2025-01-15T10:30:00")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime assignedAt;
-
- @Schema(description = "Username de l'administrateur qui a fait l'assignation", example = "admin@lions.dev")
- private String assignedBy;
-
- @Schema(description = "Raison de l'assignation", example = "Nouveau gestionnaire du realm client")
- private String raison;
-
- @Schema(description = "Commentaires administratifs", example = "Accès temporaire pour support")
- private String commentaires;
-
- @Schema(description = "Indique si c'est une assignation temporaire", example = "false")
- private Boolean temporaire;
-
- @Schema(description = "Date d'expiration de l'assignation temporaire", example = "2025-12-31T23:59:59")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime dateExpiration;
-
- @Schema(description = "Indique si l'assignation est active", example = "true")
- private Boolean active;
-
- /**
- * Vérifie si l'assignation est temporaire
- * @return true si temporaire
- */
- public boolean isTemporaire() {
- return Boolean.TRUE.equals(temporaire);
- }
-
- /**
- * Vérifie si l'assignation est active
- * @return true si active
- */
- public boolean isActive() {
- return Boolean.TRUE.equals(active);
- }
-
- /**
- * Vérifie si l'assignation a expiré
- * @return true si expirée
- */
- public boolean isExpired() {
- if (!isTemporaire() || dateExpiration == null) {
- return false;
- }
- return LocalDateTime.now().isAfter(dateExpiration);
- }
-
- /**
- * Vérifie si l'utilisateur est super admin
- * @return true si super admin
- */
- public boolean isSuperAdmin() {
- return Boolean.TRUE.equals(isSuperAdmin);
- }
-
- /**
- * Retourne un résumé de l'assignation
- * @return résumé
- */
- public String getSummary() {
- return String.format("Realm '%s' assigné à %s%s",
- realmName,
- username != null ? username : userId,
- isTemporaire() ? " (temporaire)" : ""
- );
- }
-}
+package dev.lions.user.manager.dto.realm;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.user.manager.dto.base.BaseDTO;
+import jakarta.validation.constraints.NotBlank;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+import java.time.LocalDateTime;
+
+/**
+ * DTO pour assigner ou révoquer l'accès d'un utilisateur à un realm
+ * Permet de gérer les permissions multi-tenant
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Attribution ou révocation d'accès à un realm")
+@RegisterForReflection
+public class RealmAssignmentDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotBlank(message = "L'ID utilisateur est obligatoire")
+ @Schema(description = "ID de l'utilisateur Keycloak", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479", required = true)
+ private String userId;
+
+ @Schema(description = "Username de l'utilisateur", example = "jdupont")
+ private String username;
+
+ @Schema(description = "Email de l'utilisateur", example = "jdupont@example.com")
+ private String email;
+
+ @NotBlank(message = "Le nom du realm est obligatoire")
+ @Schema(description = "Nom du realm assigné", example = "btpxpress", required = true)
+ private String realmName;
+
+ @Schema(description = "Indique si l'utilisateur est super admin (peut gérer tous les realms)", example = "false")
+ private Boolean isSuperAdmin;
+
+ @Schema(description = "Date d'assignation", example = "2025-01-15T10:30:00")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime assignedAt;
+
+ @Schema(description = "Username de l'administrateur qui a fait l'assignation", example = "admin@lions.dev")
+ private String assignedBy;
+
+ @Schema(description = "Raison de l'assignation", example = "Nouveau gestionnaire du realm client")
+ private String raison;
+
+ @Schema(description = "Commentaires administratifs", example = "Accès temporaire pour support")
+ private String commentaires;
+
+ @Schema(description = "Indique si c'est une assignation temporaire", example = "false")
+ private Boolean temporaire;
+
+ @Schema(description = "Date d'expiration de l'assignation temporaire", example = "2025-12-31T23:59:59")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime dateExpiration;
+
+ @Schema(description = "Indique si l'assignation est active", example = "true")
+ private Boolean active;
+
+ /**
+ * Vérifie si l'assignation est temporaire
+ * @return true si temporaire
+ */
+ public boolean isTemporaire() {
+ return Boolean.TRUE.equals(temporaire);
+ }
+
+ /**
+ * Vérifie si l'assignation est active
+ * @return true si active
+ */
+ public boolean isActive() {
+ return Boolean.TRUE.equals(active);
+ }
+
+ /**
+ * Vérifie si l'assignation a expiré
+ * @return true si expirée
+ */
+ public boolean isExpired() {
+ if (!isTemporaire() || dateExpiration == null) {
+ return false;
+ }
+ return LocalDateTime.now().isAfter(dateExpiration);
+ }
+
+ /**
+ * Vérifie si l'utilisateur est super admin
+ * @return true si super admin
+ */
+ public boolean isSuperAdmin() {
+ return Boolean.TRUE.equals(isSuperAdmin);
+ }
+
+ /**
+ * Retourne un résumé de l'assignation
+ * @return résumé
+ */
+ public String getSummary() {
+ return String.format("Realm '%s' assigné à %s%s",
+ realmName,
+ username != null ? username : userId,
+ isTemporaire() ? " (temporaire)" : ""
+ );
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentDTO.java b/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentDTO.java
index f2da065..8737758 100644
--- a/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentDTO.java
@@ -1,101 +1,101 @@
-package dev.lions.user.manager.dto.role;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.user.manager.enums.role.TypeRole;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * DTO pour assigner ou révoquer des rôles à un utilisateur
- * Utilisé dans les opérations d'attribution de rôles
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Attribution ou révocation de rôles")
-public class RoleAssignmentDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @NotBlank(message = "L'ID utilisateur est obligatoire")
- @Schema(description = "ID de l'utilisateur cible", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479", required = true)
- private String userId;
-
- @Schema(description = "Username de l'utilisateur cible (optionnel)", example = "jdupont")
- private String username;
-
- @NotEmpty(message = "Au moins un rôle doit être spécifié")
- @Schema(description = "Liste des noms de rôles à attribuer ou révoquer", required = true)
- private List roleNames;
-
- @Schema(description = "Liste des IDs de rôles à attribuer ou révoquer")
- private List roleIds;
-
- @NotNull(message = "Le type de rôle est obligatoire")
- @Schema(description = "Type de rôle", example = "REALM_ROLE", required = true)
- private TypeRole typeRole;
-
- @Schema(description = "Nom du Realm", example = "btpxpress")
- private String realmName;
-
- @Schema(description = "Nom du Client (requis si typeRole = CLIENT_ROLE)", example = "btpxpress-app")
- private String clientName;
-
- @Schema(description = "ID du Client (optionnel)")
- private String clientId;
-
- @Schema(description = "Raison de l'attribution/révocation", example = "Promotion au poste de gestionnaire")
- private String raison;
-
- @Schema(description = "Commentaires administratifs", example = "Demandé par le manager")
- private String commentaires;
-
- @Schema(description = "Indique si c'est une attribution temporaire", example = "false")
- private Boolean temporaire;
-
- @Schema(description = "Date d'expiration de l'attribution temporaire", example = "2025-12-31T23:59:59")
- private String dateExpiration;
-
- @Schema(description = "Indique si les rôles composites doivent être inclus", example = "true")
- @Builder.Default
- private Boolean includeComposites = true;
-
- @Schema(description = "Indique si l'opération doit notifier l'utilisateur", example = "true")
- @Builder.Default
- private Boolean notifyUser = false;
-
- /**
- * Valide que les données nécessaires sont présentes pour un rôle client
- * @return true si valide
- */
- public boolean isValidForClientRole() {
- return typeRole == TypeRole.CLIENT_ROLE && clientName != null && !clientName.isBlank();
- }
-
- /**
- * Valide que les données nécessaires sont présentes pour un rôle realm
- * @return true si valide
- */
- public boolean isValidForRealmRole() {
- return typeRole == TypeRole.REALM_ROLE;
- }
-
- /**
- * Retourne le nombre de rôles à assigner/révoquer
- * @return nombre de rôles
- */
- public int getRoleCount() {
- return roleNames != null ? roleNames.size() : 0;
- }
-}
+package dev.lions.user.manager.dto.role;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.user.manager.enums.role.TypeRole;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * DTO pour assigner ou révoquer des rôles à un utilisateur
+ * Utilisé dans les opérations d'attribution de rôles
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Attribution ou révocation de rôles")
+public class RoleAssignmentDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotBlank(message = "L'ID utilisateur est obligatoire")
+ @Schema(description = "ID de l'utilisateur cible", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479", required = true)
+ private String userId;
+
+ @Schema(description = "Username de l'utilisateur cible (optionnel)", example = "jdupont")
+ private String username;
+
+ @NotEmpty(message = "Au moins un rôle doit être spécifié")
+ @Schema(description = "Liste des noms de rôles à attribuer ou révoquer", required = true)
+ private List roleNames;
+
+ @Schema(description = "Liste des IDs de rôles à attribuer ou révoquer")
+ private List roleIds;
+
+ @NotNull(message = "Le type de rôle est obligatoire")
+ @Schema(description = "Type de rôle", example = "REALM_ROLE", required = true)
+ private TypeRole typeRole;
+
+ @Schema(description = "Nom du Realm", example = "btpxpress")
+ private String realmName;
+
+ @Schema(description = "Nom du Client (requis si typeRole = CLIENT_ROLE)", example = "btpxpress-app")
+ private String clientName;
+
+ @Schema(description = "ID du Client (optionnel)")
+ private String clientId;
+
+ @Schema(description = "Raison de l'attribution/révocation", example = "Promotion au poste de gestionnaire")
+ private String raison;
+
+ @Schema(description = "Commentaires administratifs", example = "Demandé par le manager")
+ private String commentaires;
+
+ @Schema(description = "Indique si c'est une attribution temporaire", example = "false")
+ private Boolean temporaire;
+
+ @Schema(description = "Date d'expiration de l'attribution temporaire", example = "2025-12-31T23:59:59")
+ private String dateExpiration;
+
+ @Schema(description = "Indique si les rôles composites doivent être inclus", example = "true")
+ @Builder.Default
+ private Boolean includeComposites = true;
+
+ @Schema(description = "Indique si l'opération doit notifier l'utilisateur", example = "true")
+ @Builder.Default
+ private Boolean notifyUser = false;
+
+ /**
+ * Valide que les données nécessaires sont présentes pour un rôle client
+ * @return true si valide
+ */
+ public boolean isValidForClientRole() {
+ return typeRole == TypeRole.CLIENT_ROLE && clientName != null && !clientName.isBlank();
+ }
+
+ /**
+ * Valide que les données nécessaires sont présentes pour un rôle realm
+ * @return true si valide
+ */
+ public boolean isValidForRealmRole() {
+ return typeRole == TypeRole.REALM_ROLE;
+ }
+
+ /**
+ * Retourne le nombre de rôles à assigner/révoquer
+ * @return nombre de rôles
+ */
+ public int getRoleCount() {
+ return roleNames != null ? roleNames.size() : 0;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentRequestDTO.java b/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentRequestDTO.java
index e90fa46..84ebb7a 100644
--- a/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentRequestDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/role/RoleAssignmentRequestDTO.java
@@ -1,22 +1,22 @@
-package dev.lions.user.manager.dto.role;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-import java.util.List;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Requête d'attribution ou de révocation de rôles")
-public class RoleAssignmentRequestDTO implements Serializable {
- @Schema(description = "Liste des noms de rôles", required = true)
- private List roleNames;
-}
+package dev.lions.user.manager.dto.role;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Requête d'attribution ou de révocation de rôles")
+public class RoleAssignmentRequestDTO implements Serializable {
+ @Schema(description = "Liste des noms de rôles", required = true)
+ private List roleNames;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/role/RoleDTO.java b/src/main/java/dev/lions/user/manager/dto/role/RoleDTO.java
index 31bf580..e2b5087 100644
--- a/src/main/java/dev/lions/user/manager/dto/role/RoleDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/role/RoleDTO.java
@@ -1,146 +1,146 @@
-package dev.lions.user.manager.dto.role;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.user.manager.dto.base.BaseDTO;
-import dev.lions.user.manager.enums.role.TypeRole;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-import lombok.experimental.SuperBuilder;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import io.quarkus.runtime.annotations.RegisterForReflection;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * DTO représentant un rôle Keycloak
- * Mappé depuis RoleRepresentation de Keycloak Admin API
- */
-@Data
-@SuperBuilder
-@NoArgsConstructor
-@AllArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Rôle Keycloak (Realm ou Client)")
-@RegisterForReflection
-public class RoleDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- @NotBlank(message = "Le nom du rôle est obligatoire")
- @Size(min = 2, max = 100, message = "Le nom du rôle doit contenir entre 2 et 100 caractères")
- @Pattern(regexp = "^[a-zA-Z0-9_-]+$", message = "Le nom du rôle ne peut contenir que des lettres, chiffres, underscores et tirets")
- @Schema(description = "Nom du rôle", example = "admin_btpxpress", required = true)
- private String name;
-
- @Schema(description = "Description du rôle", example = "Administrateur avec tous les privilèges")
- private String description;
-
- @Schema(description = "Type de rôle", example = "REALM_ROLE")
- private TypeRole typeRole;
-
- @Schema(description = "Indique si c'est un rôle composite", example = "false")
- private Boolean composite;
-
- @Schema(description = "ID du conteneur (Realm ou Client)", example = "btpxpress")
- private String containerId;
-
- @Schema(description = "Nom du Realm", example = "btpxpress")
- private String realmName;
-
- @Schema(description = "Nom du Client (si rôle client)", example = "btpxpress-app")
- private String clientName;
-
- @Schema(description = "ID du Client (si rôle client)")
- private String clientId;
-
- @Schema(description = "Rôles composites inclus dans ce rôle")
- private List compositeRoles;
-
- @Schema(description = "Rôles Realm composites")
- private List compositeRealmRoles;
-
- @Schema(description = "Rôles Client composites par client")
- private Map> compositeClientRoles;
-
- @Schema(description = "Attributs personnalisés du rôle")
- private Map> attributes;
-
- @Schema(description = "Nombre d'utilisateurs ayant ce rôle", example = "15")
- private Integer userCount;
-
- @Schema(description = "Indique si le rôle est un rôle système", example = "false")
- private Boolean systemRole;
-
- @Schema(description = "Indique si le rôle peut être supprimé", example = "true")
- private Boolean deletable;
-
- /**
- * Détermine si c'est un rôle Realm
- * @return true si typeRole est REALM_ROLE
- */
- public boolean isRealmRole() {
- return typeRole == TypeRole.REALM_ROLE;
- }
-
- /**
- * Détermine si c'est un rôle Client
- * @return true si typeRole est CLIENT_ROLE
- */
- public boolean isClientRole() {
- return typeRole == TypeRole.CLIENT_ROLE;
- }
-
- /**
- * Détermine si le rôle est composite
- * @return true si composite = true et a des rôles composites
- */
- public boolean isComposite() {
- return Boolean.TRUE.equals(composite)
- && ((compositeRoles != null && !compositeRoles.isEmpty())
- || (compositeRealmRoles != null && !compositeRealmRoles.isEmpty())
- || (compositeClientRoles != null && !compositeClientRoles.isEmpty()));
- }
-
- /**
- * Retourne le nom complet du rôle (avec préfixe client si applicable)
- * @return nom complet
- */
- public String getFullName() {
- if (isClientRole() && clientName != null) {
- return clientName + ":" + name;
- }
- return name;
- }
-
- /**
- * DTO pour rôle composite
- */
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @SuperBuilder
- @Schema(description = "Rôle composite")
- public static class RoleCompositeDTO {
- @Schema(description = "ID du rôle", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479")
- private String id;
-
- @Schema(description = "Nom du rôle", example = "gestionnaire")
- private String name;
-
- @Schema(description = "Description du rôle")
- private String description;
-
- @Schema(description = "Type de rôle", example = "REALM_ROLE")
- private TypeRole typeRole;
-
- @Schema(description = "Nom du client (si client role)")
- private String clientName;
- }
-}
+package dev.lions.user.manager.dto.role;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.user.manager.dto.base.BaseDTO;
+import dev.lions.user.manager.enums.role.TypeRole;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DTO représentant un rôle Keycloak
+ * Mappé depuis RoleRepresentation de Keycloak Admin API
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Rôle Keycloak (Realm ou Client)")
+@RegisterForReflection
+public class RoleDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotBlank(message = "Le nom du rôle est obligatoire")
+ @Size(min = 2, max = 100, message = "Le nom du rôle doit contenir entre 2 et 100 caractères")
+ @Pattern(regexp = "^[a-zA-Z0-9_-]+$", message = "Le nom du rôle ne peut contenir que des lettres, chiffres, underscores et tirets")
+ @Schema(description = "Nom du rôle", example = "admin_btpxpress", required = true)
+ private String name;
+
+ @Schema(description = "Description du rôle", example = "Administrateur avec tous les privilèges")
+ private String description;
+
+ @Schema(description = "Type de rôle", example = "REALM_ROLE")
+ private TypeRole typeRole;
+
+ @Schema(description = "Indique si c'est un rôle composite", example = "false")
+ private Boolean composite;
+
+ @Schema(description = "ID du conteneur (Realm ou Client)", example = "btpxpress")
+ private String containerId;
+
+ @Schema(description = "Nom du Realm", example = "btpxpress")
+ private String realmName;
+
+ @Schema(description = "Nom du Client (si rôle client)", example = "btpxpress-app")
+ private String clientName;
+
+ @Schema(description = "ID du Client (si rôle client)")
+ private String clientId;
+
+ @Schema(description = "Rôles composites inclus dans ce rôle")
+ private List compositeRoles;
+
+ @Schema(description = "Rôles Realm composites")
+ private List compositeRealmRoles;
+
+ @Schema(description = "Rôles Client composites par client")
+ private Map> compositeClientRoles;
+
+ @Schema(description = "Attributs personnalisés du rôle")
+ private Map> attributes;
+
+ @Schema(description = "Nombre d'utilisateurs ayant ce rôle", example = "15")
+ private Integer userCount;
+
+ @Schema(description = "Indique si le rôle est un rôle système", example = "false")
+ private Boolean systemRole;
+
+ @Schema(description = "Indique si le rôle peut être supprimé", example = "true")
+ private Boolean deletable;
+
+ /**
+ * Détermine si c'est un rôle Realm
+ * @return true si typeRole est REALM_ROLE
+ */
+ public boolean isRealmRole() {
+ return typeRole == TypeRole.REALM_ROLE;
+ }
+
+ /**
+ * Détermine si c'est un rôle Client
+ * @return true si typeRole est CLIENT_ROLE
+ */
+ public boolean isClientRole() {
+ return typeRole == TypeRole.CLIENT_ROLE;
+ }
+
+ /**
+ * Détermine si le rôle est composite
+ * @return true si composite = true et a des rôles composites
+ */
+ public boolean isComposite() {
+ return Boolean.TRUE.equals(composite)
+ && ((compositeRoles != null && !compositeRoles.isEmpty())
+ || (compositeRealmRoles != null && !compositeRealmRoles.isEmpty())
+ || (compositeClientRoles != null && !compositeClientRoles.isEmpty()));
+ }
+
+ /**
+ * Retourne le nom complet du rôle (avec préfixe client si applicable)
+ * @return nom complet
+ */
+ public String getFullName() {
+ if (isClientRole() && clientName != null) {
+ return clientName + ":" + name;
+ }
+ return name;
+ }
+
+ /**
+ * DTO pour rôle composite
+ */
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @SuperBuilder
+ @Schema(description = "Rôle composite")
+ public static class RoleCompositeDTO {
+ @Schema(description = "ID du rôle", example = "f47ac10b-58cc-4372-a567-0e02b2c3d479")
+ private String id;
+
+ @Schema(description = "Nom du rôle", example = "gestionnaire")
+ private String name;
+
+ @Schema(description = "Description du rôle")
+ private String description;
+
+ @Schema(description = "Type de rôle", example = "REALM_ROLE")
+ private TypeRole typeRole;
+
+ @Schema(description = "Nom du client (si client role)")
+ private String clientName;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/sync/HealthStatusDTO.java b/src/main/java/dev/lions/user/manager/dto/sync/HealthStatusDTO.java
index cb996c6..7914e6a 100644
--- a/src/main/java/dev/lions/user/manager/dto/sync/HealthStatusDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/sync/HealthStatusDTO.java
@@ -1,46 +1,46 @@
-package dev.lions.user.manager.dto.sync;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-/**
- * DTO représentant le statut de santé de Keycloak
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Statut de santé de Keycloak")
-public class HealthStatusDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "Timestamp du check de santé (millisecondes)", example = "1699545600000")
- private long timestamp;
-
- @Schema(description = "Indique si Keycloak est accessible", example = "true")
- private boolean keycloakAccessible;
-
- @Schema(description = "Version de Keycloak", example = "23.0.3")
- private String keycloakVersion;
-
- @Schema(description = "Indique si les realms sont accessibles", example = "true")
- private boolean realmsAccessible;
-
- @Schema(description = "Nombre de realms disponibles", example = "5")
- private int realmsCount;
-
- @Schema(description = "Indique si Keycloak est globalement en bonne santé", example = "true")
- private boolean overallHealthy;
-
- @Schema(description = "Message d'erreur si le check a échoué")
- private String errorMessage;
-}
-
+package dev.lions.user.manager.dto.sync;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+/**
+ * DTO représentant le statut de santé de Keycloak
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Statut de santé de Keycloak")
+public class HealthStatusDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "Timestamp du check de santé (millisecondes)", example = "1699545600000")
+ private long timestamp;
+
+ @Schema(description = "Indique si Keycloak est accessible", example = "true")
+ private boolean keycloakAccessible;
+
+ @Schema(description = "Version de Keycloak", example = "23.0.3")
+ private String keycloakVersion;
+
+ @Schema(description = "Indique si les realms sont accessibles", example = "true")
+ private boolean realmsAccessible;
+
+ @Schema(description = "Nombre de realms disponibles", example = "5")
+ private int realmsCount;
+
+ @Schema(description = "Indique si Keycloak est globalement en bonne santé", example = "true")
+ private boolean overallHealthy;
+
+ @Schema(description = "Message d'erreur si le check a échoué")
+ private String errorMessage;
+}
+
diff --git a/src/main/java/dev/lions/user/manager/dto/sync/SyncConsistencyDTO.java b/src/main/java/dev/lions/user/manager/dto/sync/SyncConsistencyDTO.java
index ac6a1d1..6010480 100644
--- a/src/main/java/dev/lions/user/manager/dto/sync/SyncConsistencyDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/sync/SyncConsistencyDTO.java
@@ -1,29 +1,29 @@
-package dev.lions.user.manager.dto.sync;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.Set;
-
-/**
- * DTO rapport de cohérence entre données Keycloak et cache local.
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SyncConsistencyDTO {
- private String realmName;
- private String status; // OK, MISMATCH, ERROR
- private Integer usersKeycloakCount;
- private Integer usersLocalCount;
- private Set missingUsersInLocal;
- private Set missingUsersInKeycloak;
- private Integer rolesKeycloakCount;
- private Integer rolesLocalCount;
- private Set missingRolesInLocal;
- private Set missingRolesInKeycloak;
- private String error;
-}
+package dev.lions.user.manager.dto.sync;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Set;
+
+/**
+ * DTO rapport de cohérence entre données Keycloak et cache local.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SyncConsistencyDTO {
+ private String realmName;
+ private String status; // OK, MISMATCH, ERROR
+ private Integer usersKeycloakCount;
+ private Integer usersLocalCount;
+ private Set missingUsersInLocal;
+ private Set missingUsersInKeycloak;
+ private Integer rolesKeycloakCount;
+ private Integer rolesLocalCount;
+ private Set missingRolesInLocal;
+ private Set missingRolesInKeycloak;
+ private String error;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/sync/SyncHistoryDTO.java b/src/main/java/dev/lions/user/manager/dto/sync/SyncHistoryDTO.java
index ca19650..fb503d3 100644
--- a/src/main/java/dev/lions/user/manager/dto/sync/SyncHistoryDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/sync/SyncHistoryDTO.java
@@ -1,23 +1,23 @@
-package dev.lions.user.manager.dto.sync;
-
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.AllArgsConstructor;
-
-import java.time.LocalDateTime;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SyncHistoryDTO {
- private String id;
- private String realmName;
- private LocalDateTime syncDate;
- private String syncType; // FULL, PARTIAL, USER, ROLE
- private String status; // SUCCESS, FAILURE
- private Integer itemsProcessed;
- private Long durationMs;
- private String errorMessage;
-}
+package dev.lions.user.manager.dto.sync;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SyncHistoryDTO {
+ private String id;
+ private String realmName;
+ private LocalDateTime syncDate;
+ private String syncType; // FULL, PARTIAL, USER, ROLE
+ private String status; // SUCCESS, FAILURE
+ private Integer itemsProcessed;
+ private Long durationMs;
+ private String errorMessage;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/sync/SyncResultDTO.java b/src/main/java/dev/lions/user/manager/dto/sync/SyncResultDTO.java
index d05c687..829d00b 100644
--- a/src/main/java/dev/lions/user/manager/dto/sync/SyncResultDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/sync/SyncResultDTO.java
@@ -1,57 +1,57 @@
-package dev.lions.user.manager.dto.sync;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-/**
- * DTO représentant le résultat d'une synchronisation
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Résultat d'une synchronisation avec Keycloak")
-public class SyncResultDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "Nom du realm synchronisé", example = "lions")
- private String realmName;
-
- @Schema(description = "Nombre d'utilisateurs synchronisés", example = "150")
- private int usersCount;
-
- @Schema(description = "Nombre de rôles realm synchronisés", example = "25")
- private int realmRolesCount;
-
- @Schema(description = "Nombre de rôles client synchronisés", example = "50")
- private int clientRolesCount;
-
- @Schema(description = "Indique si la synchronisation a réussi", example = "true")
- private boolean success;
-
- @Schema(description = "Message d'erreur si la synchronisation a échoué")
- private String errorMessage;
-
- @Schema(description = "Timestamp de début de la synchronisation (millisecondes)", example = "1699545600000")
- private long startTime;
-
- @Schema(description = "Timestamp de fin de la synchronisation (millisecondes)", example = "1699545615000")
- private long endTime;
-
- /**
- * Retourne la durée de la synchronisation en millisecondes
- * @return durée en ms
- */
- public long getDurationMs() {
- return endTime - startTime;
- }
-}
-
+package dev.lions.user.manager.dto.sync;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+/**
+ * DTO représentant le résultat d'une synchronisation
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Résultat d'une synchronisation avec Keycloak")
+public class SyncResultDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "Nom du realm synchronisé", example = "lions")
+ private String realmName;
+
+ @Schema(description = "Nombre d'utilisateurs synchronisés", example = "150")
+ private int usersCount;
+
+ @Schema(description = "Nombre de rôles realm synchronisés", example = "25")
+ private int realmRolesCount;
+
+ @Schema(description = "Nombre de rôles client synchronisés", example = "50")
+ private int clientRolesCount;
+
+ @Schema(description = "Indique si la synchronisation a réussi", example = "true")
+ private boolean success;
+
+ @Schema(description = "Message d'erreur si la synchronisation a échoué")
+ private String errorMessage;
+
+ @Schema(description = "Timestamp de début de la synchronisation (millisecondes)", example = "1699545600000")
+ private long startTime;
+
+ @Schema(description = "Timestamp de fin de la synchronisation (millisecondes)", example = "1699545615000")
+ private long endTime;
+
+ /**
+ * Retourne la durée de la synchronisation en millisecondes
+ * @return durée en ms
+ */
+ public long getDurationMs() {
+ return endTime - startTime;
+ }
+}
+
diff --git a/src/main/java/dev/lions/user/manager/dto/user/PasswordResetRequestDTO.java b/src/main/java/dev/lions/user/manager/dto/user/PasswordResetRequestDTO.java
index 870ad48..7bc384d 100644
--- a/src/main/java/dev/lions/user/manager/dto/user/PasswordResetRequestDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/user/PasswordResetRequestDTO.java
@@ -1,25 +1,25 @@
-package dev.lions.user.manager.dto.user;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Requête de réinitialisation de mot de passe")
-public class PasswordResetRequestDTO implements Serializable {
- @Schema(description = "Nouveau mot de passe", required = true)
- private String password;
-
- @Schema(description = "Indique si le mot de passe est temporaire", defaultValue = "true")
- @Builder.Default
- private boolean temporary = true;
-}
+package dev.lions.user.manager.dto.user;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Requête de réinitialisation de mot de passe")
+public class PasswordResetRequestDTO implements Serializable {
+ @Schema(description = "Nouveau mot de passe", required = true)
+ private String password;
+
+ @Schema(description = "Indique si le mot de passe est temporaire", defaultValue = "true")
+ @Builder.Default
+ private boolean temporary = true;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/user/SessionsRevokedDTO.java b/src/main/java/dev/lions/user/manager/dto/user/SessionsRevokedDTO.java
index 15dee6f..8975b45 100644
--- a/src/main/java/dev/lions/user/manager/dto/user/SessionsRevokedDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/user/SessionsRevokedDTO.java
@@ -1,21 +1,21 @@
-package dev.lions.user.manager.dto.user;
-
-import io.quarkus.runtime.annotations.RegisterForReflection;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@RegisterForReflection
-@Schema(description = "Réponse de révocation de sessions")
-public class SessionsRevokedDTO implements Serializable {
- @Schema(description = "Nombre de sessions révoquées")
- private int count;
-}
+package dev.lions.user.manager.dto.user;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@RegisterForReflection
+@Schema(description = "Réponse de révocation de sessions")
+public class SessionsRevokedDTO implements Serializable {
+ @Schema(description = "Nombre de sessions révoquées")
+ private int count;
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/user/UserDTO.java b/src/main/java/dev/lions/user/manager/dto/user/UserDTO.java
index 520b01a..da9d5f5 100644
--- a/src/main/java/dev/lions/user/manager/dto/user/UserDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/user/UserDTO.java
@@ -1,211 +1,211 @@
-package dev.lions.user.manager.dto.user;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.user.manager.dto.base.BaseDTO;
-import dev.lions.user.manager.enums.user.StatutUser;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-import lombok.experimental.SuperBuilder;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import io.quarkus.runtime.annotations.RegisterForReflection;
-
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Map;
-
-/**
- * DTO représentant un utilisateur Keycloak
- * Mappé depuis la représentation UserRepresentation de Keycloak Admin API
- */
-@Data
-@SuperBuilder
-@NoArgsConstructor
-@AllArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Utilisateur Keycloak")
-@RegisterForReflection
-public class UserDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- // Informations de base
- @NotBlank(message = "Le nom d'utilisateur est obligatoire")
- @Size(min = 3, max = 100, message = "Le nom d'utilisateur doit contenir entre 3 et 100 caractères")
- @Pattern(regexp = "^[a-zA-Z0-9._-]+$", message = "Le nom d'utilisateur ne peut contenir que des lettres, chiffres, points, tirets et underscores")
- @Schema(description = "Nom d'utilisateur unique", example = "jdupont", required = true)
- private String username;
-
- @NotBlank(message = "L'email est obligatoire")
- @Email(message = "Format d'email invalide")
- @Schema(description = "Adresse email", example = "jean.dupont@lions.dev", required = true)
- private String email;
-
- @Schema(description = "Email vérifié", example = "true")
- private Boolean emailVerified;
-
- @NotBlank(message = "Le prénom est obligatoire")
- @Size(min = 2, max = 100, message = "Le prénom doit contenir entre 2 et 100 caractères")
- @Schema(description = "Prénom", example = "Jean", required = true)
- private String prenom;
-
- @NotBlank(message = "Le nom est obligatoire")
- @Size(min = 2, max = 100, message = "Le nom doit contenir entre 2 et 100 caractères")
- @Schema(description = "Nom de famille", example = "Dupont", required = true)
- private String nom;
-
- // Statut
- @Schema(description = "Statut de l'utilisateur", example = "ACTIF")
- private StatutUser statut;
-
- @Schema(description = "Compte activé", example = "true")
- private Boolean enabled;
-
- // Informations supplémentaires
- @Schema(description = "Numéro de téléphone", example = "+225 07 12 34 56 78")
- private String telephone;
-
- @Schema(description = "Organisation/Entreprise", example = "Lions Dev")
- private String organisation;
-
- @Schema(description = "Département", example = "IT")
- private String departement;
-
- @Schema(description = "Fonction/Poste", example = "Développeur Senior")
- private String fonction;
-
- @Schema(description = "Pays", example = "Côte d'Ivoire")
- private String pays;
-
- @Schema(description = "Ville", example = "Abidjan")
- private String ville;
-
- @Schema(description = "Langue préférée", example = "fr")
- private String langue;
-
- @Schema(description = "Fuseau horaire", example = "Africa/Abidjan")
- private String timezone;
-
- // Realm et rôles
- @Schema(description = "Realm Keycloak", example = "btpxpress")
- private String realmName;
-
- @Schema(description = "Liste des rôles Realm assignés")
- private List realmRoles;
-
- @Schema(description = "Liste des rôles Client assignés")
- private Map> clientRoles;
-
- @Schema(description = "Liste des groupes auxquels appartient l'utilisateur")
- private List groups;
-
- // Dates importantes
- @Schema(description = "Date de dernière connexion", example = "2025-01-15T10:30:00")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime derniereConnexion;
-
- @Schema(description = "Date d'expiration du compte", example = "2026-01-15T23:59:59")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime dateExpiration;
-
- @Schema(description = "Date de verrouillage du compte", example = "2025-01-15T16:00:00")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime dateVerrouillage;
-
- // Attributs personnalisés Keycloak
- @Schema(description = "Attributs personnalisés Keycloak")
- private Map> attributes;
-
- // Actions requises
- @Schema(description = "Actions requises (ex: UPDATE_PASSWORD, VERIFY_EMAIL)")
- private List requiredActions;
-
- // Fédération
- @Schema(description = "Fournisseur d'identité fédéré", example = "google")
- private String federatedIdentityProvider;
-
- @Schema(description = "Lien d'identité fédérée")
- private List federatedIdentities;
-
- // Crédentiels temporaires
- @Schema(description = "Mot de passe temporaire (création uniquement)")
- private String temporaryPassword;
-
- @Schema(description = "Indique si le mot de passe est temporaire")
- private Boolean temporaryPasswordFlag;
-
- // Informations de session
- @Schema(description = "Nombre de sessions actives", example = "2")
- private Integer activeSessions;
-
- @Schema(description = "Nombre d'échecs de connexion", example = "0")
- private Integer failedLoginAttempts;
-
- // Audit
- @Schema(description = "Raison de la dernière modification")
- private String raisonModification;
-
- @Schema(description = "Commentaires administratifs")
- private String commentaires;
-
- /**
- * Retourne le nom complet de l'utilisateur
- * @return prénom + nom
- */
- public String getNomComplet() {
- if (prenom != null && nom != null) {
- return prenom + " " + nom;
- }
- return username;
- }
-
- /**
- * Détermine si l'utilisateur est actif
- * @return true si statut ACTIF et enabled
- */
- public boolean isActif() {
- return statut == StatutUser.ACTIF && Boolean.TRUE.equals(enabled);
- }
-
- /**
- * Détermine si le compte a expiré
- * @return true si dateExpiration est passée
- */
- public boolean isExpire() {
- return dateExpiration != null && dateExpiration.isBefore(LocalDateTime.now());
- }
-
- /**
- * Détermine si l'utilisateur a des actions requises
- * @return true si des actions sont requises
- */
- public boolean hasRequiredActions() {
- return requiredActions != null && !requiredActions.isEmpty();
- }
-
- /**
- * DTO pour identité fédérée
- */
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @SuperBuilder
- @Schema(description = "Identité fédérée")
- public static class FederatedIdentityDTO {
- @Schema(description = "Fournisseur d'identité", example = "google")
- private String identityProvider;
-
- @Schema(description = "ID utilisateur chez le fournisseur")
- private String userId;
-
- @Schema(description = "Nom d'utilisateur chez le fournisseur")
- private String userName;
- }
-}
+package dev.lions.user.manager.dto.user;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.user.manager.dto.base.BaseDTO;
+import dev.lions.user.manager.enums.user.StatutUser;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DTO représentant un utilisateur Keycloak
+ * Mappé depuis la représentation UserRepresentation de Keycloak Admin API
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Utilisateur Keycloak")
+@RegisterForReflection
+public class UserDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ // Informations de base
+ @NotBlank(message = "Le nom d'utilisateur est obligatoire")
+ @Size(min = 3, max = 100, message = "Le nom d'utilisateur doit contenir entre 3 et 100 caractères")
+ @Pattern(regexp = "^[a-zA-Z0-9._-]+$", message = "Le nom d'utilisateur ne peut contenir que des lettres, chiffres, points, tirets et underscores")
+ @Schema(description = "Nom d'utilisateur unique", example = "jdupont", required = true)
+ private String username;
+
+ @NotBlank(message = "L'email est obligatoire")
+ @Email(message = "Format d'email invalide")
+ @Schema(description = "Adresse email", example = "jean.dupont@lions.dev", required = true)
+ private String email;
+
+ @Schema(description = "Email vérifié", example = "true")
+ private Boolean emailVerified;
+
+ @NotBlank(message = "Le prénom est obligatoire")
+ @Size(min = 2, max = 100, message = "Le prénom doit contenir entre 2 et 100 caractères")
+ @Schema(description = "Prénom", example = "Jean", required = true)
+ private String prenom;
+
+ @NotBlank(message = "Le nom est obligatoire")
+ @Size(min = 2, max = 100, message = "Le nom doit contenir entre 2 et 100 caractères")
+ @Schema(description = "Nom de famille", example = "Dupont", required = true)
+ private String nom;
+
+ // Statut
+ @Schema(description = "Statut de l'utilisateur", example = "ACTIF")
+ private StatutUser statut;
+
+ @Schema(description = "Compte activé", example = "true")
+ private Boolean enabled;
+
+ // Informations supplémentaires
+ @Schema(description = "Numéro de téléphone", example = "+225 07 12 34 56 78")
+ private String telephone;
+
+ @Schema(description = "Organisation/Entreprise", example = "Lions Dev")
+ private String organisation;
+
+ @Schema(description = "Département", example = "IT")
+ private String departement;
+
+ @Schema(description = "Fonction/Poste", example = "Développeur Senior")
+ private String fonction;
+
+ @Schema(description = "Pays", example = "Côte d'Ivoire")
+ private String pays;
+
+ @Schema(description = "Ville", example = "Abidjan")
+ private String ville;
+
+ @Schema(description = "Langue préférée", example = "fr")
+ private String langue;
+
+ @Schema(description = "Fuseau horaire", example = "Africa/Abidjan")
+ private String timezone;
+
+ // Realm et rôles
+ @Schema(description = "Realm Keycloak", example = "btpxpress")
+ private String realmName;
+
+ @Schema(description = "Liste des rôles Realm assignés")
+ private List realmRoles;
+
+ @Schema(description = "Liste des rôles Client assignés")
+ private Map> clientRoles;
+
+ @Schema(description = "Liste des groupes auxquels appartient l'utilisateur")
+ private List groups;
+
+ // Dates importantes
+ @Schema(description = "Date de dernière connexion", example = "2025-01-15T10:30:00")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime derniereConnexion;
+
+ @Schema(description = "Date d'expiration du compte", example = "2026-01-15T23:59:59")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime dateExpiration;
+
+ @Schema(description = "Date de verrouillage du compte", example = "2025-01-15T16:00:00")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime dateVerrouillage;
+
+ // Attributs personnalisés Keycloak
+ @Schema(description = "Attributs personnalisés Keycloak")
+ private Map> attributes;
+
+ // Actions requises
+ @Schema(description = "Actions requises (ex: UPDATE_PASSWORD, VERIFY_EMAIL)")
+ private List requiredActions;
+
+ // Fédération
+ @Schema(description = "Fournisseur d'identité fédéré", example = "google")
+ private String federatedIdentityProvider;
+
+ @Schema(description = "Lien d'identité fédérée")
+ private List federatedIdentities;
+
+ // Crédentiels temporaires
+ @Schema(description = "Mot de passe temporaire (création uniquement)")
+ private String temporaryPassword;
+
+ @Schema(description = "Indique si le mot de passe est temporaire")
+ private Boolean temporaryPasswordFlag;
+
+ // Informations de session
+ @Schema(description = "Nombre de sessions actives", example = "2")
+ private Integer activeSessions;
+
+ @Schema(description = "Nombre d'échecs de connexion", example = "0")
+ private Integer failedLoginAttempts;
+
+ // Audit
+ @Schema(description = "Raison de la dernière modification")
+ private String raisonModification;
+
+ @Schema(description = "Commentaires administratifs")
+ private String commentaires;
+
+ /**
+ * Retourne le nom complet de l'utilisateur
+ * @return prénom + nom
+ */
+ public String getNomComplet() {
+ if (prenom != null && nom != null) {
+ return prenom + " " + nom;
+ }
+ return username;
+ }
+
+ /**
+ * Détermine si l'utilisateur est actif
+ * @return true si statut ACTIF et enabled
+ */
+ public boolean isActif() {
+ return statut == StatutUser.ACTIF && Boolean.TRUE.equals(enabled);
+ }
+
+ /**
+ * Détermine si le compte a expiré
+ * @return true si dateExpiration est passée
+ */
+ public boolean isExpire() {
+ return dateExpiration != null && dateExpiration.isBefore(LocalDateTime.now());
+ }
+
+ /**
+ * Détermine si l'utilisateur a des actions requises
+ * @return true si des actions sont requises
+ */
+ public boolean hasRequiredActions() {
+ return requiredActions != null && !requiredActions.isEmpty();
+ }
+
+ /**
+ * DTO pour identité fédérée
+ */
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @SuperBuilder
+ @Schema(description = "Identité fédérée")
+ public static class FederatedIdentityDTO {
+ @Schema(description = "Fournisseur d'identité", example = "google")
+ private String identityProvider;
+
+ @Schema(description = "ID utilisateur chez le fournisseur")
+ private String userId;
+
+ @Schema(description = "Nom d'utilisateur chez le fournisseur")
+ private String userName;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTO.java b/src/main/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTO.java
index 0fe5a2f..9596e62 100644
--- a/src/main/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTO.java
@@ -1,193 +1,193 @@
-package dev.lions.user.manager.dto.user;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.user.manager.enums.user.StatutUser;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-import java.util.List;
-
-/**
- * Critères de recherche pour les utilisateurs
- * Utilisé pour filtrer les utilisateurs via l'API Keycloak Admin
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Critères de recherche d'utilisateurs")
-public class UserSearchCriteriaDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- // Recherche textuelle
- @Schema(description = "Terme de recherche générale (username, email, nom, prénom)", example = "dupont")
- private String searchTerm;
-
- @Schema(description = "Nom d'utilisateur exact", example = "jdupont")
- private String username;
-
- @Schema(description = "Email exact", example = "jean.dupont@lions.dev")
- private String email;
-
- @Schema(description = "Prénom", example = "Jean")
- private String prenom;
-
- @Schema(description = "Nom de famille", example = "Dupont")
- private String nom;
-
- @Schema(description = "Numéro de téléphone", example = "+225 01 02 03 04 05")
- private String telephone;
-
- // Filtres de statut
- @Schema(description = "Statut de l'utilisateur", example = "ACTIF")
- private StatutUser statut;
-
- @Schema(description = "Compte activé", example = "true")
- private Boolean enabled;
-
- @Schema(description = "Email vérifié", example = "true")
- private Boolean emailVerified;
-
- // Filtres de rôle et groupe
- @Schema(description = "Liste des rôles Realm à filtrer")
- private List realmRoles;
-
- @Schema(description = "Liste des rôles Client à filtrer")
- private List clientRoles;
-
- @Schema(description = "Liste des groupes à filtrer")
- private List groups;
-
- @Schema(description = "Nom du client pour filtrer par rôles client", example = "btpxpress-app")
- private String clientName;
-
- // Filtres organisationnels
- @Schema(description = "Organisation/Entreprise", example = "Lions Dev")
- private String organisation;
-
- @Schema(description = "Département", example = "IT")
- private String departement;
-
- @Schema(description = "Fonction/Poste", example = "Développeur")
- private String fonction;
-
- @Schema(description = "Pays", example = "Côte d'Ivoire")
- private String pays;
-
- @Schema(description = "Ville", example = "Abidjan")
- private String ville;
-
- // Filtres temporels
- @Schema(description = "Date de création minimum", example = "2025-01-01T00:00:00")
- private LocalDateTime dateCreationMin;
-
- @Schema(description = "Date de création maximum", example = "2025-12-31T23:59:59")
- private LocalDateTime dateCreationMax;
-
- @Schema(description = "Date de dernière connexion minimum", example = "2025-01-01T00:00:00")
- private LocalDateTime derniereConnexionMin;
-
- @Schema(description = "Date de dernière connexion maximum", example = "2025-01-31T23:59:59")
- private LocalDateTime derniereConnexionMax;
-
- // Filtres spéciaux
- @Schema(description = "Utilisateurs avec actions requises uniquement", example = "true")
- private Boolean hasRequiredActions;
-
- @Schema(description = "Utilisateurs verrouillés uniquement", example = "false")
- private Boolean isLocked;
-
- @Schema(description = "Utilisateurs expirés uniquement", example = "false")
- private Boolean isExpired;
-
- @Schema(description = "Utilisateurs avec sessions actives uniquement", example = "true")
- private Boolean hasActiveSessions;
-
- // Realm
- @Schema(description = "Nom du Realm à filtrer", example = "btpxpress")
- private String realmName;
-
- // Pagination
- @Schema(description = "Numéro de page (commence à 0)", example = "0", defaultValue = "0")
- @Builder.Default
- private Integer page = 0;
-
- @Schema(description = "Taille de la page", example = "20", defaultValue = "20")
- @Builder.Default
- private Integer pageSize = 20;
-
- @Schema(description = "Nombre maximum de résultats", example = "100")
- private Integer maxResults;
-
- // Tri
- @Schema(description = "Champ de tri (username, email, prenom, nom, dateCreation, derniereConnexion)", example = "username")
- @Builder.Default
- private String sortBy = "username";
-
- @Schema(description = "Ordre de tri (ASC ou DESC)", example = "ASC")
- @Builder.Default
- private String sortOrder = "ASC";
-
- // Options d'inclusion
- @Schema(description = "Inclure les rôles dans les résultats", example = "true")
- @Builder.Default
- private Boolean includeRoles = false;
-
- @Schema(description = "Inclure les groupes dans les résultats", example = "true")
- @Builder.Default
- private Boolean includeGroups = false;
-
- @Schema(description = "Inclure les attributs personnalisés", example = "false")
- @Builder.Default
- private Boolean includeAttributes = false;
-
- @Schema(description = "Inclure les informations de session", example = "false")
- @Builder.Default
- private Boolean includeSessionInfo = false;
-
- /**
- * Détermine si des filtres de recherche sont appliqués
- * @return true si au moins un filtre est défini
- */
- public boolean hasFilters() {
- return searchTerm != null
- || username != null
- || email != null
- || prenom != null
- || nom != null
- || statut != null
- || enabled != null
- || emailVerified != null
- || (realmRoles != null && !realmRoles.isEmpty())
- || (clientRoles != null && !clientRoles.isEmpty())
- || (groups != null && !groups.isEmpty())
- || organisation != null
- || departement != null
- || fonction != null
- || pays != null
- || ville != null
- || dateCreationMin != null
- || dateCreationMax != null
- || derniereConnexionMin != null
- || derniereConnexionMax != null
- || hasRequiredActions != null
- || isLocked != null
- || isExpired != null
- || hasActiveSessions != null;
- }
-
- /**
- * Calcule l'offset pour la pagination Keycloak
- * @return offset calculé à partir de page et pageSize
- */
- public int getOffset() {
- return page * pageSize;
- }
-}
+package dev.lions.user.manager.dto.user;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.user.manager.enums.user.StatutUser;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * Critères de recherche pour les utilisateurs
+ * Utilisé pour filtrer les utilisateurs via l'API Keycloak Admin
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Critères de recherche d'utilisateurs")
+public class UserSearchCriteriaDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ // Recherche textuelle
+ @Schema(description = "Terme de recherche générale (username, email, nom, prénom)", example = "dupont")
+ private String searchTerm;
+
+ @Schema(description = "Nom d'utilisateur exact", example = "jdupont")
+ private String username;
+
+ @Schema(description = "Email exact", example = "jean.dupont@lions.dev")
+ private String email;
+
+ @Schema(description = "Prénom", example = "Jean")
+ private String prenom;
+
+ @Schema(description = "Nom de famille", example = "Dupont")
+ private String nom;
+
+ @Schema(description = "Numéro de téléphone", example = "+225 01 02 03 04 05")
+ private String telephone;
+
+ // Filtres de statut
+ @Schema(description = "Statut de l'utilisateur", example = "ACTIF")
+ private StatutUser statut;
+
+ @Schema(description = "Compte activé", example = "true")
+ private Boolean enabled;
+
+ @Schema(description = "Email vérifié", example = "true")
+ private Boolean emailVerified;
+
+ // Filtres de rôle et groupe
+ @Schema(description = "Liste des rôles Realm à filtrer")
+ private List realmRoles;
+
+ @Schema(description = "Liste des rôles Client à filtrer")
+ private List clientRoles;
+
+ @Schema(description = "Liste des groupes à filtrer")
+ private List groups;
+
+ @Schema(description = "Nom du client pour filtrer par rôles client", example = "btpxpress-app")
+ private String clientName;
+
+ // Filtres organisationnels
+ @Schema(description = "Organisation/Entreprise", example = "Lions Dev")
+ private String organisation;
+
+ @Schema(description = "Département", example = "IT")
+ private String departement;
+
+ @Schema(description = "Fonction/Poste", example = "Développeur")
+ private String fonction;
+
+ @Schema(description = "Pays", example = "Côte d'Ivoire")
+ private String pays;
+
+ @Schema(description = "Ville", example = "Abidjan")
+ private String ville;
+
+ // Filtres temporels
+ @Schema(description = "Date de création minimum", example = "2025-01-01T00:00:00")
+ private LocalDateTime dateCreationMin;
+
+ @Schema(description = "Date de création maximum", example = "2025-12-31T23:59:59")
+ private LocalDateTime dateCreationMax;
+
+ @Schema(description = "Date de dernière connexion minimum", example = "2025-01-01T00:00:00")
+ private LocalDateTime derniereConnexionMin;
+
+ @Schema(description = "Date de dernière connexion maximum", example = "2025-01-31T23:59:59")
+ private LocalDateTime derniereConnexionMax;
+
+ // Filtres spéciaux
+ @Schema(description = "Utilisateurs avec actions requises uniquement", example = "true")
+ private Boolean hasRequiredActions;
+
+ @Schema(description = "Utilisateurs verrouillés uniquement", example = "false")
+ private Boolean isLocked;
+
+ @Schema(description = "Utilisateurs expirés uniquement", example = "false")
+ private Boolean isExpired;
+
+ @Schema(description = "Utilisateurs avec sessions actives uniquement", example = "true")
+ private Boolean hasActiveSessions;
+
+ // Realm
+ @Schema(description = "Nom du Realm à filtrer", example = "btpxpress")
+ private String realmName;
+
+ // Pagination
+ @Schema(description = "Numéro de page (commence à 0)", example = "0", defaultValue = "0")
+ @Builder.Default
+ private Integer page = 0;
+
+ @Schema(description = "Taille de la page", example = "20", defaultValue = "20")
+ @Builder.Default
+ private Integer pageSize = 20;
+
+ @Schema(description = "Nombre maximum de résultats", example = "100")
+ private Integer maxResults;
+
+ // Tri
+ @Schema(description = "Champ de tri (username, email, prenom, nom, dateCreation, derniereConnexion)", example = "username")
+ @Builder.Default
+ private String sortBy = "username";
+
+ @Schema(description = "Ordre de tri (ASC ou DESC)", example = "ASC")
+ @Builder.Default
+ private String sortOrder = "ASC";
+
+ // Options d'inclusion
+ @Schema(description = "Inclure les rôles dans les résultats", example = "true")
+ @Builder.Default
+ private Boolean includeRoles = false;
+
+ @Schema(description = "Inclure les groupes dans les résultats", example = "true")
+ @Builder.Default
+ private Boolean includeGroups = false;
+
+ @Schema(description = "Inclure les attributs personnalisés", example = "false")
+ @Builder.Default
+ private Boolean includeAttributes = false;
+
+ @Schema(description = "Inclure les informations de session", example = "false")
+ @Builder.Default
+ private Boolean includeSessionInfo = false;
+
+ /**
+ * Détermine si des filtres de recherche sont appliqués
+ * @return true si au moins un filtre est défini
+ */
+ public boolean hasFilters() {
+ return searchTerm != null
+ || username != null
+ || email != null
+ || prenom != null
+ || nom != null
+ || statut != null
+ || enabled != null
+ || emailVerified != null
+ || (realmRoles != null && !realmRoles.isEmpty())
+ || (clientRoles != null && !clientRoles.isEmpty())
+ || (groups != null && !groups.isEmpty())
+ || organisation != null
+ || departement != null
+ || fonction != null
+ || pays != null
+ || ville != null
+ || dateCreationMin != null
+ || dateCreationMax != null
+ || derniereConnexionMin != null
+ || derniereConnexionMax != null
+ || hasRequiredActions != null
+ || isLocked != null
+ || isExpired != null
+ || hasActiveSessions != null;
+ }
+
+ /**
+ * Calcule l'offset pour la pagination Keycloak
+ * @return offset calculé à partir de page et pageSize
+ */
+ public int getOffset() {
+ return page * pageSize;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/dto/user/UserSearchResultDTO.java b/src/main/java/dev/lions/user/manager/dto/user/UserSearchResultDTO.java
index d96661e..3e018c3 100644
--- a/src/main/java/dev/lions/user/manager/dto/user/UserSearchResultDTO.java
+++ b/src/main/java/dev/lions/user/manager/dto/user/UserSearchResultDTO.java
@@ -1,107 +1,107 @@
-package dev.lions.user.manager.dto.user;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-import io.quarkus.runtime.annotations.RegisterForReflection;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * Résultat paginé de recherche d'utilisateurs
- * Contient la liste des utilisateurs et les métadonnées de pagination
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Schema(description = "Résultat paginé de recherche d'utilisateurs")
-@RegisterForReflection
-public class UserSearchResultDTO implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @Schema(description = "Liste des utilisateurs trouvés")
- private List users;
-
- @Schema(description = "Nombre total d'utilisateurs correspondant aux critères", example = "156")
- private Long totalCount;
-
- @Schema(description = "Numéro de la page actuelle (commence à 0)", example = "0")
- private Integer currentPage;
-
- @Schema(description = "Taille de la page", example = "20")
- private Integer pageSize;
-
- @Schema(description = "Nombre total de pages", example = "8")
- private Integer totalPages;
-
- @Schema(description = "Indique s'il y a une page suivante", example = "true")
- private Boolean hasNextPage;
-
- @Schema(description = "Indique s'il y a une page précédente", example = "false")
- private Boolean hasPreviousPage;
-
- @Schema(description = "Index du premier élément de la page", example = "0")
- private Integer firstElement;
-
- @Schema(description = "Index du dernier élément de la page", example = "19")
- private Integer lastElement;
-
- @Schema(description = "Indique si la page est vide", example = "false")
- private Boolean isEmpty;
-
- @Schema(description = "Indique si c'est la première page", example = "true")
- private Boolean isFirstPage;
-
- @Schema(description = "Indique si c'est la dernière page", example = "false")
- private Boolean isLastPage;
-
- @Schema(description = "Critères de recherche utilisés")
- private UserSearchCriteriaDTO criteria;
-
- @Schema(description = "Temps d'exécution de la recherche en millisecondes", example = "145")
- private Long executionTimeMs;
-
- /**
- * Construit un résultat de recherche à partir d'une liste d'utilisateurs
- * @param users liste des utilisateurs
- * @param criteria critères de recherche
- * @param totalCount nombre total de résultats
- * @return UserSearchResultDTO
- */
- public static UserSearchResultDTO of(List users, UserSearchCriteriaDTO criteria, Long totalCount) {
- int pageSize = criteria.getPageSize();
- int currentPage = criteria.getPage();
- long totalPages = (totalCount + pageSize - 1) / pageSize;
-
- return UserSearchResultDTO.builder()
- .users(users)
- .totalCount(totalCount)
- .currentPage(currentPage)
- .pageSize(pageSize)
- .totalPages((int) totalPages)
- .hasNextPage(currentPage < totalPages - 1)
- .hasPreviousPage(currentPage > 0)
- .firstElement(currentPage * pageSize)
- .lastElement(Math.min((currentPage + 1) * pageSize - 1, totalCount.intValue()))
- .isEmpty(users == null || users.isEmpty())
- .isFirstPage(currentPage == 0)
- .isLastPage(currentPage >= totalPages - 1)
- .criteria(criteria)
- .build();
- }
-
- /**
- * Retourne le nombre d'utilisateurs dans la page courante
- * @return nombre d'utilisateurs
- */
- public int getCurrentPageSize() {
- return users != null ? users.size() : 0;
- }
-}
+package dev.lions.user.manager.dto.user;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Résultat paginé de recherche d'utilisateurs
+ * Contient la liste des utilisateurs et les métadonnées de pagination
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Schema(description = "Résultat paginé de recherche d'utilisateurs")
+@RegisterForReflection
+public class UserSearchResultDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "Liste des utilisateurs trouvés")
+ private List users;
+
+ @Schema(description = "Nombre total d'utilisateurs correspondant aux critères", example = "156")
+ private Long totalCount;
+
+ @Schema(description = "Numéro de la page actuelle (commence à 0)", example = "0")
+ private Integer currentPage;
+
+ @Schema(description = "Taille de la page", example = "20")
+ private Integer pageSize;
+
+ @Schema(description = "Nombre total de pages", example = "8")
+ private Integer totalPages;
+
+ @Schema(description = "Indique s'il y a une page suivante", example = "true")
+ private Boolean hasNextPage;
+
+ @Schema(description = "Indique s'il y a une page précédente", example = "false")
+ private Boolean hasPreviousPage;
+
+ @Schema(description = "Index du premier élément de la page", example = "0")
+ private Integer firstElement;
+
+ @Schema(description = "Index du dernier élément de la page", example = "19")
+ private Integer lastElement;
+
+ @Schema(description = "Indique si la page est vide", example = "false")
+ private Boolean isEmpty;
+
+ @Schema(description = "Indique si c'est la première page", example = "true")
+ private Boolean isFirstPage;
+
+ @Schema(description = "Indique si c'est la dernière page", example = "false")
+ private Boolean isLastPage;
+
+ @Schema(description = "Critères de recherche utilisés")
+ private UserSearchCriteriaDTO criteria;
+
+ @Schema(description = "Temps d'exécution de la recherche en millisecondes", example = "145")
+ private Long executionTimeMs;
+
+ /**
+ * Construit un résultat de recherche à partir d'une liste d'utilisateurs
+ * @param users liste des utilisateurs
+ * @param criteria critères de recherche
+ * @param totalCount nombre total de résultats
+ * @return UserSearchResultDTO
+ */
+ public static UserSearchResultDTO of(List users, UserSearchCriteriaDTO criteria, Long totalCount) {
+ int pageSize = criteria.getPageSize();
+ int currentPage = criteria.getPage();
+ long totalPages = (totalCount + pageSize - 1) / pageSize;
+
+ return UserSearchResultDTO.builder()
+ .users(users)
+ .totalCount(totalCount)
+ .currentPage(currentPage)
+ .pageSize(pageSize)
+ .totalPages((int) totalPages)
+ .hasNextPage(currentPage < totalPages - 1)
+ .hasPreviousPage(currentPage > 0)
+ .firstElement(currentPage * pageSize)
+ .lastElement(Math.min((currentPage + 1) * pageSize - 1, totalCount.intValue()))
+ .isEmpty(users == null || users.isEmpty())
+ .isFirstPage(currentPage == 0)
+ .isLastPage(currentPage >= totalPages - 1)
+ .criteria(criteria)
+ .build();
+ }
+
+ /**
+ * Retourne le nombre d'utilisateurs dans la page courante
+ * @return nombre d'utilisateurs
+ */
+ public int getCurrentPageSize() {
+ return users != null ? users.size() : 0;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/enums/audit/TypeActionAudit.java b/src/main/java/dev/lions/user/manager/enums/audit/TypeActionAudit.java
index b2c9a5a..2c3cb8f 100644
--- a/src/main/java/dev/lions/user/manager/enums/audit/TypeActionAudit.java
+++ b/src/main/java/dev/lions/user/manager/enums/audit/TypeActionAudit.java
@@ -1,116 +1,116 @@
-package dev.lions.user.manager.enums.audit;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-/**
- * Type d'action effectuée sur une ressource
- * Utilisé pour l'audit trail
- */
-@Getter
-@RequiredArgsConstructor
-@Schema(description = "Type d'action pour l'audit")
-public enum TypeActionAudit {
-
- // Actions Utilisateur
- USER_CREATE("Création utilisateur", "USER", "CREATE"),
- USER_UPDATE("Modification utilisateur", "USER", "UPDATE"),
- USER_DELETE("Suppression utilisateur", "USER", "DELETE"),
- USER_ACTIVATE("Activation utilisateur", "USER", "ACTIVATE"),
- USER_DEACTIVATE("Désactivation utilisateur", "USER", "DEACTIVATE"),
- USER_SUSPEND("Suspension utilisateur", "USER", "SUSPEND"),
- USER_UNLOCK("Déverrouillage utilisateur", "USER", "UNLOCK"),
- USER_PASSWORD_RESET("Réinitialisation mot de passe", "USER", "PASSWORD_RESET"),
- USER_EMAIL_VERIFY("Vérification email", "USER", "EMAIL_VERIFY"),
- USER_FORCE_LOGOUT("Déconnexion forcée", "USER", "FORCE_LOGOUT"),
- USER_IMPORT("Import utilisateurs CSV", "USER", "IMPORT"), // Ajout
-
- // Actions Rôle
- ROLE_CREATE("Création rôle", "ROLE", "CREATE"),
- ROLE_UPDATE("Modification rôle", "ROLE", "UPDATE"),
- ROLE_DELETE("Suppression rôle", "ROLE", "DELETE"),
- ROLE_ASSIGN("Attribution rôle", "ROLE", "ASSIGN"),
- ROLE_REVOKE("Révocation rôle", "ROLE", "REVOKE"),
- ROLE_ADD_COMPOSITE("Ajout rôle composite", "ROLE", "ADD_COMPOSITE"),
- ROLE_REMOVE_COMPOSITE("Retrait rôle composite", "ROLE", "REMOVE_COMPOSITE"),
-
- // Actions Groupe
- GROUP_CREATE("Création groupe", "GROUP", "CREATE"),
- GROUP_UPDATE("Modification groupe", "GROUP", "UPDATE"),
- GROUP_DELETE("Suppression groupe", "GROUP", "DELETE"),
- GROUP_ADD_MEMBER("Ajout membre groupe", "GROUP", "ADD_MEMBER"),
- GROUP_REMOVE_MEMBER("Retrait membre groupe", "GROUP", "REMOVE_MEMBER"),
-
- // Actions Realm & Sync
- REALM_SYNC("Synchronisation realm (Général)", "REALM", "SYNC"),
- SYNC_USERS("Synchronisation utilisateurs", "REALM", "SYNC_USERS"), // Ajout
- SYNC_ROLES("Synchronisation rôles", "REALM", "SYNC_ROLES"), // Ajout
- REALM_EXPORT("Export realm", "REALM", "EXPORT"),
- REALM_IMPORT("Import realm", "REALM", "IMPORT"),
- REALM_ASSIGN("Assignation realm", "REALM", "ASSIGN"),
- REALM_REVOKE("Révocation realm", "REALM", "REVOKE"),
- REALM_ACTIVATE("Activation assignation realm", "REALM", "ACTIVATE"),
- REALM_DEACTIVATE("Désactivation assignation realm", "REALM", "DEACTIVATE"),
- REALM_SET_SUPER_ADMIN("Définition super admin", "REALM", "SET_SUPER_ADMIN"),
-
- // Actions Session
- SESSION_CREATE("Création session", "SESSION", "CREATE"),
- SESSION_DELETE("Suppression session", "SESSION", "DELETE"),
- SESSION_REVOKE_ALL("Révocation toutes sessions", "SESSION", "REVOKE_ALL"),
-
- // Actions Système
- SYSTEM_BACKUP("Sauvegarde système", "SYSTEM", "BACKUP"),
- SYSTEM_RESTORE("Restauration système", "SYSTEM", "RESTORE"),
- SYSTEM_CONFIG_CHANGE("Modification configuration", "SYSTEM", "CONFIG_CHANGE");
-
- private final String libelle;
- private final String ressourceType;
- private final String actionType;
-
- /**
- * Détermine si l'action concerne un utilisateur
- */
- public boolean isUserAction() {
- return ressourceType.equals("USER");
- }
-
- /**
- * Détermine si l'action concerne un rôle
- */
- public boolean isRoleAction() {
- return ressourceType.equals("ROLE");
- }
-
- /**
- * Détermine si l'action est une création
- */
- public boolean isCreateAction() {
- return actionType.equals("CREATE");
- }
-
- /**
- * Détermine si l'action est une modification
- */
- public boolean isUpdateAction() {
- return actionType.equals("UPDATE");
- }
-
- /**
- * Détermine si l'action est une suppression
- */
- public boolean isDeleteAction() {
- return actionType.equals("DELETE");
- }
-
- /**
- * Détermine si l'action est critique (nécessite alerte)
- */
- public boolean isCritical() {
- return this == USER_DELETE
- || this == ROLE_DELETE
- || this == USER_SUSPEND
- || this == SESSION_REVOKE_ALL
- || this == SYSTEM_RESTORE;
- }
-}
+package dev.lions.user.manager.enums.audit;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+/**
+ * Type d'action effectuée sur une ressource
+ * Utilisé pour l'audit trail
+ */
+@Getter
+@RequiredArgsConstructor
+@Schema(description = "Type d'action pour l'audit")
+public enum TypeActionAudit {
+
+ // Actions Utilisateur
+ USER_CREATE("Création utilisateur", "USER", "CREATE"),
+ USER_UPDATE("Modification utilisateur", "USER", "UPDATE"),
+ USER_DELETE("Suppression utilisateur", "USER", "DELETE"),
+ USER_ACTIVATE("Activation utilisateur", "USER", "ACTIVATE"),
+ USER_DEACTIVATE("Désactivation utilisateur", "USER", "DEACTIVATE"),
+ USER_SUSPEND("Suspension utilisateur", "USER", "SUSPEND"),
+ USER_UNLOCK("Déverrouillage utilisateur", "USER", "UNLOCK"),
+ USER_PASSWORD_RESET("Réinitialisation mot de passe", "USER", "PASSWORD_RESET"),
+ USER_EMAIL_VERIFY("Vérification email", "USER", "EMAIL_VERIFY"),
+ USER_FORCE_LOGOUT("Déconnexion forcée", "USER", "FORCE_LOGOUT"),
+ USER_IMPORT("Import utilisateurs CSV", "USER", "IMPORT"), // Ajout
+
+ // Actions Rôle
+ ROLE_CREATE("Création rôle", "ROLE", "CREATE"),
+ ROLE_UPDATE("Modification rôle", "ROLE", "UPDATE"),
+ ROLE_DELETE("Suppression rôle", "ROLE", "DELETE"),
+ ROLE_ASSIGN("Attribution rôle", "ROLE", "ASSIGN"),
+ ROLE_REVOKE("Révocation rôle", "ROLE", "REVOKE"),
+ ROLE_ADD_COMPOSITE("Ajout rôle composite", "ROLE", "ADD_COMPOSITE"),
+ ROLE_REMOVE_COMPOSITE("Retrait rôle composite", "ROLE", "REMOVE_COMPOSITE"),
+
+ // Actions Groupe
+ GROUP_CREATE("Création groupe", "GROUP", "CREATE"),
+ GROUP_UPDATE("Modification groupe", "GROUP", "UPDATE"),
+ GROUP_DELETE("Suppression groupe", "GROUP", "DELETE"),
+ GROUP_ADD_MEMBER("Ajout membre groupe", "GROUP", "ADD_MEMBER"),
+ GROUP_REMOVE_MEMBER("Retrait membre groupe", "GROUP", "REMOVE_MEMBER"),
+
+ // Actions Realm & Sync
+ REALM_SYNC("Synchronisation realm (Général)", "REALM", "SYNC"),
+ SYNC_USERS("Synchronisation utilisateurs", "REALM", "SYNC_USERS"), // Ajout
+ SYNC_ROLES("Synchronisation rôles", "REALM", "SYNC_ROLES"), // Ajout
+ REALM_EXPORT("Export realm", "REALM", "EXPORT"),
+ REALM_IMPORT("Import realm", "REALM", "IMPORT"),
+ REALM_ASSIGN("Assignation realm", "REALM", "ASSIGN"),
+ REALM_REVOKE("Révocation realm", "REALM", "REVOKE"),
+ REALM_ACTIVATE("Activation assignation realm", "REALM", "ACTIVATE"),
+ REALM_DEACTIVATE("Désactivation assignation realm", "REALM", "DEACTIVATE"),
+ REALM_SET_SUPER_ADMIN("Définition super admin", "REALM", "SET_SUPER_ADMIN"),
+
+ // Actions Session
+ SESSION_CREATE("Création session", "SESSION", "CREATE"),
+ SESSION_DELETE("Suppression session", "SESSION", "DELETE"),
+ SESSION_REVOKE_ALL("Révocation toutes sessions", "SESSION", "REVOKE_ALL"),
+
+ // Actions Système
+ SYSTEM_BACKUP("Sauvegarde système", "SYSTEM", "BACKUP"),
+ SYSTEM_RESTORE("Restauration système", "SYSTEM", "RESTORE"),
+ SYSTEM_CONFIG_CHANGE("Modification configuration", "SYSTEM", "CONFIG_CHANGE");
+
+ private final String libelle;
+ private final String ressourceType;
+ private final String actionType;
+
+ /**
+ * Détermine si l'action concerne un utilisateur
+ */
+ public boolean isUserAction() {
+ return ressourceType.equals("USER");
+ }
+
+ /**
+ * Détermine si l'action concerne un rôle
+ */
+ public boolean isRoleAction() {
+ return ressourceType.equals("ROLE");
+ }
+
+ /**
+ * Détermine si l'action est une création
+ */
+ public boolean isCreateAction() {
+ return actionType.equals("CREATE");
+ }
+
+ /**
+ * Détermine si l'action est une modification
+ */
+ public boolean isUpdateAction() {
+ return actionType.equals("UPDATE");
+ }
+
+ /**
+ * Détermine si l'action est une suppression
+ */
+ public boolean isDeleteAction() {
+ return actionType.equals("DELETE");
+ }
+
+ /**
+ * Détermine si l'action est critique (nécessite alerte)
+ */
+ public boolean isCritical() {
+ return this == USER_DELETE
+ || this == ROLE_DELETE
+ || this == USER_SUSPEND
+ || this == SESSION_REVOKE_ALL
+ || this == SYSTEM_RESTORE;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/enums/role/TypeRole.java b/src/main/java/dev/lions/user/manager/enums/role/TypeRole.java
index d1cc603..b1e8869 100644
--- a/src/main/java/dev/lions/user/manager/enums/role/TypeRole.java
+++ b/src/main/java/dev/lions/user/manager/enums/role/TypeRole.java
@@ -1,60 +1,60 @@
-package dev.lions.user.manager.enums.role;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-/**
- * Type de rôle dans Keycloak
- * Distingue les rôles au niveau Realm vs Client
- */
-@Getter
-@RequiredArgsConstructor
-@Schema(description = "Type de rôle Keycloak")
-public enum TypeRole {
-
- /**
- * Rôle global au niveau du Realm
- * Applicable à tous les clients du realm
- */
- REALM_ROLE("Realm Role", "Rôle global applicable à tous les clients du realm", "realm-role"),
-
- /**
- * Rôle spécifique à un client
- * Limité au scope d'un client particulier
- */
- CLIENT_ROLE("Client Role", "Rôle spécifique à un client particulier", "client-role"),
-
- /**
- * Rôle composite (contient d'autres rôles)
- */
- COMPOSITE_ROLE("Composite Role", "Rôle composite contenant d'autres rôles", "composite-role");
-
- private final String libelle;
- private final String description;
- private final String codeKeycloak;
-
- /**
- * Détermine si le rôle est au niveau realm
- * @return true si c'est un realm role
- */
- public boolean isRealmRole() {
- return this == REALM_ROLE;
- }
-
- /**
- * Détermine si le rôle est au niveau client
- * @return true si c'est un client role
- */
- public boolean isClientRole() {
- return this == CLIENT_ROLE;
- }
-
- /**
- * Détermine si le rôle est composite
- * @return true si c'est un composite role
- */
- public boolean isComposite() {
- return this == COMPOSITE_ROLE;
- }
-}
+package dev.lions.user.manager.enums.role;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+/**
+ * Type de rôle dans Keycloak
+ * Distingue les rôles au niveau Realm vs Client
+ */
+@Getter
+@RequiredArgsConstructor
+@Schema(description = "Type de rôle Keycloak")
+public enum TypeRole {
+
+ /**
+ * Rôle global au niveau du Realm
+ * Applicable à tous les clients du realm
+ */
+ REALM_ROLE("Realm Role", "Rôle global applicable à tous les clients du realm", "realm-role"),
+
+ /**
+ * Rôle spécifique à un client
+ * Limité au scope d'un client particulier
+ */
+ CLIENT_ROLE("Client Role", "Rôle spécifique à un client particulier", "client-role"),
+
+ /**
+ * Rôle composite (contient d'autres rôles)
+ */
+ COMPOSITE_ROLE("Composite Role", "Rôle composite contenant d'autres rôles", "composite-role");
+
+ private final String libelle;
+ private final String description;
+ private final String codeKeycloak;
+
+ /**
+ * Détermine si le rôle est au niveau realm
+ * @return true si c'est un realm role
+ */
+ public boolean isRealmRole() {
+ return this == REALM_ROLE;
+ }
+
+ /**
+ * Détermine si le rôle est au niveau client
+ * @return true si c'est un client role
+ */
+ public boolean isClientRole() {
+ return this == CLIENT_ROLE;
+ }
+
+ /**
+ * Détermine si le rôle est composite
+ * @return true si c'est un composite role
+ */
+ public boolean isComposite() {
+ return this == COMPOSITE_ROLE;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/enums/user/StatutUser.java b/src/main/java/dev/lions/user/manager/enums/user/StatutUser.java
index bcf0834..6a3ec58 100644
--- a/src/main/java/dev/lions/user/manager/enums/user/StatutUser.java
+++ b/src/main/java/dev/lions/user/manager/enums/user/StatutUser.java
@@ -1,79 +1,79 @@
-package dev.lions.user.manager.enums.user;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-/**
- * Statut d'un utilisateur dans Keycloak
- * Mappé depuis le champ "enabled" et attributs personnalisés
- */
-@Getter
-@RequiredArgsConstructor
-@Schema(description = "Statut d'un utilisateur")
-public enum StatutUser {
-
- /**
- * Utilisateur actif et opérationnel
- */
- ACTIF("Actif", "Utilisateur actif avec accès complet", true),
-
- /**
- * Utilisateur désactivé temporairement (peut être réactivé)
- */
- INACTIF("Inactif", "Utilisateur désactivé temporairement", false),
-
- /**
- * Utilisateur suspendu suite à une action administrative
- */
- SUSPENDU("Suspendu", "Compte suspendu par un administrateur", false),
-
- /**
- * Utilisateur en attente de validation
- */
- EN_ATTENTE("En attente", "Compte en attente de validation", false),
-
- /**
- * Utilisateur verrouillé suite à des tentatives échouées
- */
- VERROUILLE("Verrouillé", "Compte verrouillé suite à plusieurs échecs d'authentification", false),
-
- /**
- * Utilisateur dont le compte a expiré
- */
- EXPIRE("Expiré", "Compte expiré et nécessite une réactivation", false),
-
- /**
- * Utilisateur supprimé (soft delete)
- */
- SUPPRIME("Supprimé", "Compte supprimé logiquement", false);
-
- private final String libelle;
- private final String description;
- private final boolean enabled;
-
- /**
- * Convertit un statut Keycloak "enabled" en StatutUser
- * @param enabled état enabled de Keycloak
- * @return ACTIF si enabled=true, INACTIF sinon
- */
- public static StatutUser fromEnabled(boolean enabled) {
- return enabled ? ACTIF : INACTIF;
- }
-
- /**
- * Détermine si l'utilisateur peut se connecter
- * @return true si le statut permet la connexion
- */
- public boolean peutSeConnecter() {
- return this == ACTIF;
- }
-
- /**
- * Détermine si l'utilisateur peut être réactivé
- * @return true si le statut permet la réactivation
- */
- public boolean peutEtreReactive() {
- return this == INACTIF || this == SUSPENDU || this == EXPIRE;
- }
-}
+package dev.lions.user.manager.enums.user;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+/**
+ * Statut d'un utilisateur dans Keycloak
+ * Mappé depuis le champ "enabled" et attributs personnalisés
+ */
+@Getter
+@RequiredArgsConstructor
+@Schema(description = "Statut d'un utilisateur")
+public enum StatutUser {
+
+ /**
+ * Utilisateur actif et opérationnel
+ */
+ ACTIF("Actif", "Utilisateur actif avec accès complet", true),
+
+ /**
+ * Utilisateur désactivé temporairement (peut être réactivé)
+ */
+ INACTIF("Inactif", "Utilisateur désactivé temporairement", false),
+
+ /**
+ * Utilisateur suspendu suite à une action administrative
+ */
+ SUSPENDU("Suspendu", "Compte suspendu par un administrateur", false),
+
+ /**
+ * Utilisateur en attente de validation
+ */
+ EN_ATTENTE("En attente", "Compte en attente de validation", false),
+
+ /**
+ * Utilisateur verrouillé suite à des tentatives échouées
+ */
+ VERROUILLE("Verrouillé", "Compte verrouillé suite à plusieurs échecs d'authentification", false),
+
+ /**
+ * Utilisateur dont le compte a expiré
+ */
+ EXPIRE("Expiré", "Compte expiré et nécessite une réactivation", false),
+
+ /**
+ * Utilisateur supprimé (soft delete)
+ */
+ SUPPRIME("Supprimé", "Compte supprimé logiquement", false);
+
+ private final String libelle;
+ private final String description;
+ private final boolean enabled;
+
+ /**
+ * Convertit un statut Keycloak "enabled" en StatutUser
+ * @param enabled état enabled de Keycloak
+ * @return ACTIF si enabled=true, INACTIF sinon
+ */
+ public static StatutUser fromEnabled(boolean enabled) {
+ return enabled ? ACTIF : INACTIF;
+ }
+
+ /**
+ * Détermine si l'utilisateur peut se connecter
+ * @return true si le statut permet la connexion
+ */
+ public boolean peutSeConnecter() {
+ return this == ACTIF;
+ }
+
+ /**
+ * Détermine si l'utilisateur peut être réactivé
+ * @return true si le statut permet la réactivation
+ */
+ public boolean peutEtreReactive() {
+ return this == INACTIF || this == SUSPENDU || this == EXPIRE;
+ }
+}
diff --git a/src/main/java/dev/lions/user/manager/service/AuditService.java b/src/main/java/dev/lions/user/manager/service/AuditService.java
index ee6d729..64b0729 100644
--- a/src/main/java/dev/lions/user/manager/service/AuditService.java
+++ b/src/main/java/dev/lions/user/manager/service/AuditService.java
@@ -1,219 +1,219 @@
-package dev.lions.user.manager.service;
-
-import dev.lions.user.manager.dto.audit.AuditLogDTO;
-import dev.lions.user.manager.enums.audit.TypeActionAudit;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Service de gestion des logs d'audit
- * Enregistre toutes les actions effectuées via l'API
- */
-public interface AuditService {
-
- /**
- * Enregistre une entrée d'audit
- * @param auditLog entrée d'audit
- * @return entrée enregistrée avec son ID
- */
- AuditLogDTO logAction(@Valid @NotNull AuditLogDTO auditLog);
-
- /**
- * Enregistre une action réussie
- * @param typeAction type d'action
- * @param ressourceType type de ressource
- * @param ressourceId ID de la ressource
- * @param ressourceName nom de la ressource
- * @param realmName nom du realm
- * @param acteurUserId ID de l'acteur
- * @param description description
- */
- void logSuccess(@NotNull TypeActionAudit typeAction,
- @NotBlank String ressourceType,
- String ressourceId,
- String ressourceName,
- @NotBlank String realmName,
- @NotBlank String acteurUserId,
- String description);
-
- /**
- * Enregistre une action échouée
- * @param typeAction type d'action
- * @param ressourceType type de ressource
- * @param ressourceId ID de la ressource
- * @param ressourceName nom de la ressource
- * @param realmName nom du realm
- * @param acteurUserId ID de l'acteur
- * @param errorCode code d'erreur
- * @param errorMessage message d'erreur
- */
- void logFailure(@NotNull TypeActionAudit typeAction,
- @NotBlank String ressourceType,
- String ressourceId,
- String ressourceName,
- @NotBlank String realmName,
- @NotBlank String acteurUserId,
- String errorCode,
- String errorMessage);
-
- /**
- * Recherche les logs d'audit par utilisateur acteur
- * @param acteurUserId ID de l'utilisateur acteur
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste des logs
- */
- List findByActeur(@NotBlank String acteurUserId,
- LocalDateTime dateDebut,
- LocalDateTime dateFin,
- int page,
- int pageSize);
-
- /**
- * Recherche les logs d'audit par ressource
- * @param ressourceType type de ressource
- * @param ressourceId ID de la ressource
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste des logs
- */
- List findByRessource(@NotBlank String ressourceType,
- @NotBlank String ressourceId,
- LocalDateTime dateDebut,
- LocalDateTime dateFin,
- int page,
- int pageSize);
-
- /**
- * Recherche les logs d'audit par type d'action
- * @param typeAction type d'action
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste des logs
- */
- List findByTypeAction(@NotNull TypeActionAudit typeAction,
- @NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin,
- int page,
- int pageSize);
-
- /**
- * Recherche les logs d'audit par realm
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste des logs
- */
- List findByRealm(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin,
- int page,
- int pageSize);
-
- /**
- * Recherche les actions échouées
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste des logs d'échec
- */
- List findFailures(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin,
- int page,
- int pageSize);
-
- /**
- * Recherche les actions critiques
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste des logs critiques
- */
- List findCriticalActions(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin,
- int page,
- int pageSize);
-
- /**
- * Compte les actions par type
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @return map type d'action -> nombre
- */
- Map countByActionType(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin);
-
- /**
- * Compte les actions par utilisateur
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @return map username -> nombre d'actions
- */
- Map countByActeur(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin);
-
- /**
- * Compte les actions réussies vs échouées
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @return map "success" -> count, "failure" -> count
- */
- Map countSuccessVsFailure(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin);
-
- /**
- * Exporte les logs d'audit au format CSV
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @return contenu CSV
- */
- String exportToCSV(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin);
-
- /**
- * Supprime les logs d'audit plus anciens qu'une date
- * @param dateLimite date limite (logs antérieurs seront supprimés)
- * @return nombre de logs supprimés
- */
- long purgeOldLogs(@NotNull LocalDateTime dateLimite);
-
- /**
- * Récupère les statistiques d'audit pour un dashboard
- * @param realmName nom du realm
- * @param dateDebut date de début
- * @param dateFin date de fin
- * @return map de statistiques
- */
- Map getAuditStatistics(@NotBlank String realmName,
- LocalDateTime dateDebut,
- LocalDateTime dateFin);
-}
+package dev.lions.user.manager.service;
+
+import dev.lions.user.manager.dto.audit.AuditLogDTO;
+import dev.lions.user.manager.enums.audit.TypeActionAudit;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Service de gestion des logs d'audit
+ * Enregistre toutes les actions effectuées via l'API
+ */
+public interface AuditService {
+
+ /**
+ * Enregistre une entrée d'audit
+ * @param auditLog entrée d'audit
+ * @return entrée enregistrée avec son ID
+ */
+ AuditLogDTO logAction(@Valid @NotNull AuditLogDTO auditLog);
+
+ /**
+ * Enregistre une action réussie
+ * @param typeAction type d'action
+ * @param ressourceType type de ressource
+ * @param ressourceId ID de la ressource
+ * @param ressourceName nom de la ressource
+ * @param realmName nom du realm
+ * @param acteurUserId ID de l'acteur
+ * @param description description
+ */
+ void logSuccess(@NotNull TypeActionAudit typeAction,
+ @NotBlank String ressourceType,
+ String ressourceId,
+ String ressourceName,
+ @NotBlank String realmName,
+ @NotBlank String acteurUserId,
+ String description);
+
+ /**
+ * Enregistre une action échouée
+ * @param typeAction type d'action
+ * @param ressourceType type de ressource
+ * @param ressourceId ID de la ressource
+ * @param ressourceName nom de la ressource
+ * @param realmName nom du realm
+ * @param acteurUserId ID de l'acteur
+ * @param errorCode code d'erreur
+ * @param errorMessage message d'erreur
+ */
+ void logFailure(@NotNull TypeActionAudit typeAction,
+ @NotBlank String ressourceType,
+ String ressourceId,
+ String ressourceName,
+ @NotBlank String realmName,
+ @NotBlank String acteurUserId,
+ String errorCode,
+ String errorMessage);
+
+ /**
+ * Recherche les logs d'audit par utilisateur acteur
+ * @param acteurUserId ID de l'utilisateur acteur
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste des logs
+ */
+ List findByActeur(@NotBlank String acteurUserId,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin,
+ int page,
+ int pageSize);
+
+ /**
+ * Recherche les logs d'audit par ressource
+ * @param ressourceType type de ressource
+ * @param ressourceId ID de la ressource
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste des logs
+ */
+ List findByRessource(@NotBlank String ressourceType,
+ @NotBlank String ressourceId,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin,
+ int page,
+ int pageSize);
+
+ /**
+ * Recherche les logs d'audit par type d'action
+ * @param typeAction type d'action
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste des logs
+ */
+ List findByTypeAction(@NotNull TypeActionAudit typeAction,
+ @NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin,
+ int page,
+ int pageSize);
+
+ /**
+ * Recherche les logs d'audit par realm
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste des logs
+ */
+ List findByRealm(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin,
+ int page,
+ int pageSize);
+
+ /**
+ * Recherche les actions échouées
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste des logs d'échec
+ */
+ List findFailures(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin,
+ int page,
+ int pageSize);
+
+ /**
+ * Recherche les actions critiques
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste des logs critiques
+ */
+ List findCriticalActions(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin,
+ int page,
+ int pageSize);
+
+ /**
+ * Compte les actions par type
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @return map type d'action -> nombre
+ */
+ Map countByActionType(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin);
+
+ /**
+ * Compte les actions par utilisateur
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @return map username -> nombre d'actions
+ */
+ Map countByActeur(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin);
+
+ /**
+ * Compte les actions réussies vs échouées
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @return map "success" -> count, "failure" -> count
+ */
+ Map countSuccessVsFailure(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin);
+
+ /**
+ * Exporte les logs d'audit au format CSV
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @return contenu CSV
+ */
+ String exportToCSV(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin);
+
+ /**
+ * Supprime les logs d'audit plus anciens qu'une date
+ * @param dateLimite date limite (logs antérieurs seront supprimés)
+ * @return nombre de logs supprimés
+ */
+ long purgeOldLogs(@NotNull LocalDateTime dateLimite);
+
+ /**
+ * Récupère les statistiques d'audit pour un dashboard
+ * @param realmName nom du realm
+ * @param dateDebut date de début
+ * @param dateFin date de fin
+ * @return map de statistiques
+ */
+ Map getAuditStatistics(@NotBlank String realmName,
+ LocalDateTime dateDebut,
+ LocalDateTime dateFin);
+}
diff --git a/src/main/java/dev/lions/user/manager/service/RealmAuthorizationService.java b/src/main/java/dev/lions/user/manager/service/RealmAuthorizationService.java
index 527ad63..e921543 100644
--- a/src/main/java/dev/lions/user/manager/service/RealmAuthorizationService.java
+++ b/src/main/java/dev/lions/user/manager/service/RealmAuthorizationService.java
@@ -1,132 +1,132 @@
-package dev.lions.user.manager.service;
-
-import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Service de gestion des autorisations multi-tenant par realm
- * Permet de contrôler quels utilisateurs peuvent administrer quels realms
- */
-public interface RealmAuthorizationService {
-
- /**
- * Récupère toutes les assignations de realms
- * @return liste de toutes les assignations
- */
- List getAllAssignments();
-
- /**
- * Récupère les assignations pour un utilisateur spécifique
- * @param userId ID de l'utilisateur Keycloak
- * @return liste des realms assignés à cet utilisateur
- */
- List getAssignmentsByUser(@NotBlank String userId);
-
- /**
- * Récupère les assignations pour un realm spécifique
- * @param realmName nom du realm
- * @return liste des utilisateurs ayant accès à ce realm
- */
- List getAssignmentsByRealm(@NotBlank String realmName);
-
- /**
- * Récupère une assignation spécifique
- * @param assignmentId ID de l'assignation
- * @return assignation ou Optional vide
- */
- Optional getAssignmentById(@NotBlank String assignmentId);
-
- /**
- * Vérifie si un utilisateur peut administrer un realm donné
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return true si l'utilisateur peut administrer ce realm
- */
- boolean canManageRealm(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Vérifie si un utilisateur est super admin (peut tout gérer)
- * @param userId ID de l'utilisateur
- * @return true si super admin
- */
- boolean isSuperAdmin(@NotBlank String userId);
-
- /**
- * Récupère la liste des realms qu'un utilisateur peut administrer
- * @param userId ID de l'utilisateur
- * @return liste des noms de realms, ou liste vide si super admin (peut tout gérer)
- */
- List getAuthorizedRealms(@NotBlank String userId);
-
- /**
- * Assigne un realm à un utilisateur
- * @param assignment données de l'assignation
- * @return assignation créée
- */
- RealmAssignmentDTO assignRealmToUser(@Valid @NotNull RealmAssignmentDTO assignment);
-
- /**
- * Retire l'accès d'un utilisateur à un realm
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- */
- void revokeRealmFromUser(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Retire toutes les assignations d'un utilisateur
- * @param userId ID de l'utilisateur
- */
- void revokeAllRealmsFromUser(@NotBlank String userId);
-
- /**
- * Retire toutes les assignations pour un realm
- * @param realmName nom du realm
- */
- void revokeAllUsersFromRealm(@NotBlank String realmName);
-
- /**
- * Définit un utilisateur comme super admin
- * @param userId ID de l'utilisateur
- * @param superAdmin true pour définir comme super admin, false pour retirer
- */
- void setSuperAdmin(@NotBlank String userId, boolean superAdmin);
-
- /**
- * Désactive une assignation (sans la supprimer)
- * @param assignmentId ID de l'assignation
- */
- void deactivateAssignment(@NotBlank String assignmentId);
-
- /**
- * Réactive une assignation
- * @param assignmentId ID de l'assignation
- */
- void activateAssignment(@NotBlank String assignmentId);
-
- /**
- * Compte le nombre d'assignations pour un utilisateur
- * @param userId ID de l'utilisateur
- * @return nombre d'assignations actives
- */
- long countAssignmentsByUser(@NotBlank String userId);
-
- /**
- * Compte le nombre d'utilisateurs ayant accès à un realm
- * @param realmName nom du realm
- * @return nombre d'utilisateurs
- */
- long countUsersByRealm(@NotBlank String realmName);
-
- /**
- * Vérifie si une assignation existe
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return true si l'assignation existe
- */
- boolean assignmentExists(@NotBlank String userId, @NotBlank String realmName);
-}
+package dev.lions.user.manager.service;
+
+import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Service de gestion des autorisations multi-tenant par realm
+ * Permet de contrôler quels utilisateurs peuvent administrer quels realms
+ */
+public interface RealmAuthorizationService {
+
+ /**
+ * Récupère toutes les assignations de realms
+ * @return liste de toutes les assignations
+ */
+ List getAllAssignments();
+
+ /**
+ * Récupère les assignations pour un utilisateur spécifique
+ * @param userId ID de l'utilisateur Keycloak
+ * @return liste des realms assignés à cet utilisateur
+ */
+ List getAssignmentsByUser(@NotBlank String userId);
+
+ /**
+ * Récupère les assignations pour un realm spécifique
+ * @param realmName nom du realm
+ * @return liste des utilisateurs ayant accès à ce realm
+ */
+ List getAssignmentsByRealm(@NotBlank String realmName);
+
+ /**
+ * Récupère une assignation spécifique
+ * @param assignmentId ID de l'assignation
+ * @return assignation ou Optional vide
+ */
+ Optional getAssignmentById(@NotBlank String assignmentId);
+
+ /**
+ * Vérifie si un utilisateur peut administrer un realm donné
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return true si l'utilisateur peut administrer ce realm
+ */
+ boolean canManageRealm(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Vérifie si un utilisateur est super admin (peut tout gérer)
+ * @param userId ID de l'utilisateur
+ * @return true si super admin
+ */
+ boolean isSuperAdmin(@NotBlank String userId);
+
+ /**
+ * Récupère la liste des realms qu'un utilisateur peut administrer
+ * @param userId ID de l'utilisateur
+ * @return liste des noms de realms, ou liste vide si super admin (peut tout gérer)
+ */
+ List getAuthorizedRealms(@NotBlank String userId);
+
+ /**
+ * Assigne un realm à un utilisateur
+ * @param assignment données de l'assignation
+ * @return assignation créée
+ */
+ RealmAssignmentDTO assignRealmToUser(@Valid @NotNull RealmAssignmentDTO assignment);
+
+ /**
+ * Retire l'accès d'un utilisateur à un realm
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ */
+ void revokeRealmFromUser(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Retire toutes les assignations d'un utilisateur
+ * @param userId ID de l'utilisateur
+ */
+ void revokeAllRealmsFromUser(@NotBlank String userId);
+
+ /**
+ * Retire toutes les assignations pour un realm
+ * @param realmName nom du realm
+ */
+ void revokeAllUsersFromRealm(@NotBlank String realmName);
+
+ /**
+ * Définit un utilisateur comme super admin
+ * @param userId ID de l'utilisateur
+ * @param superAdmin true pour définir comme super admin, false pour retirer
+ */
+ void setSuperAdmin(@NotBlank String userId, boolean superAdmin);
+
+ /**
+ * Désactive une assignation (sans la supprimer)
+ * @param assignmentId ID de l'assignation
+ */
+ void deactivateAssignment(@NotBlank String assignmentId);
+
+ /**
+ * Réactive une assignation
+ * @param assignmentId ID de l'assignation
+ */
+ void activateAssignment(@NotBlank String assignmentId);
+
+ /**
+ * Compte le nombre d'assignations pour un utilisateur
+ * @param userId ID de l'utilisateur
+ * @return nombre d'assignations actives
+ */
+ long countAssignmentsByUser(@NotBlank String userId);
+
+ /**
+ * Compte le nombre d'utilisateurs ayant accès à un realm
+ * @param realmName nom du realm
+ * @return nombre d'utilisateurs
+ */
+ long countUsersByRealm(@NotBlank String realmName);
+
+ /**
+ * Vérifie si une assignation existe
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return true si l'assignation existe
+ */
+ boolean assignmentExists(@NotBlank String userId, @NotBlank String realmName);
+}
diff --git a/src/main/java/dev/lions/user/manager/service/RoleService.java b/src/main/java/dev/lions/user/manager/service/RoleService.java
index b38d361..1813a9f 100644
--- a/src/main/java/dev/lions/user/manager/service/RoleService.java
+++ b/src/main/java/dev/lions/user/manager/service/RoleService.java
@@ -1,226 +1,226 @@
-package dev.lions.user.manager.service;
-
-import dev.lions.user.manager.dto.role.RoleAssignmentDTO;
-import dev.lions.user.manager.dto.role.RoleDTO;
-import dev.lions.user.manager.enums.role.TypeRole;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Service de gestion des rôles Keycloak
- * Utilise uniquement l'API Admin Keycloak (AUCUN accès direct à la DB)
- */
-public interface RoleService {
-
- /**
- * Récupère tous les rôles d'un realm
- * @param realmName nom du realm
- * @return liste des rôles
- */
- List getAllRealmRoles(@NotBlank String realmName);
-
- /**
- * Récupère tous les rôles d'un client
- * @param realmName nom du realm
- * @param clientName nom du client
- * @return liste des rôles
- */
- List getAllClientRoles(@NotBlank String realmName, @NotBlank String clientName);
-
- /**
- * Récupère un rôle par son ID
- * @param roleId ID du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle (REALM ou CLIENT)
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return rôle ou Optional vide
- */
- Optional getRoleById(@NotBlank String roleId,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Récupère un rôle par son nom
- * @param roleName nom du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle (REALM ou CLIENT)
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return rôle ou Optional vide
- */
- Optional getRoleByName(@NotBlank String roleName,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Crée un nouveau rôle realm
- * @param role données du rôle
- * @param realmName nom du realm
- * @return rôle créé
- */
- RoleDTO createRealmRole(@Valid @NotNull RoleDTO role, @NotBlank String realmName);
-
- /**
- * Crée un nouveau rôle client
- * @param role données du rôle
- * @param realmName nom du realm
- * @param clientName nom du client
- * @return rôle créé
- */
- RoleDTO createClientRole(@Valid @NotNull RoleDTO role,
- @NotBlank String realmName,
- @NotBlank String clientName);
-
- /**
- * Met à jour un rôle
- * @param roleId ID du rôle
- * @param role données modifiées
- * @param realmName nom du realm
- * @param typeRole type de rôle
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return rôle mis à jour
- */
- RoleDTO updateRole(@NotBlank String roleId,
- @Valid @NotNull RoleDTO role,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Supprime un rôle
- * @param roleId ID du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle
- * @param clientName nom du client (si CLIENT_ROLE)
- */
- void deleteRole(@NotBlank String roleId,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Assigne des rôles à un utilisateur
- * @param assignment données d'attribution
- */
- void assignRolesToUser(@Valid @NotNull RoleAssignmentDTO assignment);
-
- /**
- * Révoque des rôles d'un utilisateur
- * @param assignment données de révocation
- */
- void revokeRolesFromUser(@Valid @NotNull RoleAssignmentDTO assignment);
-
- /**
- * Récupère les rôles realm d'un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return liste des rôles
- */
- List getUserRealmRoles(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Récupère les rôles client d'un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @param clientName nom du client
- * @return liste des rôles
- */
- List getUserClientRoles(@NotBlank String userId,
- @NotBlank String realmName,
- @NotBlank String clientName);
-
- /**
- * Récupère tous les rôles d'un utilisateur (realm + clients)
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return liste des rôles
- */
- List getAllUserRoles(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Ajoute un rôle composite
- * @param parentRoleId ID du rôle parent
- * @param childRoleIds IDs des rôles enfants à ajouter
- * @param realmName nom du realm
- * @param typeRole type du rôle parent
- * @param clientName nom du client (si CLIENT_ROLE)
- */
- void addCompositeRoles(@NotBlank String parentRoleId,
- @NotNull List childRoleIds,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Retire un rôle composite
- * @param parentRoleId ID du rôle parent
- * @param childRoleIds IDs des rôles enfants à retirer
- * @param realmName nom du realm
- * @param typeRole type du rôle parent
- * @param clientName nom du client (si CLIENT_ROLE)
- */
- void removeCompositeRoles(@NotBlank String parentRoleId,
- @NotNull List childRoleIds,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Récupère les rôles composites d'un rôle
- * @param roleId ID du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return liste des rôles composites
- */
- List getCompositeRoles(@NotBlank String roleId,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Compte le nombre d'utilisateurs ayant un rôle
- * @param roleId ID du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return nombre d'utilisateurs
- */
- long countUsersWithRole(@NotBlank String roleId,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Vérifie si un rôle existe
- * @param roleName nom du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return true si existe
- */
- boolean roleExists(@NotBlank String roleName,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-
- /**
- * Vérifie si un utilisateur a un rôle spécifique
- * @param userId ID de l'utilisateur
- * @param roleName nom du rôle
- * @param realmName nom du realm
- * @param typeRole type de rôle
- * @param clientName nom du client (si CLIENT_ROLE)
- * @return true si l'utilisateur a le rôle
- */
- boolean userHasRole(@NotBlank String userId,
- @NotBlank String roleName,
- @NotBlank String realmName,
- @NotNull TypeRole typeRole,
- String clientName);
-}
+package dev.lions.user.manager.service;
+
+import dev.lions.user.manager.dto.role.RoleAssignmentDTO;
+import dev.lions.user.manager.dto.role.RoleDTO;
+import dev.lions.user.manager.enums.role.TypeRole;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Service de gestion des rôles Keycloak
+ * Utilise uniquement l'API Admin Keycloak (AUCUN accès direct à la DB)
+ */
+public interface RoleService {
+
+ /**
+ * Récupère tous les rôles d'un realm
+ * @param realmName nom du realm
+ * @return liste des rôles
+ */
+ List getAllRealmRoles(@NotBlank String realmName);
+
+ /**
+ * Récupère tous les rôles d'un client
+ * @param realmName nom du realm
+ * @param clientName nom du client
+ * @return liste des rôles
+ */
+ List getAllClientRoles(@NotBlank String realmName, @NotBlank String clientName);
+
+ /**
+ * Récupère un rôle par son ID
+ * @param roleId ID du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle (REALM ou CLIENT)
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return rôle ou Optional vide
+ */
+ Optional getRoleById(@NotBlank String roleId,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Récupère un rôle par son nom
+ * @param roleName nom du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle (REALM ou CLIENT)
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return rôle ou Optional vide
+ */
+ Optional getRoleByName(@NotBlank String roleName,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Crée un nouveau rôle realm
+ * @param role données du rôle
+ * @param realmName nom du realm
+ * @return rôle créé
+ */
+ RoleDTO createRealmRole(@Valid @NotNull RoleDTO role, @NotBlank String realmName);
+
+ /**
+ * Crée un nouveau rôle client
+ * @param role données du rôle
+ * @param realmName nom du realm
+ * @param clientName nom du client
+ * @return rôle créé
+ */
+ RoleDTO createClientRole(@Valid @NotNull RoleDTO role,
+ @NotBlank String realmName,
+ @NotBlank String clientName);
+
+ /**
+ * Met à jour un rôle
+ * @param roleId ID du rôle
+ * @param role données modifiées
+ * @param realmName nom du realm
+ * @param typeRole type de rôle
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return rôle mis à jour
+ */
+ RoleDTO updateRole(@NotBlank String roleId,
+ @Valid @NotNull RoleDTO role,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Supprime un rôle
+ * @param roleId ID du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle
+ * @param clientName nom du client (si CLIENT_ROLE)
+ */
+ void deleteRole(@NotBlank String roleId,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Assigne des rôles à un utilisateur
+ * @param assignment données d'attribution
+ */
+ void assignRolesToUser(@Valid @NotNull RoleAssignmentDTO assignment);
+
+ /**
+ * Révoque des rôles d'un utilisateur
+ * @param assignment données de révocation
+ */
+ void revokeRolesFromUser(@Valid @NotNull RoleAssignmentDTO assignment);
+
+ /**
+ * Récupère les rôles realm d'un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return liste des rôles
+ */
+ List getUserRealmRoles(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Récupère les rôles client d'un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @param clientName nom du client
+ * @return liste des rôles
+ */
+ List getUserClientRoles(@NotBlank String userId,
+ @NotBlank String realmName,
+ @NotBlank String clientName);
+
+ /**
+ * Récupère tous les rôles d'un utilisateur (realm + clients)
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return liste des rôles
+ */
+ List getAllUserRoles(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Ajoute un rôle composite
+ * @param parentRoleId ID du rôle parent
+ * @param childRoleIds IDs des rôles enfants à ajouter
+ * @param realmName nom du realm
+ * @param typeRole type du rôle parent
+ * @param clientName nom du client (si CLIENT_ROLE)
+ */
+ void addCompositeRoles(@NotBlank String parentRoleId,
+ @NotNull List childRoleIds,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Retire un rôle composite
+ * @param parentRoleId ID du rôle parent
+ * @param childRoleIds IDs des rôles enfants à retirer
+ * @param realmName nom du realm
+ * @param typeRole type du rôle parent
+ * @param clientName nom du client (si CLIENT_ROLE)
+ */
+ void removeCompositeRoles(@NotBlank String parentRoleId,
+ @NotNull List childRoleIds,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Récupère les rôles composites d'un rôle
+ * @param roleId ID du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return liste des rôles composites
+ */
+ List getCompositeRoles(@NotBlank String roleId,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Compte le nombre d'utilisateurs ayant un rôle
+ * @param roleId ID du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return nombre d'utilisateurs
+ */
+ long countUsersWithRole(@NotBlank String roleId,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Vérifie si un rôle existe
+ * @param roleName nom du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return true si existe
+ */
+ boolean roleExists(@NotBlank String roleName,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+
+ /**
+ * Vérifie si un utilisateur a un rôle spécifique
+ * @param userId ID de l'utilisateur
+ * @param roleName nom du rôle
+ * @param realmName nom du realm
+ * @param typeRole type de rôle
+ * @param clientName nom du client (si CLIENT_ROLE)
+ * @return true si l'utilisateur a le rôle
+ */
+ boolean userHasRole(@NotBlank String userId,
+ @NotBlank String roleName,
+ @NotBlank String realmName,
+ @NotNull TypeRole typeRole,
+ String clientName);
+}
diff --git a/src/main/java/dev/lions/user/manager/service/SyncService.java b/src/main/java/dev/lions/user/manager/service/SyncService.java
index b0cfb91..b9600ab 100644
--- a/src/main/java/dev/lions/user/manager/service/SyncService.java
+++ b/src/main/java/dev/lions/user/manager/service/SyncService.java
@@ -1,65 +1,65 @@
-package dev.lions.user.manager.service;
-
-import jakarta.validation.constraints.NotBlank;
-
-import java.util.Map;
-
-/**
- * Service de synchronisation avec Keycloak
- * Permet la synchronisation des données entre différents realms
- */
-public interface SyncService {
-
- /**
- * Synchronise les utilisateurs d'un realm
- * @param realmName nom du realm à synchroniser
- * @return nombre d'utilisateurs synchronisés
- */
- int syncUsersFromRealm(@NotBlank String realmName);
-
- /**
- * Synchronise les rôles d'un realm
- * @param realmName nom du realm à synchroniser
- * @return nombre de rôles synchronisés
- */
- int syncRolesFromRealm(@NotBlank String realmName);
-
- /**
- * Synchronise tous les realms configurés
- * @return map realm -> nombre d'éléments synchronisés
- */
- Map syncAllRealms();
-
- /**
- * Vérifie la cohérence des données entre cache local et Keycloak
- * @param realmName nom du realm
- * @return rapport de cohérence
- */
- Map checkDataConsistency(@NotBlank String realmName);
-
- /**
- * Force la resynchronisation complète d'un realm
- * @param realmName nom du realm
- * @return statistiques de synchronisation
- */
- Map forceSyncRealm(@NotBlank String realmName);
-
- /**
- * Récupère le statut de la dernière synchronisation
- * @param realmName nom du realm
- * @return statut de synchronisation
- */
- Map getLastSyncStatus(@NotBlank String realmName);
-
- /**
- * Vérifie la disponibilité de Keycloak
- * @return true si Keycloak est disponible
- */
- boolean isKeycloakAvailable();
-
- /**
- * Récupère les informations de santé de Keycloak
- * @return informations de santé
- */
- Map getKeycloakHealthInfo();
-}
+package dev.lions.user.manager.service;
+
+import jakarta.validation.constraints.NotBlank;
+
+import java.util.Map;
+
+/**
+ * Service de synchronisation avec Keycloak
+ * Permet la synchronisation des données entre différents realms
+ */
+public interface SyncService {
+
+ /**
+ * Synchronise les utilisateurs d'un realm
+ * @param realmName nom du realm à synchroniser
+ * @return nombre d'utilisateurs synchronisés
+ */
+ int syncUsersFromRealm(@NotBlank String realmName);
+
+ /**
+ * Synchronise les rôles d'un realm
+ * @param realmName nom du realm à synchroniser
+ * @return nombre de rôles synchronisés
+ */
+ int syncRolesFromRealm(@NotBlank String realmName);
+
+ /**
+ * Synchronise tous les realms configurés
+ * @return map realm -> nombre d'éléments synchronisés
+ */
+ Map syncAllRealms();
+
+ /**
+ * Vérifie la cohérence des données entre cache local et Keycloak
+ * @param realmName nom du realm
+ * @return rapport de cohérence
+ */
+ Map checkDataConsistency(@NotBlank String realmName);
+
+ /**
+ * Force la resynchronisation complète d'un realm
+ * @param realmName nom du realm
+ * @return statistiques de synchronisation
+ */
+ Map forceSyncRealm(@NotBlank String realmName);
+
+ /**
+ * Récupère le statut de la dernière synchronisation
+ * @param realmName nom du realm
+ * @return statut de synchronisation
+ */
+ Map getLastSyncStatus(@NotBlank String realmName);
+
+ /**
+ * Vérifie la disponibilité de Keycloak
+ * @return true si Keycloak est disponible
+ */
+ boolean isKeycloakAvailable();
+
+ /**
+ * Récupère les informations de santé de Keycloak
+ * @return informations de santé
+ */
+ Map getKeycloakHealthInfo();
+}
diff --git a/src/main/java/dev/lions/user/manager/service/UserService.java b/src/main/java/dev/lions/user/manager/service/UserService.java
index 8e26274..4f8236c 100644
--- a/src/main/java/dev/lions/user/manager/service/UserService.java
+++ b/src/main/java/dev/lions/user/manager/service/UserService.java
@@ -1,185 +1,185 @@
-package dev.lions.user.manager.service;
-
-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.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- * Service de gestion des utilisateurs Keycloak
- * Utilise uniquement l'API Admin Keycloak (AUCUN accès direct à la DB)
- */
-public interface UserService {
-
- /**
- * Recherche des utilisateurs selon des critères
- * @param criteria critères de recherche
- * @return résultat paginé
- */
- UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria);
-
- /**
- * Récupère un utilisateur par son ID
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return utilisateur ou Optional vide
- */
- Optional getUserById(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Récupère un utilisateur par son username
- * @param username username
- * @param realmName nom du realm
- * @return utilisateur ou Optional vide
- */
- Optional getUserByUsername(@NotBlank String username, @NotBlank String realmName);
-
- /**
- * Récupère un utilisateur par son email
- * @param email email
- * @param realmName nom du realm
- * @return utilisateur ou Optional vide
- */
- Optional getUserByEmail(@NotBlank String email, @NotBlank String realmName);
-
- /**
- * Crée un nouvel utilisateur
- * @param user données de l'utilisateur
- * @param realmName nom du realm
- * @return utilisateur créé avec son ID
- */
- UserDTO createUser(@Valid @NotNull UserDTO user, @NotBlank String realmName);
-
- /**
- * Met à jour un utilisateur existant
- * @param userId ID de l'utilisateur
- * @param user données modifiées
- * @param realmName nom du realm
- * @return utilisateur mis à jour
- */
- UserDTO updateUser(@NotBlank String userId, @Valid @NotNull UserDTO user, @NotBlank String realmName);
-
- /**
- * Supprime un utilisateur (soft ou hard delete selon configuration)
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @param hardDelete true pour suppression définitive, false pour soft delete
- */
- void deleteUser(@NotBlank String userId, @NotBlank String realmName, boolean hardDelete);
-
- /**
- * Active un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- */
- void activateUser(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Désactive un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @param raison raison de la désactivation
- */
- void deactivateUser(@NotBlank String userId, @NotBlank String realmName, String raison);
-
- /**
- * Suspend un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @param raison raison de la suspension
- * @param duree durée de la suspension en jours (0 = indéfinie)
- */
- void suspendUser(@NotBlank String userId, @NotBlank String realmName, String raison, int duree);
-
- /**
- * Déverrouille un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- */
- void unlockUser(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Réinitialise le mot de passe d'un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @param temporaryPassword mot de passe temporaire
- * @param temporary true si le mot de passe doit être changé à la prochaine connexion
- */
- void resetPassword(@NotBlank String userId, @NotBlank String realmName,
- @NotBlank String temporaryPassword, boolean temporary);
-
- /**
- * Envoie un email de vérification
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- */
- void sendVerificationEmail(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Force la déconnexion de toutes les sessions d'un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return nombre de sessions révoquées
- */
- int logoutAllSessions(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Récupère les sessions actives d'un utilisateur
- * @param userId ID de l'utilisateur
- * @param realmName nom du realm
- * @return liste des informations de session
- */
- List getActiveSessions(@NotBlank String userId, @NotBlank String realmName);
-
- /**
- * Compte le nombre d'utilisateurs selon des critères
- * @param criteria critères de recherche
- * @return nombre d'utilisateurs
- */
- long countUsers(@NotNull UserSearchCriteriaDTO criteria);
-
- /**
- * Récupère tous les utilisateurs d'un realm (avec pagination)
- * @param realmName nom du realm
- * @param page numéro de page
- * @param pageSize taille de la page
- * @return liste paginée d'utilisateurs
- */
- UserSearchResultDTO getAllUsers(@NotBlank String realmName, int page, int pageSize);
-
- /**
- * Vérifie si un username existe déjà
- * @param username username à vérifier
- * @param realmName nom du realm
- * @return true si existe
- */
- boolean usernameExists(@NotBlank String username, @NotBlank String realmName);
-
- /**
- * Vérifie si un email existe déjà
- * @param email email à vérifier
- * @param realmName nom du realm
- * @return true si existe
- */
- boolean emailExists(@NotBlank String email, @NotBlank String realmName);
-
- /**
- * Exporte les utilisateurs au format CSV
- * @param criteria critères de recherche
- * @return contenu CSV
- */
- String exportUsersToCSV(@NotNull UserSearchCriteriaDTO criteria);
-
- /**
- * Importe des utilisateurs depuis un CSV avec rapport détaillé
- * @param csvContent contenu CSV
- * @param realmName nom du realm
- * @return résultat détaillé de l'import (succès, erreurs)
- */
- dev.lions.user.manager.dto.importexport.ImportResultDTO importUsersFromCSV(@NotBlank String csvContent, @NotBlank String realmName);
-}
+package dev.lions.user.manager.service;
+
+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.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Service de gestion des utilisateurs Keycloak
+ * Utilise uniquement l'API Admin Keycloak (AUCUN accès direct à la DB)
+ */
+public interface UserService {
+
+ /**
+ * Recherche des utilisateurs selon des critères
+ * @param criteria critères de recherche
+ * @return résultat paginé
+ */
+ UserSearchResultDTO searchUsers(@Valid @NotNull UserSearchCriteriaDTO criteria);
+
+ /**
+ * Récupère un utilisateur par son ID
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return utilisateur ou Optional vide
+ */
+ Optional getUserById(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Récupère un utilisateur par son username
+ * @param username username
+ * @param realmName nom du realm
+ * @return utilisateur ou Optional vide
+ */
+ Optional getUserByUsername(@NotBlank String username, @NotBlank String realmName);
+
+ /**
+ * Récupère un utilisateur par son email
+ * @param email email
+ * @param realmName nom du realm
+ * @return utilisateur ou Optional vide
+ */
+ Optional getUserByEmail(@NotBlank String email, @NotBlank String realmName);
+
+ /**
+ * Crée un nouvel utilisateur
+ * @param user données de l'utilisateur
+ * @param realmName nom du realm
+ * @return utilisateur créé avec son ID
+ */
+ UserDTO createUser(@Valid @NotNull UserDTO user, @NotBlank String realmName);
+
+ /**
+ * Met à jour un utilisateur existant
+ * @param userId ID de l'utilisateur
+ * @param user données modifiées
+ * @param realmName nom du realm
+ * @return utilisateur mis à jour
+ */
+ UserDTO updateUser(@NotBlank String userId, @Valid @NotNull UserDTO user, @NotBlank String realmName);
+
+ /**
+ * Supprime un utilisateur (soft ou hard delete selon configuration)
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @param hardDelete true pour suppression définitive, false pour soft delete
+ */
+ void deleteUser(@NotBlank String userId, @NotBlank String realmName, boolean hardDelete);
+
+ /**
+ * Active un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ */
+ void activateUser(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Désactive un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @param raison raison de la désactivation
+ */
+ void deactivateUser(@NotBlank String userId, @NotBlank String realmName, String raison);
+
+ /**
+ * Suspend un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @param raison raison de la suspension
+ * @param duree durée de la suspension en jours (0 = indéfinie)
+ */
+ void suspendUser(@NotBlank String userId, @NotBlank String realmName, String raison, int duree);
+
+ /**
+ * Déverrouille un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ */
+ void unlockUser(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Réinitialise le mot de passe d'un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @param temporaryPassword mot de passe temporaire
+ * @param temporary true si le mot de passe doit être changé à la prochaine connexion
+ */
+ void resetPassword(@NotBlank String userId, @NotBlank String realmName,
+ @NotBlank String temporaryPassword, boolean temporary);
+
+ /**
+ * Envoie un email de vérification
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ */
+ void sendVerificationEmail(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Force la déconnexion de toutes les sessions d'un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return nombre de sessions révoquées
+ */
+ int logoutAllSessions(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Récupère les sessions actives d'un utilisateur
+ * @param userId ID de l'utilisateur
+ * @param realmName nom du realm
+ * @return liste des informations de session
+ */
+ List getActiveSessions(@NotBlank String userId, @NotBlank String realmName);
+
+ /**
+ * Compte le nombre d'utilisateurs selon des critères
+ * @param criteria critères de recherche
+ * @return nombre d'utilisateurs
+ */
+ long countUsers(@NotNull UserSearchCriteriaDTO criteria);
+
+ /**
+ * Récupère tous les utilisateurs d'un realm (avec pagination)
+ * @param realmName nom du realm
+ * @param page numéro de page
+ * @param pageSize taille de la page
+ * @return liste paginée d'utilisateurs
+ */
+ UserSearchResultDTO getAllUsers(@NotBlank String realmName, int page, int pageSize);
+
+ /**
+ * Vérifie si un username existe déjà
+ * @param username username à vérifier
+ * @param realmName nom du realm
+ * @return true si existe
+ */
+ boolean usernameExists(@NotBlank String username, @NotBlank String realmName);
+
+ /**
+ * Vérifie si un email existe déjà
+ * @param email email à vérifier
+ * @param realmName nom du realm
+ * @return true si existe
+ */
+ boolean emailExists(@NotBlank String email, @NotBlank String realmName);
+
+ /**
+ * Exporte les utilisateurs au format CSV
+ * @param criteria critères de recherche
+ * @return contenu CSV
+ */
+ String exportUsersToCSV(@NotNull UserSearchCriteriaDTO criteria);
+
+ /**
+ * Importe des utilisateurs depuis un CSV avec rapport détaillé
+ * @param csvContent contenu CSV
+ * @param realmName nom du realm
+ * @return résultat détaillé de l'import (succès, erreurs)
+ */
+ dev.lions.user.manager.dto.importexport.ImportResultDTO importUsersFromCSV(@NotBlank String csvContent, @NotBlank String realmName);
+}
diff --git a/src/main/java/dev/lions/user/manager/validation/ValidationConstants.java b/src/main/java/dev/lions/user/manager/validation/ValidationConstants.java
index 54b007d..41d9725 100644
--- a/src/main/java/dev/lions/user/manager/validation/ValidationConstants.java
+++ b/src/main/java/dev/lions/user/manager/validation/ValidationConstants.java
@@ -1,72 +1,72 @@
-package dev.lions.user.manager.validation;
-
-/**
- * Constantes de validation pour les DTOs
- * Centralise les règles de validation communes
- */
-public final class ValidationConstants {
-
- private ValidationConstants() {
- // Classe utilitaire, pas d'instanciation
- }
-
- // Username
- public static final int USERNAME_MIN_LENGTH = 3;
- public static final int USERNAME_MAX_LENGTH = 100;
- public static final String USERNAME_PATTERN = "^[a-zA-Z0-9._-]+$";
- public static final String USERNAME_PATTERN_MESSAGE = "Le nom d'utilisateur ne peut contenir que des lettres, chiffres, points, tirets et underscores";
-
- // Email
- public static final String EMAIL_PATTERN = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
- public static final String EMAIL_PATTERN_MESSAGE = "Format d'email invalide";
-
- // Nom et Prénom
- public static final int NAME_MIN_LENGTH = 2;
- public static final int NAME_MAX_LENGTH = 100;
- public static final String NAME_PATTERN = "^[a-zA-ZÀ-ÿ\\s'-]+$";
- public static final String NAME_PATTERN_MESSAGE = "Le nom ne peut contenir que des lettres, espaces, apostrophes et tirets";
-
- // Téléphone
- public static final String PHONE_PATTERN = "^\\+?[0-9\\s.-]{8,20}$";
- public static final String PHONE_PATTERN_MESSAGE = "Format de téléphone invalide";
-
- // Mot de passe
- public static final int PASSWORD_MIN_LENGTH = 8;
- public static final int PASSWORD_MAX_LENGTH = 100;
- public static final String PASSWORD_PATTERN = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
- public static final String PASSWORD_PATTERN_MESSAGE = "Le mot de passe doit contenir au moins 8 caractères, une majuscule, une minuscule, un chiffre et un caractère spécial";
-
- // Role
- public static final int ROLE_NAME_MIN_LENGTH = 2;
- public static final int ROLE_NAME_MAX_LENGTH = 100;
- public static final String ROLE_NAME_PATTERN = "^[a-zA-Z0-9_-]+$";
- public static final String ROLE_NAME_PATTERN_MESSAGE = "Le nom du rôle ne peut contenir que des lettres, chiffres, underscores et tirets";
-
- // Realm
- public static final String REALM_NAME_PATTERN = "^[a-zA-Z0-9_-]+$";
- public static final String REALM_NAME_PATTERN_MESSAGE = "Le nom du realm ne peut contenir que des lettres, chiffres, underscores et tirets";
-
- // UUID
- public static final String UUID_PATTERN = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
- public static final String UUID_PATTERN_MESSAGE = "Format UUID invalide";
-
- // Messages d'erreur génériques
- public static final String REQUIRED_FIELD = "Ce champ est obligatoire";
- public static final String INVALID_FORMAT = "Format invalide";
- public static final String TOO_SHORT = "Valeur trop courte";
- public static final String TOO_LONG = "Valeur trop longue";
-
- // Pagination
- public static final int DEFAULT_PAGE_SIZE = 20;
- public static final int MAX_PAGE_SIZE = 100;
- public static final int MIN_PAGE_SIZE = 1;
-
- // Audit
- public static final int MAX_DESCRIPTION_LENGTH = 500;
- public static final int MAX_COMMENT_LENGTH = 1000;
- public static final int MAX_ERROR_MESSAGE_LENGTH = 2000;
-
- // IP Address
- public static final String IP_ADDRESS_PATTERN = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
- public static final String IP_ADDRESS_PATTERN_MESSAGE = "Format d'adresse IP invalide";
-}
+package dev.lions.user.manager.validation;
+
+/**
+ * Constantes de validation pour les DTOs
+ * Centralise les règles de validation communes
+ */
+public final class ValidationConstants {
+
+ private ValidationConstants() {
+ // Classe utilitaire, pas d'instanciation
+ }
+
+ // Username
+ public static final int USERNAME_MIN_LENGTH = 3;
+ public static final int USERNAME_MAX_LENGTH = 100;
+ public static final String USERNAME_PATTERN = "^[a-zA-Z0-9._-]+$";
+ public static final String USERNAME_PATTERN_MESSAGE = "Le nom d'utilisateur ne peut contenir que des lettres, chiffres, points, tirets et underscores";
+
+ // Email
+ public static final String EMAIL_PATTERN = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
+ public static final String EMAIL_PATTERN_MESSAGE = "Format d'email invalide";
+
+ // Nom et Prénom
+ public static final int NAME_MIN_LENGTH = 2;
+ public static final int NAME_MAX_LENGTH = 100;
+ public static final String NAME_PATTERN = "^[a-zA-ZÀ-ÿ\\s'-]+$";
+ public static final String NAME_PATTERN_MESSAGE = "Le nom ne peut contenir que des lettres, espaces, apostrophes et tirets";
+
+ // Téléphone
+ public static final String PHONE_PATTERN = "^\\+?[0-9\\s.-]{8,20}$";
+ public static final String PHONE_PATTERN_MESSAGE = "Format de téléphone invalide";
+
+ // Mot de passe
+ public static final int PASSWORD_MIN_LENGTH = 8;
+ public static final int PASSWORD_MAX_LENGTH = 100;
+ public static final String PASSWORD_PATTERN = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
+ public static final String PASSWORD_PATTERN_MESSAGE = "Le mot de passe doit contenir au moins 8 caractères, une majuscule, une minuscule, un chiffre et un caractère spécial";
+
+ // Role
+ public static final int ROLE_NAME_MIN_LENGTH = 2;
+ public static final int ROLE_NAME_MAX_LENGTH = 100;
+ public static final String ROLE_NAME_PATTERN = "^[a-zA-Z0-9_-]+$";
+ public static final String ROLE_NAME_PATTERN_MESSAGE = "Le nom du rôle ne peut contenir que des lettres, chiffres, underscores et tirets";
+
+ // Realm
+ public static final String REALM_NAME_PATTERN = "^[a-zA-Z0-9_-]+$";
+ public static final String REALM_NAME_PATTERN_MESSAGE = "Le nom du realm ne peut contenir que des lettres, chiffres, underscores et tirets";
+
+ // UUID
+ public static final String UUID_PATTERN = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
+ public static final String UUID_PATTERN_MESSAGE = "Format UUID invalide";
+
+ // Messages d'erreur génériques
+ public static final String REQUIRED_FIELD = "Ce champ est obligatoire";
+ public static final String INVALID_FORMAT = "Format invalide";
+ public static final String TOO_SHORT = "Valeur trop courte";
+ public static final String TOO_LONG = "Valeur trop longue";
+
+ // Pagination
+ public static final int DEFAULT_PAGE_SIZE = 20;
+ public static final int MAX_PAGE_SIZE = 100;
+ public static final int MIN_PAGE_SIZE = 1;
+
+ // Audit
+ public static final int MAX_DESCRIPTION_LENGTH = 500;
+ public static final int MAX_COMMENT_LENGTH = 1000;
+ public static final int MAX_ERROR_MESSAGE_LENGTH = 2000;
+
+ // IP Address
+ public static final String IP_ADDRESS_PATTERN = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
+ public static final String IP_ADDRESS_PATTERN_MESSAGE = "Format d'adresse IP invalide";
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/audit/AuditLogDTOTest.java b/src/test/java/dev/lions/user/manager/dto/audit/AuditLogDTOTest.java
index ee4f990..fd98377 100644
--- a/src/test/java/dev/lions/user/manager/dto/audit/AuditLogDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/audit/AuditLogDTOTest.java
@@ -1,119 +1,119 @@
-package dev.lions.user.manager.dto.audit;
-
-import dev.lions.user.manager.enums.audit.TypeActionAudit;
-import org.junit.jupiter.api.Test;
-
-import java.time.LocalDateTime;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour AuditLogDTO
- */
-class AuditLogDTOTest {
-
- @Test
- void testBuilder() {
- LocalDateTime now = LocalDateTime.now();
- AuditLogDTO log = AuditLogDTO.builder()
- .id("log-123")
- .typeAction(TypeActionAudit.USER_CREATE)
- .acteurUsername("admin")
- .acteurUserId("admin-123")
- .ressourceType("USER")
- .ressourceId("user-123")
- .ressourceName("testuser")
- .realmName("test-realm")
- .success(true)
- .description("User created")
- .dateAction(now)
- .ipAddress("192.168.1.1")
- .build();
-
- assertNotNull(log);
- assertEquals("log-123", log.getId());
- assertEquals(TypeActionAudit.USER_CREATE, log.getTypeAction());
- assertEquals("admin", log.getActeurUsername());
- assertEquals("admin-123", log.getActeurUserId());
- assertEquals("USER", log.getRessourceType());
- assertEquals("user-123", log.getRessourceId());
- assertEquals("testuser", log.getRessourceName());
- assertEquals("test-realm", log.getRealmName());
- assertTrue(log.isSuccessful());
- assertEquals("User created", log.getDescription());
- assertEquals(now, log.getDateAction());
- assertEquals("192.168.1.1", log.getIpAddress());
- }
-
- @Test
- void testNoArgsConstructor() {
- AuditLogDTO log = new AuditLogDTO();
-
- assertNotNull(log);
- assertNull(log.getId());
- assertNull(log.getTypeAction());
- assertNull(log.getActeurUsername());
- }
-
- @Test
- void testSettersAndGetters() {
- AuditLogDTO log = new AuditLogDTO();
- LocalDateTime now = LocalDateTime.now();
-
- log.setId("log-456");
- log.setTypeAction(TypeActionAudit.USER_UPDATE);
- log.setActeurUsername("user1");
- log.setActeurUserId("user1-123");
- log.setRessourceType("USER");
- log.setRessourceId("user-456");
- log.setRessourceName("user2");
- log.setRealmName("realm2");
- log.setSuccess(false);
- log.setDescription("Update failed");
- log.setDateAction(now);
- log.setIpAddress("10.0.0.1");
-
- assertEquals("log-456", log.getId());
- assertEquals(TypeActionAudit.USER_UPDATE, log.getTypeAction());
- assertEquals("user1", log.getActeurUsername());
- assertEquals("user1-123", log.getActeurUserId());
- assertEquals("USER", log.getRessourceType());
- assertEquals("user-456", log.getRessourceId());
- assertEquals("user2", log.getRessourceName());
- assertEquals("realm2", log.getRealmName());
- assertFalse(log.isSuccessful());
- assertEquals("Update failed", log.getDescription());
- assertEquals(now, log.getDateAction());
- assertEquals("10.0.0.1", log.getIpAddress());
- }
-
- @Test
- void testEqualsAndHashCode() {
- LocalDateTime now = LocalDateTime.now();
- AuditLogDTO log1 = AuditLogDTO.builder()
- .id("log-123")
- .typeAction(TypeActionAudit.USER_CREATE)
- .dateAction(now)
- .build();
-
- AuditLogDTO log2 = AuditLogDTO.builder()
- .id("log-123")
- .typeAction(TypeActionAudit.USER_CREATE)
- .dateAction(now)
- .build();
-
- assertEquals(log1, log2);
- assertEquals(log1.hashCode(), log2.hashCode());
- }
-
- @Test
- void testToString() {
- AuditLogDTO log = AuditLogDTO.builder()
- .id("log-123")
- .typeAction(TypeActionAudit.USER_CREATE)
- .build();
-
- String toString = log.toString();
- assertNotNull(toString);
- }
-}
+package dev.lions.user.manager.dto.audit;
+
+import dev.lions.user.manager.enums.audit.TypeActionAudit;
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour AuditLogDTO
+ */
+class AuditLogDTOTest {
+
+ @Test
+ void testBuilder() {
+ LocalDateTime now = LocalDateTime.now();
+ AuditLogDTO log = AuditLogDTO.builder()
+ .id("log-123")
+ .typeAction(TypeActionAudit.USER_CREATE)
+ .acteurUsername("admin")
+ .acteurUserId("admin-123")
+ .ressourceType("USER")
+ .ressourceId("user-123")
+ .ressourceName("testuser")
+ .realmName("test-realm")
+ .success(true)
+ .description("User created")
+ .dateAction(now)
+ .ipAddress("192.168.1.1")
+ .build();
+
+ assertNotNull(log);
+ assertEquals("log-123", log.getId());
+ assertEquals(TypeActionAudit.USER_CREATE, log.getTypeAction());
+ assertEquals("admin", log.getActeurUsername());
+ assertEquals("admin-123", log.getActeurUserId());
+ assertEquals("USER", log.getRessourceType());
+ assertEquals("user-123", log.getRessourceId());
+ assertEquals("testuser", log.getRessourceName());
+ assertEquals("test-realm", log.getRealmName());
+ assertTrue(log.isSuccessful());
+ assertEquals("User created", log.getDescription());
+ assertEquals(now, log.getDateAction());
+ assertEquals("192.168.1.1", log.getIpAddress());
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ AuditLogDTO log = new AuditLogDTO();
+
+ assertNotNull(log);
+ assertNull(log.getId());
+ assertNull(log.getTypeAction());
+ assertNull(log.getActeurUsername());
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ AuditLogDTO log = new AuditLogDTO();
+ LocalDateTime now = LocalDateTime.now();
+
+ log.setId("log-456");
+ log.setTypeAction(TypeActionAudit.USER_UPDATE);
+ log.setActeurUsername("user1");
+ log.setActeurUserId("user1-123");
+ log.setRessourceType("USER");
+ log.setRessourceId("user-456");
+ log.setRessourceName("user2");
+ log.setRealmName("realm2");
+ log.setSuccess(false);
+ log.setDescription("Update failed");
+ log.setDateAction(now);
+ log.setIpAddress("10.0.0.1");
+
+ assertEquals("log-456", log.getId());
+ assertEquals(TypeActionAudit.USER_UPDATE, log.getTypeAction());
+ assertEquals("user1", log.getActeurUsername());
+ assertEquals("user1-123", log.getActeurUserId());
+ assertEquals("USER", log.getRessourceType());
+ assertEquals("user-456", log.getRessourceId());
+ assertEquals("user2", log.getRessourceName());
+ assertEquals("realm2", log.getRealmName());
+ assertFalse(log.isSuccessful());
+ assertEquals("Update failed", log.getDescription());
+ assertEquals(now, log.getDateAction());
+ assertEquals("10.0.0.1", log.getIpAddress());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ LocalDateTime now = LocalDateTime.now();
+ AuditLogDTO log1 = AuditLogDTO.builder()
+ .id("log-123")
+ .typeAction(TypeActionAudit.USER_CREATE)
+ .dateAction(now)
+ .build();
+
+ AuditLogDTO log2 = AuditLogDTO.builder()
+ .id("log-123")
+ .typeAction(TypeActionAudit.USER_CREATE)
+ .dateAction(now)
+ .build();
+
+ assertEquals(log1, log2);
+ assertEquals(log1.hashCode(), log2.hashCode());
+ }
+
+ @Test
+ void testToString() {
+ AuditLogDTO log = AuditLogDTO.builder()
+ .id("log-123")
+ .typeAction(TypeActionAudit.USER_CREATE)
+ .build();
+
+ String toString = log.toString();
+ assertNotNull(toString);
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/base/BaseDTOTest.java b/src/test/java/dev/lions/user/manager/dto/base/BaseDTOTest.java
index c8c1997..9a1a479 100644
--- a/src/test/java/dev/lions/user/manager/dto/base/BaseDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/base/BaseDTOTest.java
@@ -1,134 +1,134 @@
-package dev.lions.user.manager.dto.base;
-
-import org.junit.jupiter.api.Test;
-
-import java.time.LocalDateTime;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class BaseDTOTest {
-
- // Concrete implementation for testing abstract class
- static class TestDTO extends BaseDTO {
- private static final long serialVersionUID = 1L;
- }
-
- @Test
- void testSettersAndGetters() {
- TestDTO dto = new TestDTO();
- LocalDateTime now = LocalDateTime.now();
-
- dto.setId("uuid-123");
- dto.setDateCreation(now);
- dto.setDateModification(now);
- dto.setCreeParUsername("admin");
- dto.setModifieParUsername("superadmin");
- dto.setVersion(1L);
-
- assertEquals("uuid-123", dto.getId());
- assertEquals(now, dto.getDateCreation());
- assertEquals(now, dto.getDateModification());
- assertEquals("admin", dto.getCreeParUsername());
- assertEquals("superadmin", dto.getModifieParUsername());
- assertEquals(1L, dto.getVersion());
- }
-
- @Test
- void testEqualsAndHashCode() {
- TestDTO dto1 = new TestDTO();
- dto1.setId("uuid-123");
- dto1.setVersion(1L);
-
- TestDTO dto2 = new TestDTO();
- dto2.setId("uuid-123");
- dto2.setVersion(1L);
-
- TestDTO dto3 = new TestDTO();
- dto3.setId("uuid-456");
- dto3.setVersion(2L);
-
- assertEquals(dto1, dto2);
- assertEquals(dto1.hashCode(), dto2.hashCode());
- assertNotEquals(dto1, dto3);
- }
-
- @Test
- void testToString() {
- TestDTO dto = new TestDTO();
- dto.setId("uuid-123");
- dto.setCreeParUsername("admin");
-
- String str = dto.toString();
- assertNotNull(str);
- assertTrue(str.contains("uuid-123"));
- assertTrue(str.contains("admin"));
- }
-
- @Test
- void testNoArgsConstructor() {
- TestDTO dto = new TestDTO();
- assertNull(dto.getId());
- assertNull(dto.getDateCreation());
- assertNull(dto.getDateModification());
- assertNull(dto.getCreeParUsername());
- assertNull(dto.getModifieParUsername());
- assertNull(dto.getVersion());
- }
-
- @Test
- void testAllFields() {
- LocalDateTime creationTime = LocalDateTime.of(2025, 1, 15, 10, 30);
- LocalDateTime modificationTime = LocalDateTime.of(2025, 1, 15, 14, 20);
-
- TestDTO dto = new TestDTO();
- dto.setId("f47ac10b-58cc-4372-a567-0e02b2c3d479");
- dto.setDateCreation(creationTime);
- dto.setDateModification(modificationTime);
- dto.setCreeParUsername("admin@lions.dev");
- dto.setModifieParUsername("superadmin@lions.dev");
- dto.setVersion(5L);
-
- assertEquals("f47ac10b-58cc-4372-a567-0e02b2c3d479", dto.getId());
- assertEquals(creationTime, dto.getDateCreation());
- assertEquals(modificationTime, dto.getDateModification());
- assertEquals("admin@lions.dev", dto.getCreeParUsername());
- assertEquals("superadmin@lions.dev", dto.getModifieParUsername());
- assertEquals(5L, dto.getVersion());
- }
-
- @Test
- void testEqualsWithNull() {
- TestDTO dto = new TestDTO();
- dto.setId("uuid-123");
-
- assertNotEquals(null, dto);
- }
-
- @Test
- void testEqualsWithDifferentClass() {
- TestDTO dto = new TestDTO();
- dto.setId("uuid-123");
-
- assertNotEquals("string", dto);
- }
-
- @Test
- void testEqualsSameObject() {
- TestDTO dto = new TestDTO();
- dto.setId("uuid-123");
-
- assertEquals(dto, dto);
- }
-
- @Test
- void testHashCodeConsistency() {
- TestDTO dto = new TestDTO();
- dto.setId("uuid-123");
- dto.setVersion(1L);
-
- int hash1 = dto.hashCode();
- int hash2 = dto.hashCode();
-
- assertEquals(hash1, hash2);
- }
-}
+package dev.lions.user.manager.dto.base;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class BaseDTOTest {
+
+ // Concrete implementation for testing abstract class
+ static class TestDTO extends BaseDTO {
+ private static final long serialVersionUID = 1L;
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ TestDTO dto = new TestDTO();
+ LocalDateTime now = LocalDateTime.now();
+
+ dto.setId("uuid-123");
+ dto.setDateCreation(now);
+ dto.setDateModification(now);
+ dto.setCreeParUsername("admin");
+ dto.setModifieParUsername("superadmin");
+ dto.setVersion(1L);
+
+ assertEquals("uuid-123", dto.getId());
+ assertEquals(now, dto.getDateCreation());
+ assertEquals(now, dto.getDateModification());
+ assertEquals("admin", dto.getCreeParUsername());
+ assertEquals("superadmin", dto.getModifieParUsername());
+ assertEquals(1L, dto.getVersion());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ TestDTO dto1 = new TestDTO();
+ dto1.setId("uuid-123");
+ dto1.setVersion(1L);
+
+ TestDTO dto2 = new TestDTO();
+ dto2.setId("uuid-123");
+ dto2.setVersion(1L);
+
+ TestDTO dto3 = new TestDTO();
+ dto3.setId("uuid-456");
+ dto3.setVersion(2L);
+
+ assertEquals(dto1, dto2);
+ assertEquals(dto1.hashCode(), dto2.hashCode());
+ assertNotEquals(dto1, dto3);
+ }
+
+ @Test
+ void testToString() {
+ TestDTO dto = new TestDTO();
+ dto.setId("uuid-123");
+ dto.setCreeParUsername("admin");
+
+ String str = dto.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("uuid-123"));
+ assertTrue(str.contains("admin"));
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ TestDTO dto = new TestDTO();
+ assertNull(dto.getId());
+ assertNull(dto.getDateCreation());
+ assertNull(dto.getDateModification());
+ assertNull(dto.getCreeParUsername());
+ assertNull(dto.getModifieParUsername());
+ assertNull(dto.getVersion());
+ }
+
+ @Test
+ void testAllFields() {
+ LocalDateTime creationTime = LocalDateTime.of(2025, 1, 15, 10, 30);
+ LocalDateTime modificationTime = LocalDateTime.of(2025, 1, 15, 14, 20);
+
+ TestDTO dto = new TestDTO();
+ dto.setId("f47ac10b-58cc-4372-a567-0e02b2c3d479");
+ dto.setDateCreation(creationTime);
+ dto.setDateModification(modificationTime);
+ dto.setCreeParUsername("admin@lions.dev");
+ dto.setModifieParUsername("superadmin@lions.dev");
+ dto.setVersion(5L);
+
+ assertEquals("f47ac10b-58cc-4372-a567-0e02b2c3d479", dto.getId());
+ assertEquals(creationTime, dto.getDateCreation());
+ assertEquals(modificationTime, dto.getDateModification());
+ assertEquals("admin@lions.dev", dto.getCreeParUsername());
+ assertEquals("superadmin@lions.dev", dto.getModifieParUsername());
+ assertEquals(5L, dto.getVersion());
+ }
+
+ @Test
+ void testEqualsWithNull() {
+ TestDTO dto = new TestDTO();
+ dto.setId("uuid-123");
+
+ assertNotEquals(null, dto);
+ }
+
+ @Test
+ void testEqualsWithDifferentClass() {
+ TestDTO dto = new TestDTO();
+ dto.setId("uuid-123");
+
+ assertNotEquals("string", dto);
+ }
+
+ @Test
+ void testEqualsSameObject() {
+ TestDTO dto = new TestDTO();
+ dto.setId("uuid-123");
+
+ assertEquals(dto, dto);
+ }
+
+ @Test
+ void testHashCodeConsistency() {
+ TestDTO dto = new TestDTO();
+ dto.setId("uuid-123");
+ dto.setVersion(1L);
+
+ int hash1 = dto.hashCode();
+ int hash2 = dto.hashCode();
+
+ assertEquals(hash1, hash2);
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTOTest.java b/src/test/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTOTest.java
index d085f72..accc119 100644
--- a/src/test/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/realm/RealmAssignmentDTOTest.java
@@ -1,184 +1,184 @@
-package dev.lions.user.manager.dto.realm;
-
-import org.junit.jupiter.api.Test;
-
-import java.time.LocalDateTime;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour RealmAssignmentDTO
- */
-class RealmAssignmentDTOTest {
-
- @Test
- void testBuilder() {
- LocalDateTime now = LocalDateTime.now();
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .id("assignment-1")
- .userId("user-1")
- .username("testuser")
- .email("test@example.com")
- .realmName("realm1")
- .isSuperAdmin(false)
- .active(true)
- .temporaire(false)
- .assignedAt(now)
- .assignedBy("admin")
- .raison("Test assignment")
- .commentaires("Test comments")
- .dateCreation(now)
- .dateModification(now)
- .dateExpiration(now.plusDays(30))
- .build();
-
- assertEquals("assignment-1", dto.getId());
- assertEquals("user-1", dto.getUserId());
- assertEquals("testuser", dto.getUsername());
- assertEquals("test@example.com", dto.getEmail());
- assertEquals("realm1", dto.getRealmName());
- assertFalse(dto.isSuperAdmin());
- assertTrue(dto.isActive());
- assertFalse(dto.getTemporaire());
- assertEquals(now, dto.getAssignedAt());
- assertEquals("admin", dto.getAssignedBy());
- assertEquals("Test assignment", dto.getRaison());
- assertEquals("Test comments", dto.getCommentaires());
- }
-
- @Test
- void testNoArgsConstructor() {
- RealmAssignmentDTO dto = new RealmAssignmentDTO();
- assertNotNull(dto);
- }
-
- @Test
- void testSettersAndGetters() {
- RealmAssignmentDTO dto = new RealmAssignmentDTO();
- LocalDateTime now = LocalDateTime.now();
-
- dto.setId("assignment-1");
- dto.setUserId("user-1");
- dto.setUsername("testuser");
- dto.setEmail("test@example.com");
- dto.setRealmName("realm1");
- dto.setIsSuperAdmin(true);
- dto.setActive(true);
- dto.setTemporaire(false);
- dto.setAssignedAt(now);
- dto.setAssignedBy("admin");
- dto.setRaison("Test");
- dto.setCommentaires("Comments");
- dto.setDateCreation(now);
- dto.setDateModification(now);
- dto.setDateExpiration(now.plusDays(30));
-
- assertEquals("assignment-1", dto.getId());
- assertEquals("user-1", dto.getUserId());
- assertEquals("testuser", dto.getUsername());
- assertEquals("test@example.com", dto.getEmail());
- assertEquals("realm1", dto.getRealmName());
- assertTrue(dto.isSuperAdmin());
- assertTrue(dto.isActive());
- assertFalse(dto.getTemporaire());
- assertEquals(now, dto.getAssignedAt());
- assertEquals("admin", dto.getAssignedBy());
- }
-
- @Test
- void testIsExpired_NotExpired() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .temporaire(true) // Doit être temporaire pour que isExpired() fonctionne
- .dateExpiration(LocalDateTime.now().plusDays(1))
- .build();
-
- assertFalse(dto.isExpired());
- }
-
- @Test
- void testIsExpired_Expired() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .temporaire(true) // Doit être temporaire pour que isExpired() fonctionne
- .dateExpiration(LocalDateTime.now().minusDays(1))
- .build();
-
- assertTrue(dto.isExpired());
- }
-
- @Test
- void testIsExpired_NoExpiration() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .temporaire(true)
- .dateExpiration(null)
- .build();
-
- assertFalse(dto.isExpired());
- }
-
- @Test
- void testIsExpired_NotTemporary() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .temporaire(false) // Si pas temporaire, isExpired() retourne false
- .dateExpiration(LocalDateTime.now().minusDays(1))
- .build();
-
- assertFalse(dto.isExpired());
- }
-
- @Test
- void testIsTemporaire() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .temporaire(true)
- .build();
-
- assertTrue(dto.isTemporaire());
- }
-
- @Test
- void testIsActive() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .active(true)
- .build();
-
- assertTrue(dto.isActive());
- }
-
- @Test
- void testIsSuperAdmin() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .isSuperAdmin(true)
- .build();
-
- assertTrue(dto.isSuperAdmin());
- }
-
- @Test
- void testGetSummary() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .realmName("test-realm")
- .username("testuser")
- .temporaire(true)
- .build();
-
- String summary = dto.getSummary();
- assertNotNull(summary);
- assertTrue(summary.contains("test-realm"));
- assertTrue(summary.contains("testuser"));
- assertTrue(summary.contains("temporaire"));
- }
-
- @Test
- void testGetSummary_WithUserId() {
- RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
- .realmName("test-realm")
- .userId("user-123")
- .temporaire(false)
- .build();
-
- String summary = dto.getSummary();
- assertNotNull(summary);
- assertTrue(summary.contains("test-realm"));
- assertTrue(summary.contains("user-123"));
- }
-}
-
+package dev.lions.user.manager.dto.realm;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour RealmAssignmentDTO
+ */
+class RealmAssignmentDTOTest {
+
+ @Test
+ void testBuilder() {
+ LocalDateTime now = LocalDateTime.now();
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .id("assignment-1")
+ .userId("user-1")
+ .username("testuser")
+ .email("test@example.com")
+ .realmName("realm1")
+ .isSuperAdmin(false)
+ .active(true)
+ .temporaire(false)
+ .assignedAt(now)
+ .assignedBy("admin")
+ .raison("Test assignment")
+ .commentaires("Test comments")
+ .dateCreation(now)
+ .dateModification(now)
+ .dateExpiration(now.plusDays(30))
+ .build();
+
+ assertEquals("assignment-1", dto.getId());
+ assertEquals("user-1", dto.getUserId());
+ assertEquals("testuser", dto.getUsername());
+ assertEquals("test@example.com", dto.getEmail());
+ assertEquals("realm1", dto.getRealmName());
+ assertFalse(dto.isSuperAdmin());
+ assertTrue(dto.isActive());
+ assertFalse(dto.getTemporaire());
+ assertEquals(now, dto.getAssignedAt());
+ assertEquals("admin", dto.getAssignedBy());
+ assertEquals("Test assignment", dto.getRaison());
+ assertEquals("Test comments", dto.getCommentaires());
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ RealmAssignmentDTO dto = new RealmAssignmentDTO();
+ assertNotNull(dto);
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ RealmAssignmentDTO dto = new RealmAssignmentDTO();
+ LocalDateTime now = LocalDateTime.now();
+
+ dto.setId("assignment-1");
+ dto.setUserId("user-1");
+ dto.setUsername("testuser");
+ dto.setEmail("test@example.com");
+ dto.setRealmName("realm1");
+ dto.setIsSuperAdmin(true);
+ dto.setActive(true);
+ dto.setTemporaire(false);
+ dto.setAssignedAt(now);
+ dto.setAssignedBy("admin");
+ dto.setRaison("Test");
+ dto.setCommentaires("Comments");
+ dto.setDateCreation(now);
+ dto.setDateModification(now);
+ dto.setDateExpiration(now.plusDays(30));
+
+ assertEquals("assignment-1", dto.getId());
+ assertEquals("user-1", dto.getUserId());
+ assertEquals("testuser", dto.getUsername());
+ assertEquals("test@example.com", dto.getEmail());
+ assertEquals("realm1", dto.getRealmName());
+ assertTrue(dto.isSuperAdmin());
+ assertTrue(dto.isActive());
+ assertFalse(dto.getTemporaire());
+ assertEquals(now, dto.getAssignedAt());
+ assertEquals("admin", dto.getAssignedBy());
+ }
+
+ @Test
+ void testIsExpired_NotExpired() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .temporaire(true) // Doit être temporaire pour que isExpired() fonctionne
+ .dateExpiration(LocalDateTime.now().plusDays(1))
+ .build();
+
+ assertFalse(dto.isExpired());
+ }
+
+ @Test
+ void testIsExpired_Expired() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .temporaire(true) // Doit être temporaire pour que isExpired() fonctionne
+ .dateExpiration(LocalDateTime.now().minusDays(1))
+ .build();
+
+ assertTrue(dto.isExpired());
+ }
+
+ @Test
+ void testIsExpired_NoExpiration() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .temporaire(true)
+ .dateExpiration(null)
+ .build();
+
+ assertFalse(dto.isExpired());
+ }
+
+ @Test
+ void testIsExpired_NotTemporary() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .temporaire(false) // Si pas temporaire, isExpired() retourne false
+ .dateExpiration(LocalDateTime.now().minusDays(1))
+ .build();
+
+ assertFalse(dto.isExpired());
+ }
+
+ @Test
+ void testIsTemporaire() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .temporaire(true)
+ .build();
+
+ assertTrue(dto.isTemporaire());
+ }
+
+ @Test
+ void testIsActive() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .active(true)
+ .build();
+
+ assertTrue(dto.isActive());
+ }
+
+ @Test
+ void testIsSuperAdmin() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .isSuperAdmin(true)
+ .build();
+
+ assertTrue(dto.isSuperAdmin());
+ }
+
+ @Test
+ void testGetSummary() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .realmName("test-realm")
+ .username("testuser")
+ .temporaire(true)
+ .build();
+
+ String summary = dto.getSummary();
+ assertNotNull(summary);
+ assertTrue(summary.contains("test-realm"));
+ assertTrue(summary.contains("testuser"));
+ assertTrue(summary.contains("temporaire"));
+ }
+
+ @Test
+ void testGetSummary_WithUserId() {
+ RealmAssignmentDTO dto = RealmAssignmentDTO.builder()
+ .realmName("test-realm")
+ .userId("user-123")
+ .temporaire(false)
+ .build();
+
+ String summary = dto.getSummary();
+ assertNotNull(summary);
+ assertTrue(summary.contains("test-realm"));
+ assertTrue(summary.contains("user-123"));
+ }
+}
+
diff --git a/src/test/java/dev/lions/user/manager/dto/role/RoleAssignmentDTOTest.java b/src/test/java/dev/lions/user/manager/dto/role/RoleAssignmentDTOTest.java
index b016753..6604f16 100644
--- a/src/test/java/dev/lions/user/manager/dto/role/RoleAssignmentDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/role/RoleAssignmentDTOTest.java
@@ -1,147 +1,147 @@
-package dev.lions.user.manager.dto.role;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour RoleAssignmentDTO
- */
-class RoleAssignmentDTOTest {
-
- @Test
- void testBuilder() {
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .userId("user-123")
- .realmName("test-realm")
- .roleNames(Arrays.asList("admin", "user"))
- .build();
-
- assertNotNull(assignment);
- assertEquals("user-123", assignment.getUserId());
- assertEquals("test-realm", assignment.getRealmName());
- assertEquals(2, assignment.getRoleNames().size());
- assertTrue(assignment.getRoleNames().contains("admin"));
- assertTrue(assignment.getRoleNames().contains("user"));
- }
-
- @Test
- void testNoArgsConstructor() {
- RoleAssignmentDTO assignment = new RoleAssignmentDTO();
-
- assertNotNull(assignment);
- assertNull(assignment.getUserId());
- assertNull(assignment.getRealmName());
- assertNull(assignment.getRoleNames());
- }
-
- @Test
- void testAllArgsConstructor() {
- // Le constructeur AllArgsConstructor nécessite tous les champs
- // On utilise plutôt le builder pour ce test
- List roles = Arrays.asList("admin", "user");
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .userId("user-123")
- .realmName("test-realm")
- .roleNames(roles)
- .build();
-
- assertNotNull(assignment);
- assertEquals("user-123", assignment.getUserId());
- assertEquals("test-realm", assignment.getRealmName());
- assertEquals(2, assignment.getRoleNames().size());
- }
-
- @Test
- void testSettersAndGetters() {
- RoleAssignmentDTO assignment = new RoleAssignmentDTO();
-
- assignment.setUserId("user-456");
- assignment.setRealmName("realm2");
- assignment.setRoleNames(Collections.singletonList("admin"));
-
- assertEquals("user-456", assignment.getUserId());
- assertEquals("realm2", assignment.getRealmName());
- assertEquals(1, assignment.getRoleNames().size());
- assertEquals("admin", assignment.getRoleNames().get(0));
- }
-
- @Test
- void testEqualsAndHashCode() {
- RoleAssignmentDTO assignment1 = RoleAssignmentDTO.builder()
- .userId("user-123")
- .realmName("test-realm")
- .roleNames(Arrays.asList("admin"))
- .typeRole(dev.lions.user.manager.enums.role.TypeRole.REALM_ROLE)
- .build();
-
- RoleAssignmentDTO assignment2 = RoleAssignmentDTO.builder()
- .userId("user-123")
- .realmName("test-realm")
- .roleNames(Arrays.asList("admin"))
- .typeRole(dev.lions.user.manager.enums.role.TypeRole.REALM_ROLE)
- .build();
-
- assertEquals(assignment1, assignment2);
- assertEquals(assignment1.hashCode(), assignment2.hashCode());
- }
-
- @Test
- void testIsValidForClientRole() {
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .typeRole(dev.lions.user.manager.enums.role.TypeRole.CLIENT_ROLE)
- .clientName("test-client")
- .build();
-
- assertTrue(assignment.isValidForClientRole());
- }
-
- @Test
- void testIsValidForRealmRole() {
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .typeRole(dev.lions.user.manager.enums.role.TypeRole.REALM_ROLE)
- .build();
-
- assertTrue(assignment.isValidForRealmRole());
- }
-
- @Test
- void testGetRoleCount() {
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .roleNames(Arrays.asList("admin", "user", "viewer"))
- .build();
-
- assertEquals(3, assignment.getRoleCount());
- }
-
- @Test
- void testGetRoleCount_Empty() {
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .roleNames(Collections.emptyList())
- .build();
-
- assertEquals(0, assignment.getRoleCount());
- }
-
- @Test
- void testGetRoleCount_Null() {
- RoleAssignmentDTO assignment = new RoleAssignmentDTO();
-
- assertEquals(0, assignment.getRoleCount());
- }
-
- @Test
- void testToString() {
- RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
- .userId("user-123")
- .realmName("test-realm")
- .build();
-
- String toString = assignment.toString();
- assertNotNull(toString);
- }
-}
+package dev.lions.user.manager.dto.role;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour RoleAssignmentDTO
+ */
+class RoleAssignmentDTOTest {
+
+ @Test
+ void testBuilder() {
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .userId("user-123")
+ .realmName("test-realm")
+ .roleNames(Arrays.asList("admin", "user"))
+ .build();
+
+ assertNotNull(assignment);
+ assertEquals("user-123", assignment.getUserId());
+ assertEquals("test-realm", assignment.getRealmName());
+ assertEquals(2, assignment.getRoleNames().size());
+ assertTrue(assignment.getRoleNames().contains("admin"));
+ assertTrue(assignment.getRoleNames().contains("user"));
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ RoleAssignmentDTO assignment = new RoleAssignmentDTO();
+
+ assertNotNull(assignment);
+ assertNull(assignment.getUserId());
+ assertNull(assignment.getRealmName());
+ assertNull(assignment.getRoleNames());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ // Le constructeur AllArgsConstructor nécessite tous les champs
+ // On utilise plutôt le builder pour ce test
+ List roles = Arrays.asList("admin", "user");
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .userId("user-123")
+ .realmName("test-realm")
+ .roleNames(roles)
+ .build();
+
+ assertNotNull(assignment);
+ assertEquals("user-123", assignment.getUserId());
+ assertEquals("test-realm", assignment.getRealmName());
+ assertEquals(2, assignment.getRoleNames().size());
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ RoleAssignmentDTO assignment = new RoleAssignmentDTO();
+
+ assignment.setUserId("user-456");
+ assignment.setRealmName("realm2");
+ assignment.setRoleNames(Collections.singletonList("admin"));
+
+ assertEquals("user-456", assignment.getUserId());
+ assertEquals("realm2", assignment.getRealmName());
+ assertEquals(1, assignment.getRoleNames().size());
+ assertEquals("admin", assignment.getRoleNames().get(0));
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ RoleAssignmentDTO assignment1 = RoleAssignmentDTO.builder()
+ .userId("user-123")
+ .realmName("test-realm")
+ .roleNames(Arrays.asList("admin"))
+ .typeRole(dev.lions.user.manager.enums.role.TypeRole.REALM_ROLE)
+ .build();
+
+ RoleAssignmentDTO assignment2 = RoleAssignmentDTO.builder()
+ .userId("user-123")
+ .realmName("test-realm")
+ .roleNames(Arrays.asList("admin"))
+ .typeRole(dev.lions.user.manager.enums.role.TypeRole.REALM_ROLE)
+ .build();
+
+ assertEquals(assignment1, assignment2);
+ assertEquals(assignment1.hashCode(), assignment2.hashCode());
+ }
+
+ @Test
+ void testIsValidForClientRole() {
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .typeRole(dev.lions.user.manager.enums.role.TypeRole.CLIENT_ROLE)
+ .clientName("test-client")
+ .build();
+
+ assertTrue(assignment.isValidForClientRole());
+ }
+
+ @Test
+ void testIsValidForRealmRole() {
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .typeRole(dev.lions.user.manager.enums.role.TypeRole.REALM_ROLE)
+ .build();
+
+ assertTrue(assignment.isValidForRealmRole());
+ }
+
+ @Test
+ void testGetRoleCount() {
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .roleNames(Arrays.asList("admin", "user", "viewer"))
+ .build();
+
+ assertEquals(3, assignment.getRoleCount());
+ }
+
+ @Test
+ void testGetRoleCount_Empty() {
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .roleNames(Collections.emptyList())
+ .build();
+
+ assertEquals(0, assignment.getRoleCount());
+ }
+
+ @Test
+ void testGetRoleCount_Null() {
+ RoleAssignmentDTO assignment = new RoleAssignmentDTO();
+
+ assertEquals(0, assignment.getRoleCount());
+ }
+
+ @Test
+ void testToString() {
+ RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
+ .userId("user-123")
+ .realmName("test-realm")
+ .build();
+
+ String toString = assignment.toString();
+ assertNotNull(toString);
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/role/RoleDTOTest.java b/src/test/java/dev/lions/user/manager/dto/role/RoleDTOTest.java
index 482bcce..177f977 100644
--- a/src/test/java/dev/lions/user/manager/dto/role/RoleDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/role/RoleDTOTest.java
@@ -1,318 +1,318 @@
-package dev.lions.user.manager.dto.role;
-
-import dev.lions.user.manager.enums.role.TypeRole;
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class RoleDTOTest {
-
- @Test
- void testIsRealmRole_true() {
- RoleDTO role = new RoleDTO();
- role.setTypeRole(TypeRole.REALM_ROLE);
- assertTrue(role.isRealmRole());
- assertFalse(role.isClientRole());
- }
-
- @Test
- void testIsRealmRole_false() {
- RoleDTO role = new RoleDTO();
- role.setTypeRole(TypeRole.CLIENT_ROLE);
- assertFalse(role.isRealmRole());
- }
-
- @Test
- void testIsRealmRole_null() {
- RoleDTO role = new RoleDTO();
- role.setTypeRole(null);
- assertFalse(role.isRealmRole());
- }
-
- @Test
- void testIsClientRole_true() {
- RoleDTO role = new RoleDTO();
- role.setTypeRole(TypeRole.CLIENT_ROLE);
- assertTrue(role.isClientRole());
- assertFalse(role.isRealmRole());
- }
-
- @Test
- void testIsClientRole_false() {
- RoleDTO role = new RoleDTO();
- role.setTypeRole(TypeRole.REALM_ROLE);
- assertFalse(role.isClientRole());
- }
-
- @Test
- void testIsClientRole_null() {
- RoleDTO role = new RoleDTO();
- role.setTypeRole(null);
- assertFalse(role.isClientRole());
- }
-
- @Test
- void testIsComposite_withCompositeRoles() {
- RoleDTO role = new RoleDTO();
- role.setComposite(true);
- role.setCompositeRoles(Arrays.asList("role1", "role2"));
- assertTrue(role.isComposite());
- }
-
- @Test
- void testIsComposite_withCompositeRealmRoles() {
- RoleDTO role = new RoleDTO();
- role.setComposite(true);
- role.setCompositeRoles(null);
- role.setCompositeRealmRoles(Collections.singletonList(new RoleDTO.RoleCompositeDTO()));
- assertTrue(role.isComposite());
- }
-
- @Test
- void testIsComposite_withCompositeClientRoles() {
- RoleDTO role = new RoleDTO();
- role.setComposite(true);
- role.setCompositeRoles(null);
- role.setCompositeRealmRoles(null);
- Map> clientRoles = new HashMap<>();
- clientRoles.put("client", Collections.singletonList(new RoleDTO.RoleCompositeDTO()));
- role.setCompositeClientRoles(clientRoles);
- assertTrue(role.isComposite());
- }
-
- @Test
- void testIsComposite_falseWhenCompositeFalse() {
- RoleDTO role = new RoleDTO();
- role.setComposite(false);
- role.setCompositeRoles(Arrays.asList("role1"));
- assertFalse(role.isComposite());
- }
-
- @Test
- void testIsComposite_falseWhenCompositeNull() {
- RoleDTO role = new RoleDTO();
- role.setComposite(null);
- role.setCompositeRoles(Arrays.asList("role1"));
- assertFalse(role.isComposite());
- }
-
- @Test
- void testIsComposite_falseWhenNoRoles() {
- RoleDTO role = new RoleDTO();
- role.setComposite(true);
- role.setCompositeRoles(null);
- role.setCompositeRealmRoles(null);
- role.setCompositeClientRoles(null);
- assertFalse(role.isComposite());
- }
-
- @Test
- void testIsComposite_falseWhenEmptyRoles() {
- RoleDTO role = new RoleDTO();
- role.setComposite(true);
- role.setCompositeRoles(Collections.emptyList());
- role.setCompositeRealmRoles(Collections.emptyList());
- role.setCompositeClientRoles(Collections.emptyMap());
- assertFalse(role.isComposite());
- }
-
- @Test
- void testGetFullName_realmRole() {
- RoleDTO role = new RoleDTO();
- role.setName("admin");
- role.setTypeRole(TypeRole.REALM_ROLE);
- assertEquals("admin", role.getFullName());
- }
-
- @Test
- void testGetFullName_clientRole() {
- RoleDTO role = new RoleDTO();
- role.setName("admin");
- role.setTypeRole(TypeRole.CLIENT_ROLE);
- role.setClientName("app");
- assertEquals("app:admin", role.getFullName());
- }
-
- @Test
- void testGetFullName_clientRoleNullClientName() {
- RoleDTO role = new RoleDTO();
- role.setName("admin");
- role.setTypeRole(TypeRole.CLIENT_ROLE);
- role.setClientName(null);
- assertEquals("admin", role.getFullName());
- }
-
- @Test
- void testGetFullName_nullTypeRole() {
- RoleDTO role = new RoleDTO();
- role.setName("admin");
- role.setTypeRole(null);
- assertEquals("admin", role.getFullName());
- }
-
- @Test
- void testRoleCompositeDTO_builder() {
- RoleDTO.RoleCompositeDTO comp = RoleDTO.RoleCompositeDTO.builder()
- .id("1")
- .name("role")
- .description("desc")
- .typeRole(TypeRole.REALM_ROLE)
- .clientName("client")
- .build();
-
- assertEquals("1", comp.getId());
- assertEquals("role", comp.getName());
- assertEquals("desc", comp.getDescription());
- assertEquals(TypeRole.REALM_ROLE, comp.getTypeRole());
- assertEquals("client", comp.getClientName());
- }
-
- @Test
- void testRoleCompositeDTO_settersGetters() {
- RoleDTO.RoleCompositeDTO comp = new RoleDTO.RoleCompositeDTO();
- comp.setId("id");
- comp.setName("name");
- comp.setDescription("desc");
- comp.setTypeRole(TypeRole.CLIENT_ROLE);
- comp.setClientName("client");
-
- assertEquals("id", comp.getId());
- assertEquals("name", comp.getName());
- assertEquals("desc", comp.getDescription());
- assertEquals(TypeRole.CLIENT_ROLE, comp.getTypeRole());
- assertEquals("client", comp.getClientName());
- }
-
- @Test
- void testRoleCompositeDTO_allArgsConstructor() {
- RoleDTO.RoleCompositeDTO comp = new RoleDTO.RoleCompositeDTO("id", "name", "desc", TypeRole.REALM_ROLE,
- "client");
- assertEquals("id", comp.getId());
- assertEquals("name", comp.getName());
- assertEquals("desc", comp.getDescription());
- assertEquals(TypeRole.REALM_ROLE, comp.getTypeRole());
- assertEquals("client", comp.getClientName());
- }
-
- @Test
- void testRoleCompositeDTO_equalsAndHashCode() {
- RoleDTO.RoleCompositeDTO comp1 = RoleDTO.RoleCompositeDTO.builder().id("1").name("role").build();
- RoleDTO.RoleCompositeDTO comp2 = RoleDTO.RoleCompositeDTO.builder().id("1").name("role").build();
- RoleDTO.RoleCompositeDTO comp3 = RoleDTO.RoleCompositeDTO.builder().id("2").name("other").build();
-
- assertEquals(comp1, comp2);
- assertEquals(comp1.hashCode(), comp2.hashCode());
- assertNotEquals(comp1, comp3);
- }
-
- @Test
- void testRoleCompositeDTO_toString() {
- RoleDTO.RoleCompositeDTO comp = RoleDTO.RoleCompositeDTO.builder().id("1").name("role").build();
- String str = comp.toString();
- assertNotNull(str);
- assertTrue(str.contains("role"));
- }
-
- @Test
- void testBuilderAndAllFields() {
- Map> attrs = new HashMap<>();
- attrs.put("key", Collections.singletonList("value"));
- Map> clientComposites = new HashMap<>();
- clientComposites.put("client",
- Collections.singletonList(RoleDTO.RoleCompositeDTO.builder().name("subclient").build()));
-
- RoleDTO role = RoleDTO.builder()
- .id("uuid-123")
- .name("admin")
- .description("Administrator role")
- .typeRole(TypeRole.REALM_ROLE)
- .composite(true)
- .containerId("container")
- .realmName("realm")
- .clientName("client")
- .clientId("clientId")
- .compositeRoles(Arrays.asList("role1", "role2"))
- .compositeRealmRoles(
- Collections.singletonList(RoleDTO.RoleCompositeDTO.builder().name("subrealm").build()))
- .compositeClientRoles(clientComposites)
- .attributes(attrs)
- .userCount(10)
- .systemRole(false)
- .deletable(true)
- .build();
-
- assertEquals("uuid-123", role.getId());
- assertEquals("admin", role.getName());
- assertEquals("Administrator role", role.getDescription());
- assertEquals(TypeRole.REALM_ROLE, role.getTypeRole());
- assertTrue(role.getComposite());
- assertEquals("container", role.getContainerId());
- assertEquals("realm", role.getRealmName());
- assertEquals("client", role.getClientName());
- assertEquals("clientId", role.getClientId());
- assertEquals(2, role.getCompositeRoles().size());
- assertEquals(1, role.getCompositeRealmRoles().size());
- assertEquals(1, role.getCompositeClientRoles().size());
- assertEquals(1, role.getAttributes().size());
- assertEquals(10, role.getUserCount());
- assertFalse(role.getSystemRole());
- assertTrue(role.getDeletable());
- }
-
- @Test
- void testEqualsAndHashCode() {
- RoleDTO role1 = RoleDTO.builder().id("uuid-123").name("admin").build();
- RoleDTO role2 = RoleDTO.builder().id("uuid-123").name("admin").build();
- RoleDTO role3 = RoleDTO.builder().id("uuid-456").name("user").build();
-
- assertEquals(role1, role2);
- assertEquals(role1.hashCode(), role2.hashCode());
- assertNotEquals(role1, role3);
- }
-
- @Test
- void testToString() {
- RoleDTO role = RoleDTO.builder().name("admin").description("Admin role").build();
- String str = role.toString();
- assertNotNull(str);
- assertTrue(str.contains("admin"));
- }
-
- @Test
- void testNoArgsConstructor() {
- RoleDTO role = new RoleDTO();
- assertNull(role.getName());
- assertNull(role.getDescription());
- }
-
- @Test
- void testAllArgsConstructor() {
- Map> attrs = new HashMap<>();
- Map> clientComposites = new HashMap<>();
- List compositeRoles = Collections.emptyList();
- List realmComposites = Collections.emptyList();
-
- RoleDTO role = new RoleDTO(
- "name", "desc", TypeRole.REALM_ROLE, true, "container", "realm",
- "clientName", "clientId", compositeRoles, realmComposites, clientComposites,
- attrs, 5, true, false);
-
- assertEquals("name", role.getName());
- assertEquals("desc", role.getDescription());
- assertEquals(TypeRole.REALM_ROLE, role.getTypeRole());
- assertTrue(role.getComposite());
- assertEquals("container", role.getContainerId());
- assertEquals("realm", role.getRealmName());
- assertEquals("clientName", role.getClientName());
- assertEquals("clientId", role.getClientId());
- assertEquals(5, role.getUserCount());
- assertTrue(role.getSystemRole());
- assertFalse(role.getDeletable());
- }
-}
+package dev.lions.user.manager.dto.role;
+
+import dev.lions.user.manager.enums.role.TypeRole;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class RoleDTOTest {
+
+ @Test
+ void testIsRealmRole_true() {
+ RoleDTO role = new RoleDTO();
+ role.setTypeRole(TypeRole.REALM_ROLE);
+ assertTrue(role.isRealmRole());
+ assertFalse(role.isClientRole());
+ }
+
+ @Test
+ void testIsRealmRole_false() {
+ RoleDTO role = new RoleDTO();
+ role.setTypeRole(TypeRole.CLIENT_ROLE);
+ assertFalse(role.isRealmRole());
+ }
+
+ @Test
+ void testIsRealmRole_null() {
+ RoleDTO role = new RoleDTO();
+ role.setTypeRole(null);
+ assertFalse(role.isRealmRole());
+ }
+
+ @Test
+ void testIsClientRole_true() {
+ RoleDTO role = new RoleDTO();
+ role.setTypeRole(TypeRole.CLIENT_ROLE);
+ assertTrue(role.isClientRole());
+ assertFalse(role.isRealmRole());
+ }
+
+ @Test
+ void testIsClientRole_false() {
+ RoleDTO role = new RoleDTO();
+ role.setTypeRole(TypeRole.REALM_ROLE);
+ assertFalse(role.isClientRole());
+ }
+
+ @Test
+ void testIsClientRole_null() {
+ RoleDTO role = new RoleDTO();
+ role.setTypeRole(null);
+ assertFalse(role.isClientRole());
+ }
+
+ @Test
+ void testIsComposite_withCompositeRoles() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(true);
+ role.setCompositeRoles(Arrays.asList("role1", "role2"));
+ assertTrue(role.isComposite());
+ }
+
+ @Test
+ void testIsComposite_withCompositeRealmRoles() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(true);
+ role.setCompositeRoles(null);
+ role.setCompositeRealmRoles(Collections.singletonList(new RoleDTO.RoleCompositeDTO()));
+ assertTrue(role.isComposite());
+ }
+
+ @Test
+ void testIsComposite_withCompositeClientRoles() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(true);
+ role.setCompositeRoles(null);
+ role.setCompositeRealmRoles(null);
+ Map> clientRoles = new HashMap<>();
+ clientRoles.put("client", Collections.singletonList(new RoleDTO.RoleCompositeDTO()));
+ role.setCompositeClientRoles(clientRoles);
+ assertTrue(role.isComposite());
+ }
+
+ @Test
+ void testIsComposite_falseWhenCompositeFalse() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(false);
+ role.setCompositeRoles(Arrays.asList("role1"));
+ assertFalse(role.isComposite());
+ }
+
+ @Test
+ void testIsComposite_falseWhenCompositeNull() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(null);
+ role.setCompositeRoles(Arrays.asList("role1"));
+ assertFalse(role.isComposite());
+ }
+
+ @Test
+ void testIsComposite_falseWhenNoRoles() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(true);
+ role.setCompositeRoles(null);
+ role.setCompositeRealmRoles(null);
+ role.setCompositeClientRoles(null);
+ assertFalse(role.isComposite());
+ }
+
+ @Test
+ void testIsComposite_falseWhenEmptyRoles() {
+ RoleDTO role = new RoleDTO();
+ role.setComposite(true);
+ role.setCompositeRoles(Collections.emptyList());
+ role.setCompositeRealmRoles(Collections.emptyList());
+ role.setCompositeClientRoles(Collections.emptyMap());
+ assertFalse(role.isComposite());
+ }
+
+ @Test
+ void testGetFullName_realmRole() {
+ RoleDTO role = new RoleDTO();
+ role.setName("admin");
+ role.setTypeRole(TypeRole.REALM_ROLE);
+ assertEquals("admin", role.getFullName());
+ }
+
+ @Test
+ void testGetFullName_clientRole() {
+ RoleDTO role = new RoleDTO();
+ role.setName("admin");
+ role.setTypeRole(TypeRole.CLIENT_ROLE);
+ role.setClientName("app");
+ assertEquals("app:admin", role.getFullName());
+ }
+
+ @Test
+ void testGetFullName_clientRoleNullClientName() {
+ RoleDTO role = new RoleDTO();
+ role.setName("admin");
+ role.setTypeRole(TypeRole.CLIENT_ROLE);
+ role.setClientName(null);
+ assertEquals("admin", role.getFullName());
+ }
+
+ @Test
+ void testGetFullName_nullTypeRole() {
+ RoleDTO role = new RoleDTO();
+ role.setName("admin");
+ role.setTypeRole(null);
+ assertEquals("admin", role.getFullName());
+ }
+
+ @Test
+ void testRoleCompositeDTO_builder() {
+ RoleDTO.RoleCompositeDTO comp = RoleDTO.RoleCompositeDTO.builder()
+ .id("1")
+ .name("role")
+ .description("desc")
+ .typeRole(TypeRole.REALM_ROLE)
+ .clientName("client")
+ .build();
+
+ assertEquals("1", comp.getId());
+ assertEquals("role", comp.getName());
+ assertEquals("desc", comp.getDescription());
+ assertEquals(TypeRole.REALM_ROLE, comp.getTypeRole());
+ assertEquals("client", comp.getClientName());
+ }
+
+ @Test
+ void testRoleCompositeDTO_settersGetters() {
+ RoleDTO.RoleCompositeDTO comp = new RoleDTO.RoleCompositeDTO();
+ comp.setId("id");
+ comp.setName("name");
+ comp.setDescription("desc");
+ comp.setTypeRole(TypeRole.CLIENT_ROLE);
+ comp.setClientName("client");
+
+ assertEquals("id", comp.getId());
+ assertEquals("name", comp.getName());
+ assertEquals("desc", comp.getDescription());
+ assertEquals(TypeRole.CLIENT_ROLE, comp.getTypeRole());
+ assertEquals("client", comp.getClientName());
+ }
+
+ @Test
+ void testRoleCompositeDTO_allArgsConstructor() {
+ RoleDTO.RoleCompositeDTO comp = new RoleDTO.RoleCompositeDTO("id", "name", "desc", TypeRole.REALM_ROLE,
+ "client");
+ assertEquals("id", comp.getId());
+ assertEquals("name", comp.getName());
+ assertEquals("desc", comp.getDescription());
+ assertEquals(TypeRole.REALM_ROLE, comp.getTypeRole());
+ assertEquals("client", comp.getClientName());
+ }
+
+ @Test
+ void testRoleCompositeDTO_equalsAndHashCode() {
+ RoleDTO.RoleCompositeDTO comp1 = RoleDTO.RoleCompositeDTO.builder().id("1").name("role").build();
+ RoleDTO.RoleCompositeDTO comp2 = RoleDTO.RoleCompositeDTO.builder().id("1").name("role").build();
+ RoleDTO.RoleCompositeDTO comp3 = RoleDTO.RoleCompositeDTO.builder().id("2").name("other").build();
+
+ assertEquals(comp1, comp2);
+ assertEquals(comp1.hashCode(), comp2.hashCode());
+ assertNotEquals(comp1, comp3);
+ }
+
+ @Test
+ void testRoleCompositeDTO_toString() {
+ RoleDTO.RoleCompositeDTO comp = RoleDTO.RoleCompositeDTO.builder().id("1").name("role").build();
+ String str = comp.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("role"));
+ }
+
+ @Test
+ void testBuilderAndAllFields() {
+ Map> attrs = new HashMap<>();
+ attrs.put("key", Collections.singletonList("value"));
+ Map> clientComposites = new HashMap<>();
+ clientComposites.put("client",
+ Collections.singletonList(RoleDTO.RoleCompositeDTO.builder().name("subclient").build()));
+
+ RoleDTO role = RoleDTO.builder()
+ .id("uuid-123")
+ .name("admin")
+ .description("Administrator role")
+ .typeRole(TypeRole.REALM_ROLE)
+ .composite(true)
+ .containerId("container")
+ .realmName("realm")
+ .clientName("client")
+ .clientId("clientId")
+ .compositeRoles(Arrays.asList("role1", "role2"))
+ .compositeRealmRoles(
+ Collections.singletonList(RoleDTO.RoleCompositeDTO.builder().name("subrealm").build()))
+ .compositeClientRoles(clientComposites)
+ .attributes(attrs)
+ .userCount(10)
+ .systemRole(false)
+ .deletable(true)
+ .build();
+
+ assertEquals("uuid-123", role.getId());
+ assertEquals("admin", role.getName());
+ assertEquals("Administrator role", role.getDescription());
+ assertEquals(TypeRole.REALM_ROLE, role.getTypeRole());
+ assertTrue(role.getComposite());
+ assertEquals("container", role.getContainerId());
+ assertEquals("realm", role.getRealmName());
+ assertEquals("client", role.getClientName());
+ assertEquals("clientId", role.getClientId());
+ assertEquals(2, role.getCompositeRoles().size());
+ assertEquals(1, role.getCompositeRealmRoles().size());
+ assertEquals(1, role.getCompositeClientRoles().size());
+ assertEquals(1, role.getAttributes().size());
+ assertEquals(10, role.getUserCount());
+ assertFalse(role.getSystemRole());
+ assertTrue(role.getDeletable());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ RoleDTO role1 = RoleDTO.builder().id("uuid-123").name("admin").build();
+ RoleDTO role2 = RoleDTO.builder().id("uuid-123").name("admin").build();
+ RoleDTO role3 = RoleDTO.builder().id("uuid-456").name("user").build();
+
+ assertEquals(role1, role2);
+ assertEquals(role1.hashCode(), role2.hashCode());
+ assertNotEquals(role1, role3);
+ }
+
+ @Test
+ void testToString() {
+ RoleDTO role = RoleDTO.builder().name("admin").description("Admin role").build();
+ String str = role.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("admin"));
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ RoleDTO role = new RoleDTO();
+ assertNull(role.getName());
+ assertNull(role.getDescription());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ Map> attrs = new HashMap<>();
+ Map> clientComposites = new HashMap<>();
+ List compositeRoles = Collections.emptyList();
+ List realmComposites = Collections.emptyList();
+
+ RoleDTO role = new RoleDTO(
+ "name", "desc", TypeRole.REALM_ROLE, true, "container", "realm",
+ "clientName", "clientId", compositeRoles, realmComposites, clientComposites,
+ attrs, 5, true, false);
+
+ assertEquals("name", role.getName());
+ assertEquals("desc", role.getDescription());
+ assertEquals(TypeRole.REALM_ROLE, role.getTypeRole());
+ assertTrue(role.getComposite());
+ assertEquals("container", role.getContainerId());
+ assertEquals("realm", role.getRealmName());
+ assertEquals("clientName", role.getClientName());
+ assertEquals("clientId", role.getClientId());
+ assertEquals(5, role.getUserCount());
+ assertTrue(role.getSystemRole());
+ assertFalse(role.getDeletable());
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/sync/HealthStatusDTOTest.java b/src/test/java/dev/lions/user/manager/dto/sync/HealthStatusDTOTest.java
index c6bcaee..cf2320c 100644
--- a/src/test/java/dev/lions/user/manager/dto/sync/HealthStatusDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/sync/HealthStatusDTOTest.java
@@ -1,125 +1,125 @@
-package dev.lions.user.manager.dto.sync;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class HealthStatusDTOTest {
-
- @Test
- void testBuilderAndAllFields() {
- HealthStatusDTO dto = HealthStatusDTO.builder()
- .timestamp(1699545600000L)
- .keycloakAccessible(true)
- .keycloakVersion("23.0.3")
- .realmsAccessible(true)
- .realmsCount(5)
- .overallHealthy(true)
- .errorMessage(null)
- .build();
-
- assertEquals(1699545600000L, dto.getTimestamp());
- assertTrue(dto.isKeycloakAccessible());
- assertEquals("23.0.3", dto.getKeycloakVersion());
- assertTrue(dto.isRealmsAccessible());
- assertEquals(5, dto.getRealmsCount());
- assertTrue(dto.isOverallHealthy());
- assertNull(dto.getErrorMessage());
- }
-
- @Test
- void testBuilderWithError() {
- HealthStatusDTO dto = HealthStatusDTO.builder()
- .timestamp(System.currentTimeMillis())
- .keycloakAccessible(false)
- .realmsAccessible(false)
- .overallHealthy(false)
- .errorMessage("Connection refused")
- .build();
-
- assertFalse(dto.isKeycloakAccessible());
- assertFalse(dto.isRealmsAccessible());
- assertFalse(dto.isOverallHealthy());
- assertEquals("Connection refused", dto.getErrorMessage());
- }
-
- @Test
- void testSettersAndGetters() {
- HealthStatusDTO dto = new HealthStatusDTO();
- dto.setTimestamp(12345L);
- dto.setKeycloakAccessible(true);
- dto.setKeycloakVersion("24.0.0");
- dto.setRealmsAccessible(true);
- dto.setRealmsCount(3);
- dto.setOverallHealthy(true);
- dto.setErrorMessage("warning");
-
- assertEquals(12345L, dto.getTimestamp());
- assertTrue(dto.isKeycloakAccessible());
- assertEquals("24.0.0", dto.getKeycloakVersion());
- assertTrue(dto.isRealmsAccessible());
- assertEquals(3, dto.getRealmsCount());
- assertTrue(dto.isOverallHealthy());
- assertEquals("warning", dto.getErrorMessage());
- }
-
- @Test
- void testEqualsAndHashCode() {
- HealthStatusDTO dto1 = HealthStatusDTO.builder()
- .timestamp(1000L)
- .keycloakVersion("23.0.3")
- .overallHealthy(true)
- .build();
- HealthStatusDTO dto2 = HealthStatusDTO.builder()
- .timestamp(1000L)
- .keycloakVersion("23.0.3")
- .overallHealthy(true)
- .build();
- HealthStatusDTO dto3 = HealthStatusDTO.builder()
- .timestamp(2000L)
- .keycloakVersion("24.0.0")
- .overallHealthy(false)
- .build();
-
- assertEquals(dto1, dto2);
- assertEquals(dto1.hashCode(), dto2.hashCode());
- assertNotEquals(dto1, dto3);
- }
-
- @Test
- void testToString() {
- HealthStatusDTO dto = HealthStatusDTO.builder()
- .keycloakVersion("23.0.3")
- .overallHealthy(true)
- .build();
- String str = dto.toString();
- assertNotNull(str);
- assertTrue(str.contains("23.0.3"));
- }
-
- @Test
- void testNoArgsConstructor() {
- HealthStatusDTO dto = new HealthStatusDTO();
- assertEquals(0L, dto.getTimestamp());
- assertFalse(dto.isKeycloakAccessible());
- assertNull(dto.getKeycloakVersion());
- assertFalse(dto.isRealmsAccessible());
- assertEquals(0, dto.getRealmsCount());
- assertFalse(dto.isOverallHealthy());
- assertNull(dto.getErrorMessage());
- }
-
- @Test
- void testAllArgsConstructor() {
- HealthStatusDTO dto = new HealthStatusDTO(
- 1000L, true, "23.0.3", true, 5, true, null);
-
- assertEquals(1000L, dto.getTimestamp());
- assertTrue(dto.isKeycloakAccessible());
- assertEquals("23.0.3", dto.getKeycloakVersion());
- assertTrue(dto.isRealmsAccessible());
- assertEquals(5, dto.getRealmsCount());
- assertTrue(dto.isOverallHealthy());
- assertNull(dto.getErrorMessage());
- }
-}
+package dev.lions.user.manager.dto.sync;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class HealthStatusDTOTest {
+
+ @Test
+ void testBuilderAndAllFields() {
+ HealthStatusDTO dto = HealthStatusDTO.builder()
+ .timestamp(1699545600000L)
+ .keycloakAccessible(true)
+ .keycloakVersion("23.0.3")
+ .realmsAccessible(true)
+ .realmsCount(5)
+ .overallHealthy(true)
+ .errorMessage(null)
+ .build();
+
+ assertEquals(1699545600000L, dto.getTimestamp());
+ assertTrue(dto.isKeycloakAccessible());
+ assertEquals("23.0.3", dto.getKeycloakVersion());
+ assertTrue(dto.isRealmsAccessible());
+ assertEquals(5, dto.getRealmsCount());
+ assertTrue(dto.isOverallHealthy());
+ assertNull(dto.getErrorMessage());
+ }
+
+ @Test
+ void testBuilderWithError() {
+ HealthStatusDTO dto = HealthStatusDTO.builder()
+ .timestamp(System.currentTimeMillis())
+ .keycloakAccessible(false)
+ .realmsAccessible(false)
+ .overallHealthy(false)
+ .errorMessage("Connection refused")
+ .build();
+
+ assertFalse(dto.isKeycloakAccessible());
+ assertFalse(dto.isRealmsAccessible());
+ assertFalse(dto.isOverallHealthy());
+ assertEquals("Connection refused", dto.getErrorMessage());
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ HealthStatusDTO dto = new HealthStatusDTO();
+ dto.setTimestamp(12345L);
+ dto.setKeycloakAccessible(true);
+ dto.setKeycloakVersion("24.0.0");
+ dto.setRealmsAccessible(true);
+ dto.setRealmsCount(3);
+ dto.setOverallHealthy(true);
+ dto.setErrorMessage("warning");
+
+ assertEquals(12345L, dto.getTimestamp());
+ assertTrue(dto.isKeycloakAccessible());
+ assertEquals("24.0.0", dto.getKeycloakVersion());
+ assertTrue(dto.isRealmsAccessible());
+ assertEquals(3, dto.getRealmsCount());
+ assertTrue(dto.isOverallHealthy());
+ assertEquals("warning", dto.getErrorMessage());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ HealthStatusDTO dto1 = HealthStatusDTO.builder()
+ .timestamp(1000L)
+ .keycloakVersion("23.0.3")
+ .overallHealthy(true)
+ .build();
+ HealthStatusDTO dto2 = HealthStatusDTO.builder()
+ .timestamp(1000L)
+ .keycloakVersion("23.0.3")
+ .overallHealthy(true)
+ .build();
+ HealthStatusDTO dto3 = HealthStatusDTO.builder()
+ .timestamp(2000L)
+ .keycloakVersion("24.0.0")
+ .overallHealthy(false)
+ .build();
+
+ assertEquals(dto1, dto2);
+ assertEquals(dto1.hashCode(), dto2.hashCode());
+ assertNotEquals(dto1, dto3);
+ }
+
+ @Test
+ void testToString() {
+ HealthStatusDTO dto = HealthStatusDTO.builder()
+ .keycloakVersion("23.0.3")
+ .overallHealthy(true)
+ .build();
+ String str = dto.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("23.0.3"));
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ HealthStatusDTO dto = new HealthStatusDTO();
+ assertEquals(0L, dto.getTimestamp());
+ assertFalse(dto.isKeycloakAccessible());
+ assertNull(dto.getKeycloakVersion());
+ assertFalse(dto.isRealmsAccessible());
+ assertEquals(0, dto.getRealmsCount());
+ assertFalse(dto.isOverallHealthy());
+ assertNull(dto.getErrorMessage());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ HealthStatusDTO dto = new HealthStatusDTO(
+ 1000L, true, "23.0.3", true, 5, true, null);
+
+ assertEquals(1000L, dto.getTimestamp());
+ assertTrue(dto.isKeycloakAccessible());
+ assertEquals("23.0.3", dto.getKeycloakVersion());
+ assertTrue(dto.isRealmsAccessible());
+ assertEquals(5, dto.getRealmsCount());
+ assertTrue(dto.isOverallHealthy());
+ assertNull(dto.getErrorMessage());
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/sync/SyncResultDTOTest.java b/src/test/java/dev/lions/user/manager/dto/sync/SyncResultDTOTest.java
index 0be3a91..4704f63 100644
--- a/src/test/java/dev/lions/user/manager/dto/sync/SyncResultDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/sync/SyncResultDTOTest.java
@@ -1,127 +1,127 @@
-package dev.lions.user.manager.dto.sync;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class SyncResultDTOTest {
-
- @Test
- void testGetDurationMs() {
- SyncResultDTO dto = SyncResultDTO.builder()
- .startTime(1000L)
- .endTime(5000L)
- .build();
- assertEquals(4000L, dto.getDurationMs());
- }
-
- @Test
- void testGetDurationMs_sameTime() {
- SyncResultDTO dto = SyncResultDTO.builder()
- .startTime(1000L)
- .endTime(1000L)
- .build();
- assertEquals(0L, dto.getDurationMs());
- }
-
- @Test
- void testBuilderAndAllFields() {
- SyncResultDTO dto = SyncResultDTO.builder()
- .realmName("btpxpress")
- .usersCount(150)
- .realmRolesCount(25)
- .clientRolesCount(50)
- .success(true)
- .errorMessage(null)
- .startTime(1699545600000L)
- .endTime(1699545615000L)
- .build();
-
- assertEquals("btpxpress", dto.getRealmName());
- assertEquals(150, dto.getUsersCount());
- assertEquals(25, dto.getRealmRolesCount());
- assertEquals(50, dto.getClientRolesCount());
- assertTrue(dto.isSuccess());
- assertNull(dto.getErrorMessage());
- assertEquals(1699545600000L, dto.getStartTime());
- assertEquals(1699545615000L, dto.getEndTime());
- assertEquals(15000L, dto.getDurationMs());
- }
-
- @Test
- void testBuilderWithError() {
- SyncResultDTO dto = SyncResultDTO.builder()
- .realmName("btpxpress")
- .success(false)
- .errorMessage("Connection failed")
- .build();
-
- assertEquals("btpxpress", dto.getRealmName());
- assertFalse(dto.isSuccess());
- assertEquals("Connection failed", dto.getErrorMessage());
- }
-
- @Test
- void testSettersAndGetters() {
- SyncResultDTO dto = new SyncResultDTO();
- dto.setRealmName("realm");
- dto.setUsersCount(10);
- dto.setRealmRolesCount(5);
- dto.setClientRolesCount(3);
- dto.setSuccess(true);
- dto.setErrorMessage("error");
- dto.setStartTime(100L);
- dto.setEndTime(200L);
-
- assertEquals("realm", dto.getRealmName());
- assertEquals(10, dto.getUsersCount());
- assertEquals(5, dto.getRealmRolesCount());
- assertEquals(3, dto.getClientRolesCount());
- assertTrue(dto.isSuccess());
- assertEquals("error", dto.getErrorMessage());
- assertEquals(100L, dto.getStartTime());
- assertEquals(200L, dto.getEndTime());
- }
-
- @Test
- void testEqualsAndHashCode() {
- SyncResultDTO dto1 = SyncResultDTO.builder().realmName("realm").usersCount(10).build();
- SyncResultDTO dto2 = SyncResultDTO.builder().realmName("realm").usersCount(10).build();
- SyncResultDTO dto3 = SyncResultDTO.builder().realmName("other").usersCount(5).build();
-
- assertEquals(dto1, dto2);
- assertEquals(dto1.hashCode(), dto2.hashCode());
- assertNotEquals(dto1, dto3);
- }
-
- @Test
- void testToString() {
- SyncResultDTO dto = SyncResultDTO.builder().realmName("realm").success(true).build();
- String str = dto.toString();
- assertNotNull(str);
- assertTrue(str.contains("realm"));
- }
-
- @Test
- void testNoArgsConstructor() {
- SyncResultDTO dto = new SyncResultDTO();
- assertNull(dto.getRealmName());
- assertEquals(0, dto.getUsersCount());
- assertFalse(dto.isSuccess());
- }
-
- @Test
- void testAllArgsConstructor() {
- SyncResultDTO dto = new SyncResultDTO(
- "realm", 100, 20, 30, true, null, 1000L, 2000L);
-
- assertEquals("realm", dto.getRealmName());
- assertEquals(100, dto.getUsersCount());
- assertEquals(20, dto.getRealmRolesCount());
- assertEquals(30, dto.getClientRolesCount());
- assertTrue(dto.isSuccess());
- assertNull(dto.getErrorMessage());
- assertEquals(1000L, dto.getStartTime());
- assertEquals(2000L, dto.getEndTime());
- }
-}
+package dev.lions.user.manager.dto.sync;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class SyncResultDTOTest {
+
+ @Test
+ void testGetDurationMs() {
+ SyncResultDTO dto = SyncResultDTO.builder()
+ .startTime(1000L)
+ .endTime(5000L)
+ .build();
+ assertEquals(4000L, dto.getDurationMs());
+ }
+
+ @Test
+ void testGetDurationMs_sameTime() {
+ SyncResultDTO dto = SyncResultDTO.builder()
+ .startTime(1000L)
+ .endTime(1000L)
+ .build();
+ assertEquals(0L, dto.getDurationMs());
+ }
+
+ @Test
+ void testBuilderAndAllFields() {
+ SyncResultDTO dto = SyncResultDTO.builder()
+ .realmName("btpxpress")
+ .usersCount(150)
+ .realmRolesCount(25)
+ .clientRolesCount(50)
+ .success(true)
+ .errorMessage(null)
+ .startTime(1699545600000L)
+ .endTime(1699545615000L)
+ .build();
+
+ assertEquals("btpxpress", dto.getRealmName());
+ assertEquals(150, dto.getUsersCount());
+ assertEquals(25, dto.getRealmRolesCount());
+ assertEquals(50, dto.getClientRolesCount());
+ assertTrue(dto.isSuccess());
+ assertNull(dto.getErrorMessage());
+ assertEquals(1699545600000L, dto.getStartTime());
+ assertEquals(1699545615000L, dto.getEndTime());
+ assertEquals(15000L, dto.getDurationMs());
+ }
+
+ @Test
+ void testBuilderWithError() {
+ SyncResultDTO dto = SyncResultDTO.builder()
+ .realmName("btpxpress")
+ .success(false)
+ .errorMessage("Connection failed")
+ .build();
+
+ assertEquals("btpxpress", dto.getRealmName());
+ assertFalse(dto.isSuccess());
+ assertEquals("Connection failed", dto.getErrorMessage());
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ SyncResultDTO dto = new SyncResultDTO();
+ dto.setRealmName("realm");
+ dto.setUsersCount(10);
+ dto.setRealmRolesCount(5);
+ dto.setClientRolesCount(3);
+ dto.setSuccess(true);
+ dto.setErrorMessage("error");
+ dto.setStartTime(100L);
+ dto.setEndTime(200L);
+
+ assertEquals("realm", dto.getRealmName());
+ assertEquals(10, dto.getUsersCount());
+ assertEquals(5, dto.getRealmRolesCount());
+ assertEquals(3, dto.getClientRolesCount());
+ assertTrue(dto.isSuccess());
+ assertEquals("error", dto.getErrorMessage());
+ assertEquals(100L, dto.getStartTime());
+ assertEquals(200L, dto.getEndTime());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ SyncResultDTO dto1 = SyncResultDTO.builder().realmName("realm").usersCount(10).build();
+ SyncResultDTO dto2 = SyncResultDTO.builder().realmName("realm").usersCount(10).build();
+ SyncResultDTO dto3 = SyncResultDTO.builder().realmName("other").usersCount(5).build();
+
+ assertEquals(dto1, dto2);
+ assertEquals(dto1.hashCode(), dto2.hashCode());
+ assertNotEquals(dto1, dto3);
+ }
+
+ @Test
+ void testToString() {
+ SyncResultDTO dto = SyncResultDTO.builder().realmName("realm").success(true).build();
+ String str = dto.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("realm"));
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ SyncResultDTO dto = new SyncResultDTO();
+ assertNull(dto.getRealmName());
+ assertEquals(0, dto.getUsersCount());
+ assertFalse(dto.isSuccess());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ SyncResultDTO dto = new SyncResultDTO(
+ "realm", 100, 20, 30, true, null, 1000L, 2000L);
+
+ assertEquals("realm", dto.getRealmName());
+ assertEquals(100, dto.getUsersCount());
+ assertEquals(20, dto.getRealmRolesCount());
+ assertEquals(30, dto.getClientRolesCount());
+ assertTrue(dto.isSuccess());
+ assertNull(dto.getErrorMessage());
+ assertEquals(1000L, dto.getStartTime());
+ assertEquals(2000L, dto.getEndTime());
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/user/UserDTOTest.java b/src/test/java/dev/lions/user/manager/dto/user/UserDTOTest.java
index d421f21..37ff878 100644
--- a/src/test/java/dev/lions/user/manager/dto/user/UserDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/user/UserDTOTest.java
@@ -1,305 +1,305 @@
-package dev.lions.user.manager.dto.user;
-
-import dev.lions.user.manager.enums.user.StatutUser;
-import org.junit.jupiter.api.Test;
-
-import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class UserDTOTest {
-
- @Test
- void testGetNomComplet_withPrenomAndNom() {
- UserDTO user = new UserDTO();
- user.setPrenom("Jean");
- user.setNom("Dupont");
- user.setUsername("jdupont");
- assertEquals("Jean Dupont", user.getNomComplet());
- }
-
- @Test
- void testGetNomComplet_withNullPrenom() {
- UserDTO user = new UserDTO();
- user.setPrenom(null);
- user.setNom("Dupont");
- user.setUsername("jdupont");
- assertEquals("jdupont", user.getNomComplet());
- }
-
- @Test
- void testGetNomComplet_withNullNom() {
- UserDTO user = new UserDTO();
- user.setPrenom("Jean");
- user.setNom(null);
- user.setUsername("jdupont");
- assertEquals("jdupont", user.getNomComplet());
- }
-
- @Test
- void testGetNomComplet_withBothNull() {
- UserDTO user = new UserDTO();
- user.setPrenom(null);
- user.setNom(null);
- user.setUsername("jdupont");
- assertEquals("jdupont", user.getNomComplet());
- }
-
- @Test
- void testIsActif_true() {
- UserDTO user = new UserDTO();
- user.setStatut(StatutUser.ACTIF);
- user.setEnabled(true);
- assertTrue(user.isActif());
- }
-
- @Test
- void testIsActif_falseWhenNotActif() {
- UserDTO user = new UserDTO();
- user.setStatut(StatutUser.INACTIF);
- user.setEnabled(true);
- assertFalse(user.isActif());
- }
-
- @Test
- void testIsActif_falseWhenNotEnabled() {
- UserDTO user = new UserDTO();
- user.setStatut(StatutUser.ACTIF);
- user.setEnabled(false);
- assertFalse(user.isActif());
- }
-
- @Test
- void testIsActif_falseWhenEnabledNull() {
- UserDTO user = new UserDTO();
- user.setStatut(StatutUser.ACTIF);
- user.setEnabled(null);
- assertFalse(user.isActif());
- }
-
- @Test
- void testIsExpire_true() {
- UserDTO user = new UserDTO();
- user.setDateExpiration(LocalDateTime.now().minusDays(1));
- assertTrue(user.isExpire());
- }
-
- @Test
- void testIsExpire_false() {
- UserDTO user = new UserDTO();
- user.setDateExpiration(LocalDateTime.now().plusDays(1));
- assertFalse(user.isExpire());
- }
-
- @Test
- void testIsExpire_nullDate() {
- UserDTO user = new UserDTO();
- user.setDateExpiration(null);
- assertFalse(user.isExpire());
- }
-
- @Test
- void testHasRequiredActions_true() {
- UserDTO user = new UserDTO();
- user.setRequiredActions(Arrays.asList("UPDATE_PASSWORD", "VERIFY_EMAIL"));
- assertTrue(user.hasRequiredActions());
- }
-
- @Test
- void testHasRequiredActions_empty() {
- UserDTO user = new UserDTO();
- user.setRequiredActions(Collections.emptyList());
- assertFalse(user.hasRequiredActions());
- }
-
- @Test
- void testHasRequiredActions_null() {
- UserDTO user = new UserDTO();
- user.setRequiredActions(null);
- assertFalse(user.hasRequiredActions());
- }
-
- @Test
- void testBuilderAndAllFields() {
- LocalDateTime now = LocalDateTime.now();
- Map> clientRoles = new HashMap<>();
- clientRoles.put("app", Arrays.asList("user", "admin"));
- Map> attributes = new HashMap<>();
- attributes.put("custom", Collections.singletonList("value"));
-
- List fedIds = Collections.singletonList(
- UserDTO.FederatedIdentityDTO.builder()
- .identityProvider("google")
- .userId("google-123")
- .userName("user@gmail.com")
- .build());
-
- UserDTO user = UserDTO.builder()
- .id("uuid-123")
- .dateCreation(now)
- .dateModification(now)
- .creeParUsername("admin")
- .modifieParUsername("admin")
- .version(1L)
- .username("jdupont")
- .email("jean.dupont@lions.dev")
- .emailVerified(true)
- .prenom("Jean")
- .nom("Dupont")
- .statut(StatutUser.ACTIF)
- .enabled(true)
- .telephone("+225 07 12 34 56 78")
- .organisation("Lions Dev")
- .departement("IT")
- .fonction("Developer")
- .pays("Côte d'Ivoire")
- .ville("Abidjan")
- .langue("fr")
- .timezone("Africa/Abidjan")
- .realmName("btpxpress")
- .realmRoles(Arrays.asList("user", "admin"))
- .clientRoles(clientRoles)
- .groups(Arrays.asList("group1", "group2"))
- .derniereConnexion(now)
- .dateExpiration(now.plusYears(1))
- .dateVerrouillage(null)
- .attributes(attributes)
- .requiredActions(Collections.singletonList("UPDATE_PASSWORD"))
- .federatedIdentityProvider("google")
- .federatedIdentities(fedIds)
- .temporaryPassword("temp123")
- .temporaryPasswordFlag(true)
- .activeSessions(2)
- .failedLoginAttempts(0)
- .raisonModification("Update")
- .commentaires("Test user")
- .build();
-
- assertEquals("uuid-123", user.getId());
- assertNotNull(user.getDateCreation());
- assertNotNull(user.getDateModification());
- assertEquals("admin", user.getCreeParUsername());
- assertEquals("admin", user.getModifieParUsername());
- assertEquals(1L, user.getVersion());
- assertEquals("jdupont", user.getUsername());
- assertEquals("jean.dupont@lions.dev", user.getEmail());
- assertTrue(user.getEmailVerified());
- assertEquals("Jean", user.getPrenom());
- assertEquals("Dupont", user.getNom());
- assertEquals(StatutUser.ACTIF, user.getStatut());
- assertTrue(user.getEnabled());
- assertEquals("+225 07 12 34 56 78", user.getTelephone());
- assertEquals("Lions Dev", user.getOrganisation());
- assertEquals("IT", user.getDepartement());
- assertEquals("Developer", user.getFonction());
- assertEquals("Côte d'Ivoire", user.getPays());
- assertEquals("Abidjan", user.getVille());
- assertEquals("fr", user.getLangue());
- assertEquals("Africa/Abidjan", user.getTimezone());
- assertEquals("btpxpress", user.getRealmName());
- assertEquals(2, user.getRealmRoles().size());
- assertEquals(1, user.getClientRoles().size());
- assertEquals(2, user.getGroups().size());
- assertNotNull(user.getDerniereConnexion());
- assertNotNull(user.getDateExpiration());
- assertNull(user.getDateVerrouillage());
- assertEquals(1, user.getAttributes().size());
- assertEquals(1, user.getRequiredActions().size());
- assertEquals("google", user.getFederatedIdentityProvider());
- assertEquals(1, user.getFederatedIdentities().size());
- assertEquals("temp123", user.getTemporaryPassword());
- assertTrue(user.getTemporaryPasswordFlag());
- assertEquals(2, user.getActiveSessions());
- assertEquals(0, user.getFailedLoginAttempts());
- assertEquals("Update", user.getRaisonModification());
- assertEquals("Test user", user.getCommentaires());
- }
-
- @Test
- void testEqualsAndHashCode() {
- UserDTO user1 = UserDTO.builder().id("uuid-123").username("jdupont").build();
- UserDTO user2 = UserDTO.builder().id("uuid-123").username("jdupont").build();
- UserDTO user3 = UserDTO.builder().id("uuid-456").username("other").build();
-
- assertEquals(user1, user2);
- assertEquals(user1.hashCode(), user2.hashCode());
- assertNotEquals(user1, user3);
- }
-
- @Test
- void testToString() {
- UserDTO user = UserDTO.builder().username("jdupont").email("test@test.com").build();
- String str = user.toString();
- assertNotNull(str);
- assertTrue(str.contains("jdupont"));
- assertTrue(str.contains("test@test.com"));
- }
-
- @Test
- void testFederatedIdentityDTO() {
- UserDTO.FederatedIdentityDTO fed = new UserDTO.FederatedIdentityDTO();
- fed.setIdentityProvider("google");
- fed.setUserId("user-123");
- fed.setUserName("user@gmail.com");
-
- assertEquals("google", fed.getIdentityProvider());
- assertEquals("user-123", fed.getUserId());
- assertEquals("user@gmail.com", fed.getUserName());
-
- // Test equals/hashCode/toString
- UserDTO.FederatedIdentityDTO fed2 = UserDTO.FederatedIdentityDTO.builder()
- .identityProvider("google")
- .userId("user-123")
- .userName("user@gmail.com")
- .build();
- assertEquals(fed, fed2);
- assertEquals(fed.hashCode(), fed2.hashCode());
- assertNotNull(fed.toString());
- }
-
- @Test
- void testFederatedIdentityDTO_AllArgsConstructor() {
- UserDTO.FederatedIdentityDTO fed = new UserDTO.FederatedIdentityDTO("google", "user-123", "user@gmail.com");
- assertEquals("google", fed.getIdentityProvider());
- assertEquals("user-123", fed.getUserId());
- assertEquals("user@gmail.com", fed.getUserName());
- }
-
- @Test
- void testNoArgsConstructor() {
- UserDTO user = new UserDTO();
- assertNull(user.getUsername());
- assertNull(user.getEmail());
- }
-
- @Test
- void testAllArgsConstructor() {
- LocalDateTime now = LocalDateTime.now();
- Map> clientRoles = new HashMap<>();
- Map> attributes = new HashMap<>();
- List fedIds = Collections.emptyList();
- List roles = Collections.emptyList();
- List groups = Collections.emptyList();
- List actions = Collections.emptyList();
-
- UserDTO user = new UserDTO(
- "username", "email@test.com", true, "Jean", "Dupont",
- StatutUser.ACTIF, true, "phone", "org", "dept", "func",
- "pays", "ville", "fr", "UTC", "realm", roles, clientRoles,
- groups, now, now, now, attributes, actions, "google", fedIds,
- "temppass", true, 1, 0, "reason", "comments");
-
- assertEquals("username", user.getUsername());
- assertEquals("email@test.com", user.getEmail());
- assertTrue(user.getEmailVerified());
- assertEquals("Jean", user.getPrenom());
- assertEquals("Dupont", user.getNom());
- assertEquals(StatutUser.ACTIF, user.getStatut());
- assertTrue(user.getEnabled());
- }
-}
+package dev.lions.user.manager.dto.user;
+
+import dev.lions.user.manager.enums.user.StatutUser;
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class UserDTOTest {
+
+ @Test
+ void testGetNomComplet_withPrenomAndNom() {
+ UserDTO user = new UserDTO();
+ user.setPrenom("Jean");
+ user.setNom("Dupont");
+ user.setUsername("jdupont");
+ assertEquals("Jean Dupont", user.getNomComplet());
+ }
+
+ @Test
+ void testGetNomComplet_withNullPrenom() {
+ UserDTO user = new UserDTO();
+ user.setPrenom(null);
+ user.setNom("Dupont");
+ user.setUsername("jdupont");
+ assertEquals("jdupont", user.getNomComplet());
+ }
+
+ @Test
+ void testGetNomComplet_withNullNom() {
+ UserDTO user = new UserDTO();
+ user.setPrenom("Jean");
+ user.setNom(null);
+ user.setUsername("jdupont");
+ assertEquals("jdupont", user.getNomComplet());
+ }
+
+ @Test
+ void testGetNomComplet_withBothNull() {
+ UserDTO user = new UserDTO();
+ user.setPrenom(null);
+ user.setNom(null);
+ user.setUsername("jdupont");
+ assertEquals("jdupont", user.getNomComplet());
+ }
+
+ @Test
+ void testIsActif_true() {
+ UserDTO user = new UserDTO();
+ user.setStatut(StatutUser.ACTIF);
+ user.setEnabled(true);
+ assertTrue(user.isActif());
+ }
+
+ @Test
+ void testIsActif_falseWhenNotActif() {
+ UserDTO user = new UserDTO();
+ user.setStatut(StatutUser.INACTIF);
+ user.setEnabled(true);
+ assertFalse(user.isActif());
+ }
+
+ @Test
+ void testIsActif_falseWhenNotEnabled() {
+ UserDTO user = new UserDTO();
+ user.setStatut(StatutUser.ACTIF);
+ user.setEnabled(false);
+ assertFalse(user.isActif());
+ }
+
+ @Test
+ void testIsActif_falseWhenEnabledNull() {
+ UserDTO user = new UserDTO();
+ user.setStatut(StatutUser.ACTIF);
+ user.setEnabled(null);
+ assertFalse(user.isActif());
+ }
+
+ @Test
+ void testIsExpire_true() {
+ UserDTO user = new UserDTO();
+ user.setDateExpiration(LocalDateTime.now().minusDays(1));
+ assertTrue(user.isExpire());
+ }
+
+ @Test
+ void testIsExpire_false() {
+ UserDTO user = new UserDTO();
+ user.setDateExpiration(LocalDateTime.now().plusDays(1));
+ assertFalse(user.isExpire());
+ }
+
+ @Test
+ void testIsExpire_nullDate() {
+ UserDTO user = new UserDTO();
+ user.setDateExpiration(null);
+ assertFalse(user.isExpire());
+ }
+
+ @Test
+ void testHasRequiredActions_true() {
+ UserDTO user = new UserDTO();
+ user.setRequiredActions(Arrays.asList("UPDATE_PASSWORD", "VERIFY_EMAIL"));
+ assertTrue(user.hasRequiredActions());
+ }
+
+ @Test
+ void testHasRequiredActions_empty() {
+ UserDTO user = new UserDTO();
+ user.setRequiredActions(Collections.emptyList());
+ assertFalse(user.hasRequiredActions());
+ }
+
+ @Test
+ void testHasRequiredActions_null() {
+ UserDTO user = new UserDTO();
+ user.setRequiredActions(null);
+ assertFalse(user.hasRequiredActions());
+ }
+
+ @Test
+ void testBuilderAndAllFields() {
+ LocalDateTime now = LocalDateTime.now();
+ Map> clientRoles = new HashMap<>();
+ clientRoles.put("app", Arrays.asList("user", "admin"));
+ Map> attributes = new HashMap<>();
+ attributes.put("custom", Collections.singletonList("value"));
+
+ List fedIds = Collections.singletonList(
+ UserDTO.FederatedIdentityDTO.builder()
+ .identityProvider("google")
+ .userId("google-123")
+ .userName("user@gmail.com")
+ .build());
+
+ UserDTO user = UserDTO.builder()
+ .id("uuid-123")
+ .dateCreation(now)
+ .dateModification(now)
+ .creeParUsername("admin")
+ .modifieParUsername("admin")
+ .version(1L)
+ .username("jdupont")
+ .email("jean.dupont@lions.dev")
+ .emailVerified(true)
+ .prenom("Jean")
+ .nom("Dupont")
+ .statut(StatutUser.ACTIF)
+ .enabled(true)
+ .telephone("+225 07 12 34 56 78")
+ .organisation("Lions Dev")
+ .departement("IT")
+ .fonction("Developer")
+ .pays("Côte d'Ivoire")
+ .ville("Abidjan")
+ .langue("fr")
+ .timezone("Africa/Abidjan")
+ .realmName("btpxpress")
+ .realmRoles(Arrays.asList("user", "admin"))
+ .clientRoles(clientRoles)
+ .groups(Arrays.asList("group1", "group2"))
+ .derniereConnexion(now)
+ .dateExpiration(now.plusYears(1))
+ .dateVerrouillage(null)
+ .attributes(attributes)
+ .requiredActions(Collections.singletonList("UPDATE_PASSWORD"))
+ .federatedIdentityProvider("google")
+ .federatedIdentities(fedIds)
+ .temporaryPassword("temp123")
+ .temporaryPasswordFlag(true)
+ .activeSessions(2)
+ .failedLoginAttempts(0)
+ .raisonModification("Update")
+ .commentaires("Test user")
+ .build();
+
+ assertEquals("uuid-123", user.getId());
+ assertNotNull(user.getDateCreation());
+ assertNotNull(user.getDateModification());
+ assertEquals("admin", user.getCreeParUsername());
+ assertEquals("admin", user.getModifieParUsername());
+ assertEquals(1L, user.getVersion());
+ assertEquals("jdupont", user.getUsername());
+ assertEquals("jean.dupont@lions.dev", user.getEmail());
+ assertTrue(user.getEmailVerified());
+ assertEquals("Jean", user.getPrenom());
+ assertEquals("Dupont", user.getNom());
+ assertEquals(StatutUser.ACTIF, user.getStatut());
+ assertTrue(user.getEnabled());
+ assertEquals("+225 07 12 34 56 78", user.getTelephone());
+ assertEquals("Lions Dev", user.getOrganisation());
+ assertEquals("IT", user.getDepartement());
+ assertEquals("Developer", user.getFonction());
+ assertEquals("Côte d'Ivoire", user.getPays());
+ assertEquals("Abidjan", user.getVille());
+ assertEquals("fr", user.getLangue());
+ assertEquals("Africa/Abidjan", user.getTimezone());
+ assertEquals("btpxpress", user.getRealmName());
+ assertEquals(2, user.getRealmRoles().size());
+ assertEquals(1, user.getClientRoles().size());
+ assertEquals(2, user.getGroups().size());
+ assertNotNull(user.getDerniereConnexion());
+ assertNotNull(user.getDateExpiration());
+ assertNull(user.getDateVerrouillage());
+ assertEquals(1, user.getAttributes().size());
+ assertEquals(1, user.getRequiredActions().size());
+ assertEquals("google", user.getFederatedIdentityProvider());
+ assertEquals(1, user.getFederatedIdentities().size());
+ assertEquals("temp123", user.getTemporaryPassword());
+ assertTrue(user.getTemporaryPasswordFlag());
+ assertEquals(2, user.getActiveSessions());
+ assertEquals(0, user.getFailedLoginAttempts());
+ assertEquals("Update", user.getRaisonModification());
+ assertEquals("Test user", user.getCommentaires());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ UserDTO user1 = UserDTO.builder().id("uuid-123").username("jdupont").build();
+ UserDTO user2 = UserDTO.builder().id("uuid-123").username("jdupont").build();
+ UserDTO user3 = UserDTO.builder().id("uuid-456").username("other").build();
+
+ assertEquals(user1, user2);
+ assertEquals(user1.hashCode(), user2.hashCode());
+ assertNotEquals(user1, user3);
+ }
+
+ @Test
+ void testToString() {
+ UserDTO user = UserDTO.builder().username("jdupont").email("test@test.com").build();
+ String str = user.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("jdupont"));
+ assertTrue(str.contains("test@test.com"));
+ }
+
+ @Test
+ void testFederatedIdentityDTO() {
+ UserDTO.FederatedIdentityDTO fed = new UserDTO.FederatedIdentityDTO();
+ fed.setIdentityProvider("google");
+ fed.setUserId("user-123");
+ fed.setUserName("user@gmail.com");
+
+ assertEquals("google", fed.getIdentityProvider());
+ assertEquals("user-123", fed.getUserId());
+ assertEquals("user@gmail.com", fed.getUserName());
+
+ // Test equals/hashCode/toString
+ UserDTO.FederatedIdentityDTO fed2 = UserDTO.FederatedIdentityDTO.builder()
+ .identityProvider("google")
+ .userId("user-123")
+ .userName("user@gmail.com")
+ .build();
+ assertEquals(fed, fed2);
+ assertEquals(fed.hashCode(), fed2.hashCode());
+ assertNotNull(fed.toString());
+ }
+
+ @Test
+ void testFederatedIdentityDTO_AllArgsConstructor() {
+ UserDTO.FederatedIdentityDTO fed = new UserDTO.FederatedIdentityDTO("google", "user-123", "user@gmail.com");
+ assertEquals("google", fed.getIdentityProvider());
+ assertEquals("user-123", fed.getUserId());
+ assertEquals("user@gmail.com", fed.getUserName());
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ UserDTO user = new UserDTO();
+ assertNull(user.getUsername());
+ assertNull(user.getEmail());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ LocalDateTime now = LocalDateTime.now();
+ Map> clientRoles = new HashMap<>();
+ Map> attributes = new HashMap<>();
+ List fedIds = Collections.emptyList();
+ List roles = Collections.emptyList();
+ List groups = Collections.emptyList();
+ List actions = Collections.emptyList();
+
+ UserDTO user = new UserDTO(
+ "username", "email@test.com", true, "Jean", "Dupont",
+ StatutUser.ACTIF, true, "phone", "org", "dept", "func",
+ "pays", "ville", "fr", "UTC", "realm", roles, clientRoles,
+ groups, now, now, now, attributes, actions, "google", fedIds,
+ "temppass", true, 1, 0, "reason", "comments");
+
+ assertEquals("username", user.getUsername());
+ assertEquals("email@test.com", user.getEmail());
+ assertTrue(user.getEmailVerified());
+ assertEquals("Jean", user.getPrenom());
+ assertEquals("Dupont", user.getNom());
+ assertEquals(StatutUser.ACTIF, user.getStatut());
+ assertTrue(user.getEnabled());
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTOTest.java b/src/test/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTOTest.java
index de5253b..c202dfb 100644
--- a/src/test/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/user/UserSearchCriteriaDTOTest.java
@@ -1,145 +1,145 @@
-package dev.lions.user.manager.dto.user;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour UserSearchCriteriaDTO
- */
-class UserSearchCriteriaDTOTest {
-
- @Test
- void testBuilder() {
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .realmName("test-realm")
- .username("testuser")
- .email("test@example.com")
- .enabled(true)
- .page(0)
- .pageSize(20)
- .build();
-
- assertNotNull(criteria);
- assertEquals("test-realm", criteria.getRealmName());
- assertEquals("testuser", criteria.getUsername());
- assertEquals("test@example.com", criteria.getEmail());
- assertTrue(criteria.getEnabled());
- assertEquals(0, criteria.getPage());
- assertEquals(20, criteria.getPageSize());
- }
-
- @Test
- void testNoArgsConstructor() {
- UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
-
- assertNotNull(criteria);
- assertNull(criteria.getRealmName());
- assertNull(criteria.getUsername());
- assertNull(criteria.getEmail());
- assertNull(criteria.getEnabled());
- }
-
- @Test
- void testAllArgsConstructor() {
- // Le constructeur AllArgsConstructor nécessite tous les champs
- // On utilise plutôt le builder pour ce test
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .realmName("test-realm")
- .username("testuser")
- .email("test@example.com")
- .enabled(true)
- .page(0)
- .pageSize(20)
- .build();
-
- assertNotNull(criteria);
- assertEquals("test-realm", criteria.getRealmName());
- assertEquals("testuser", criteria.getUsername());
- assertEquals("test@example.com", criteria.getEmail());
- assertTrue(criteria.getEnabled());
- assertEquals(0, criteria.getPage());
- assertEquals(20, criteria.getPageSize());
- }
-
- @Test
- void testSettersAndGetters() {
- UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
-
- criteria.setRealmName("realm1");
- criteria.setUsername("user1");
- criteria.setEmail("user1@example.com");
- criteria.setEnabled(false);
- criteria.setPage(1);
- criteria.setPageSize(10);
-
- assertEquals("realm1", criteria.getRealmName());
- assertEquals("user1", criteria.getUsername());
- assertEquals("user1@example.com", criteria.getEmail());
- assertFalse(criteria.getEnabled());
- assertEquals(1, criteria.getPage());
- assertEquals(10, criteria.getPageSize());
- }
-
- @Test
- void testEqualsAndHashCode() {
- UserSearchCriteriaDTO criteria1 = UserSearchCriteriaDTO.builder()
- .realmName("test-realm")
- .username("testuser")
- .build();
-
- UserSearchCriteriaDTO criteria2 = UserSearchCriteriaDTO.builder()
- .realmName("test-realm")
- .username("testuser")
- .build();
-
- assertEquals(criteria1, criteria2);
- assertEquals(criteria1.hashCode(), criteria2.hashCode());
- }
-
- @Test
- void testToString() {
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .realmName("test-realm")
- .username("testuser")
- .build();
-
- String toString = criteria.toString();
- assertNotNull(toString);
- assertTrue(toString.contains("test-realm") || toString.contains("testuser"));
- }
-
- @Test
- void testHasFilters_WithFilters() {
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .username("testuser")
- .enabled(true)
- .build();
-
- assertTrue(criteria.hasFilters());
- }
-
- @Test
- void testHasFilters_NoFilters() {
- UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
-
- assertFalse(criteria.hasFilters());
- }
-
- @Test
- void testGetOffset() {
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(2)
- .pageSize(20)
- .build();
-
- assertEquals(40, criteria.getOffset());
- }
-
- @Test
- void testGetOffset_Default() {
- UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
-
- assertEquals(0, criteria.getOffset());
- }
-}
+package dev.lions.user.manager.dto.user;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour UserSearchCriteriaDTO
+ */
+class UserSearchCriteriaDTOTest {
+
+ @Test
+ void testBuilder() {
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .realmName("test-realm")
+ .username("testuser")
+ .email("test@example.com")
+ .enabled(true)
+ .page(0)
+ .pageSize(20)
+ .build();
+
+ assertNotNull(criteria);
+ assertEquals("test-realm", criteria.getRealmName());
+ assertEquals("testuser", criteria.getUsername());
+ assertEquals("test@example.com", criteria.getEmail());
+ assertTrue(criteria.getEnabled());
+ assertEquals(0, criteria.getPage());
+ assertEquals(20, criteria.getPageSize());
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
+
+ assertNotNull(criteria);
+ assertNull(criteria.getRealmName());
+ assertNull(criteria.getUsername());
+ assertNull(criteria.getEmail());
+ assertNull(criteria.getEnabled());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ // Le constructeur AllArgsConstructor nécessite tous les champs
+ // On utilise plutôt le builder pour ce test
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .realmName("test-realm")
+ .username("testuser")
+ .email("test@example.com")
+ .enabled(true)
+ .page(0)
+ .pageSize(20)
+ .build();
+
+ assertNotNull(criteria);
+ assertEquals("test-realm", criteria.getRealmName());
+ assertEquals("testuser", criteria.getUsername());
+ assertEquals("test@example.com", criteria.getEmail());
+ assertTrue(criteria.getEnabled());
+ assertEquals(0, criteria.getPage());
+ assertEquals(20, criteria.getPageSize());
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
+
+ criteria.setRealmName("realm1");
+ criteria.setUsername("user1");
+ criteria.setEmail("user1@example.com");
+ criteria.setEnabled(false);
+ criteria.setPage(1);
+ criteria.setPageSize(10);
+
+ assertEquals("realm1", criteria.getRealmName());
+ assertEquals("user1", criteria.getUsername());
+ assertEquals("user1@example.com", criteria.getEmail());
+ assertFalse(criteria.getEnabled());
+ assertEquals(1, criteria.getPage());
+ assertEquals(10, criteria.getPageSize());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ UserSearchCriteriaDTO criteria1 = UserSearchCriteriaDTO.builder()
+ .realmName("test-realm")
+ .username("testuser")
+ .build();
+
+ UserSearchCriteriaDTO criteria2 = UserSearchCriteriaDTO.builder()
+ .realmName("test-realm")
+ .username("testuser")
+ .build();
+
+ assertEquals(criteria1, criteria2);
+ assertEquals(criteria1.hashCode(), criteria2.hashCode());
+ }
+
+ @Test
+ void testToString() {
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .realmName("test-realm")
+ .username("testuser")
+ .build();
+
+ String toString = criteria.toString();
+ assertNotNull(toString);
+ assertTrue(toString.contains("test-realm") || toString.contains("testuser"));
+ }
+
+ @Test
+ void testHasFilters_WithFilters() {
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .username("testuser")
+ .enabled(true)
+ .build();
+
+ assertTrue(criteria.hasFilters());
+ }
+
+ @Test
+ void testHasFilters_NoFilters() {
+ UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
+
+ assertFalse(criteria.hasFilters());
+ }
+
+ @Test
+ void testGetOffset() {
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(2)
+ .pageSize(20)
+ .build();
+
+ assertEquals(40, criteria.getOffset());
+ }
+
+ @Test
+ void testGetOffset_Default() {
+ UserSearchCriteriaDTO criteria = new UserSearchCriteriaDTO();
+
+ assertEquals(0, criteria.getOffset());
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/dto/user/UserSearchResultDTOTest.java b/src/test/java/dev/lions/user/manager/dto/user/UserSearchResultDTOTest.java
index b68480c..2fb9c6a 100644
--- a/src/test/java/dev/lions/user/manager/dto/user/UserSearchResultDTOTest.java
+++ b/src/test/java/dev/lions/user/manager/dto/user/UserSearchResultDTOTest.java
@@ -1,279 +1,279 @@
-package dev.lions.user.manager.dto.user;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class UserSearchResultDTOTest {
-
- @Test
- void testOf_firstPage() {
- List users = Arrays.asList(
- UserDTO.builder().username("user1").build(),
- UserDTO.builder().username("user2").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(0)
- .pageSize(10)
- .build();
-
- UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 25L);
-
- assertEquals(2, result.getUsers().size());
- assertEquals(25L, result.getTotalCount());
- assertEquals(0, result.getCurrentPage());
- assertEquals(10, result.getPageSize());
- assertEquals(3, result.getTotalPages());
- assertTrue(result.getHasNextPage());
- assertFalse(result.getHasPreviousPage());
- assertEquals(0, result.getFirstElement());
- assertEquals(9, result.getLastElement());
- assertFalse(result.getIsEmpty());
- assertTrue(result.getIsFirstPage());
- assertFalse(result.getIsLastPage());
- assertEquals(criteria, result.getCriteria());
- }
-
- @Test
- void testOf_middlePage() {
- List users = Arrays.asList(
- UserDTO.builder().username("user1").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(1)
- .pageSize(10)
- .build();
-
- UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 25L);
-
- assertEquals(1, result.getCurrentPage());
- assertTrue(result.getHasNextPage());
- assertTrue(result.getHasPreviousPage());
- assertFalse(result.getIsFirstPage());
- assertFalse(result.getIsLastPage());
- }
-
- @Test
- void testOf_lastPage() {
- List users = Arrays.asList(
- UserDTO.builder().username("user1").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(2)
- .pageSize(10)
- .build();
-
- UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 25L);
-
- assertEquals(2, result.getCurrentPage());
- assertFalse(result.getHasNextPage());
- assertTrue(result.getHasPreviousPage());
- assertFalse(result.getIsFirstPage());
- assertTrue(result.getIsLastPage());
- }
-
- @Test
- void testOf_emptyList() {
- List users = Collections.emptyList();
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(0)
- .pageSize(20)
- .build();
-
- UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 0L);
-
- assertTrue(result.getIsEmpty());
- assertEquals(0, result.getTotalCount());
- assertEquals(0, result.getTotalPages());
- }
-
- @Test
- void testOf_nullList() {
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(0)
- .pageSize(20)
- .build();
-
- UserSearchResultDTO result = UserSearchResultDTO.of(null, criteria, 0L);
-
- assertTrue(result.getIsEmpty());
- }
-
- @Test
- void testOf_singlePage() {
- List users = Arrays.asList(
- UserDTO.builder().username("user1").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
- .page(0)
- .pageSize(10)
- .build();
-
- UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 5L);
-
- assertEquals(1, result.getTotalPages());
- assertFalse(result.getHasNextPage());
- assertFalse(result.getHasPreviousPage());
- assertTrue(result.getIsFirstPage());
- assertTrue(result.getIsLastPage());
- }
-
- @Test
- void testGetCurrentPageSize_withUsers() {
- UserSearchResultDTO result = UserSearchResultDTO.builder()
- .users(Arrays.asList(
- UserDTO.builder().username("u1").build(),
- UserDTO.builder().username("u2").build(),
- UserDTO.builder().username("u3").build()))
- .build();
-
- assertEquals(3, result.getCurrentPageSize());
- }
-
- @Test
- void testGetCurrentPageSize_emptyUsers() {
- UserSearchResultDTO result = UserSearchResultDTO.builder()
- .users(Collections.emptyList())
- .build();
-
- assertEquals(0, result.getCurrentPageSize());
- }
-
- @Test
- void testGetCurrentPageSize_nullUsers() {
- UserSearchResultDTO result = UserSearchResultDTO.builder()
- .users(null)
- .build();
-
- assertEquals(0, result.getCurrentPageSize());
- }
-
- @Test
- void testBuilderAndAllFields() {
- List users = Collections.singletonList(UserDTO.builder().username("test").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder().page(0).pageSize(20).build();
-
- UserSearchResultDTO result = UserSearchResultDTO.builder()
- .users(users)
- .totalCount(100L)
- .currentPage(0)
- .pageSize(20)
- .totalPages(5)
- .hasNextPage(true)
- .hasPreviousPage(false)
- .firstElement(0)
- .lastElement(19)
- .isEmpty(false)
- .isFirstPage(true)
- .isLastPage(false)
- .criteria(criteria)
- .executionTimeMs(150L)
- .build();
-
- assertEquals(users, result.getUsers());
- assertEquals(100L, result.getTotalCount());
- assertEquals(0, result.getCurrentPage());
- assertEquals(20, result.getPageSize());
- assertEquals(5, result.getTotalPages());
- assertTrue(result.getHasNextPage());
- assertFalse(result.getHasPreviousPage());
- assertEquals(0, result.getFirstElement());
- assertEquals(19, result.getLastElement());
- assertFalse(result.getIsEmpty());
- assertTrue(result.getIsFirstPage());
- assertFalse(result.getIsLastPage());
- assertEquals(criteria, result.getCriteria());
- assertEquals(150L, result.getExecutionTimeMs());
- }
-
- @Test
- void testSettersAndGetters() {
- UserSearchResultDTO result = new UserSearchResultDTO();
- List users = Collections.singletonList(UserDTO.builder().username("test").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder().build();
-
- result.setUsers(users);
- result.setTotalCount(50L);
- result.setCurrentPage(1);
- result.setPageSize(10);
- result.setTotalPages(5);
- result.setHasNextPage(true);
- result.setHasPreviousPage(true);
- result.setFirstElement(10);
- result.setLastElement(19);
- result.setIsEmpty(false);
- result.setIsFirstPage(false);
- result.setIsLastPage(false);
- result.setCriteria(criteria);
- result.setExecutionTimeMs(200L);
-
- assertEquals(users, result.getUsers());
- assertEquals(50L, result.getTotalCount());
- assertEquals(1, result.getCurrentPage());
- assertEquals(10, result.getPageSize());
- assertEquals(5, result.getTotalPages());
- assertTrue(result.getHasNextPage());
- assertTrue(result.getHasPreviousPage());
- assertEquals(10, result.getFirstElement());
- assertEquals(19, result.getLastElement());
- assertFalse(result.getIsEmpty());
- assertFalse(result.getIsFirstPage());
- assertFalse(result.getIsLastPage());
- assertEquals(criteria, result.getCriteria());
- assertEquals(200L, result.getExecutionTimeMs());
- }
-
- @Test
- void testEqualsAndHashCode() {
- UserSearchResultDTO dto1 = UserSearchResultDTO.builder().totalCount(10L).currentPage(0).build();
- UserSearchResultDTO dto2 = UserSearchResultDTO.builder().totalCount(10L).currentPage(0).build();
- UserSearchResultDTO dto3 = UserSearchResultDTO.builder().totalCount(20L).currentPage(1).build();
-
- assertEquals(dto1, dto2);
- assertEquals(dto1.hashCode(), dto2.hashCode());
- assertNotEquals(dto1, dto3);
- }
-
- @Test
- void testToString() {
- UserSearchResultDTO result = UserSearchResultDTO.builder()
- .totalCount(100L)
- .currentPage(0)
- .build();
- String str = result.toString();
- assertNotNull(str);
- assertTrue(str.contains("100"));
- }
-
- @Test
- void testNoArgsConstructor() {
- UserSearchResultDTO result = new UserSearchResultDTO();
- assertNull(result.getUsers());
- assertNull(result.getTotalCount());
- assertNull(result.getCurrentPage());
- }
-
- @Test
- void testAllArgsConstructor() {
- List users = Collections.singletonList(UserDTO.builder().username("test").build());
- UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder().build();
-
- UserSearchResultDTO result = new UserSearchResultDTO(
- users, 100L, 0, 20, 5, true, false, 0, 19, false, true, false, criteria, 150L);
-
- assertEquals(users, result.getUsers());
- assertEquals(100L, result.getTotalCount());
- assertEquals(0, result.getCurrentPage());
- assertEquals(20, result.getPageSize());
- assertEquals(5, result.getTotalPages());
- assertTrue(result.getHasNextPage());
- assertFalse(result.getHasPreviousPage());
- assertEquals(0, result.getFirstElement());
- assertEquals(19, result.getLastElement());
- assertFalse(result.getIsEmpty());
- assertTrue(result.getIsFirstPage());
- assertFalse(result.getIsLastPage());
- assertEquals(criteria, result.getCriteria());
- assertEquals(150L, result.getExecutionTimeMs());
- }
-}
+package dev.lions.user.manager.dto.user;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class UserSearchResultDTOTest {
+
+ @Test
+ void testOf_firstPage() {
+ List users = Arrays.asList(
+ UserDTO.builder().username("user1").build(),
+ UserDTO.builder().username("user2").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(0)
+ .pageSize(10)
+ .build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 25L);
+
+ assertEquals(2, result.getUsers().size());
+ assertEquals(25L, result.getTotalCount());
+ assertEquals(0, result.getCurrentPage());
+ assertEquals(10, result.getPageSize());
+ assertEquals(3, result.getTotalPages());
+ assertTrue(result.getHasNextPage());
+ assertFalse(result.getHasPreviousPage());
+ assertEquals(0, result.getFirstElement());
+ assertEquals(9, result.getLastElement());
+ assertFalse(result.getIsEmpty());
+ assertTrue(result.getIsFirstPage());
+ assertFalse(result.getIsLastPage());
+ assertEquals(criteria, result.getCriteria());
+ }
+
+ @Test
+ void testOf_middlePage() {
+ List users = Arrays.asList(
+ UserDTO.builder().username("user1").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(1)
+ .pageSize(10)
+ .build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 25L);
+
+ assertEquals(1, result.getCurrentPage());
+ assertTrue(result.getHasNextPage());
+ assertTrue(result.getHasPreviousPage());
+ assertFalse(result.getIsFirstPage());
+ assertFalse(result.getIsLastPage());
+ }
+
+ @Test
+ void testOf_lastPage() {
+ List users = Arrays.asList(
+ UserDTO.builder().username("user1").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(2)
+ .pageSize(10)
+ .build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 25L);
+
+ assertEquals(2, result.getCurrentPage());
+ assertFalse(result.getHasNextPage());
+ assertTrue(result.getHasPreviousPage());
+ assertFalse(result.getIsFirstPage());
+ assertTrue(result.getIsLastPage());
+ }
+
+ @Test
+ void testOf_emptyList() {
+ List users = Collections.emptyList();
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(0)
+ .pageSize(20)
+ .build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 0L);
+
+ assertTrue(result.getIsEmpty());
+ assertEquals(0, result.getTotalCount());
+ assertEquals(0, result.getTotalPages());
+ }
+
+ @Test
+ void testOf_nullList() {
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(0)
+ .pageSize(20)
+ .build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.of(null, criteria, 0L);
+
+ assertTrue(result.getIsEmpty());
+ }
+
+ @Test
+ void testOf_singlePage() {
+ List users = Arrays.asList(
+ UserDTO.builder().username("user1").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
+ .page(0)
+ .pageSize(10)
+ .build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.of(users, criteria, 5L);
+
+ assertEquals(1, result.getTotalPages());
+ assertFalse(result.getHasNextPage());
+ assertFalse(result.getHasPreviousPage());
+ assertTrue(result.getIsFirstPage());
+ assertTrue(result.getIsLastPage());
+ }
+
+ @Test
+ void testGetCurrentPageSize_withUsers() {
+ UserSearchResultDTO result = UserSearchResultDTO.builder()
+ .users(Arrays.asList(
+ UserDTO.builder().username("u1").build(),
+ UserDTO.builder().username("u2").build(),
+ UserDTO.builder().username("u3").build()))
+ .build();
+
+ assertEquals(3, result.getCurrentPageSize());
+ }
+
+ @Test
+ void testGetCurrentPageSize_emptyUsers() {
+ UserSearchResultDTO result = UserSearchResultDTO.builder()
+ .users(Collections.emptyList())
+ .build();
+
+ assertEquals(0, result.getCurrentPageSize());
+ }
+
+ @Test
+ void testGetCurrentPageSize_nullUsers() {
+ UserSearchResultDTO result = UserSearchResultDTO.builder()
+ .users(null)
+ .build();
+
+ assertEquals(0, result.getCurrentPageSize());
+ }
+
+ @Test
+ void testBuilderAndAllFields() {
+ List users = Collections.singletonList(UserDTO.builder().username("test").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder().page(0).pageSize(20).build();
+
+ UserSearchResultDTO result = UserSearchResultDTO.builder()
+ .users(users)
+ .totalCount(100L)
+ .currentPage(0)
+ .pageSize(20)
+ .totalPages(5)
+ .hasNextPage(true)
+ .hasPreviousPage(false)
+ .firstElement(0)
+ .lastElement(19)
+ .isEmpty(false)
+ .isFirstPage(true)
+ .isLastPage(false)
+ .criteria(criteria)
+ .executionTimeMs(150L)
+ .build();
+
+ assertEquals(users, result.getUsers());
+ assertEquals(100L, result.getTotalCount());
+ assertEquals(0, result.getCurrentPage());
+ assertEquals(20, result.getPageSize());
+ assertEquals(5, result.getTotalPages());
+ assertTrue(result.getHasNextPage());
+ assertFalse(result.getHasPreviousPage());
+ assertEquals(0, result.getFirstElement());
+ assertEquals(19, result.getLastElement());
+ assertFalse(result.getIsEmpty());
+ assertTrue(result.getIsFirstPage());
+ assertFalse(result.getIsLastPage());
+ assertEquals(criteria, result.getCriteria());
+ assertEquals(150L, result.getExecutionTimeMs());
+ }
+
+ @Test
+ void testSettersAndGetters() {
+ UserSearchResultDTO result = new UserSearchResultDTO();
+ List users = Collections.singletonList(UserDTO.builder().username("test").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder().build();
+
+ result.setUsers(users);
+ result.setTotalCount(50L);
+ result.setCurrentPage(1);
+ result.setPageSize(10);
+ result.setTotalPages(5);
+ result.setHasNextPage(true);
+ result.setHasPreviousPage(true);
+ result.setFirstElement(10);
+ result.setLastElement(19);
+ result.setIsEmpty(false);
+ result.setIsFirstPage(false);
+ result.setIsLastPage(false);
+ result.setCriteria(criteria);
+ result.setExecutionTimeMs(200L);
+
+ assertEquals(users, result.getUsers());
+ assertEquals(50L, result.getTotalCount());
+ assertEquals(1, result.getCurrentPage());
+ assertEquals(10, result.getPageSize());
+ assertEquals(5, result.getTotalPages());
+ assertTrue(result.getHasNextPage());
+ assertTrue(result.getHasPreviousPage());
+ assertEquals(10, result.getFirstElement());
+ assertEquals(19, result.getLastElement());
+ assertFalse(result.getIsEmpty());
+ assertFalse(result.getIsFirstPage());
+ assertFalse(result.getIsLastPage());
+ assertEquals(criteria, result.getCriteria());
+ assertEquals(200L, result.getExecutionTimeMs());
+ }
+
+ @Test
+ void testEqualsAndHashCode() {
+ UserSearchResultDTO dto1 = UserSearchResultDTO.builder().totalCount(10L).currentPage(0).build();
+ UserSearchResultDTO dto2 = UserSearchResultDTO.builder().totalCount(10L).currentPage(0).build();
+ UserSearchResultDTO dto3 = UserSearchResultDTO.builder().totalCount(20L).currentPage(1).build();
+
+ assertEquals(dto1, dto2);
+ assertEquals(dto1.hashCode(), dto2.hashCode());
+ assertNotEquals(dto1, dto3);
+ }
+
+ @Test
+ void testToString() {
+ UserSearchResultDTO result = UserSearchResultDTO.builder()
+ .totalCount(100L)
+ .currentPage(0)
+ .build();
+ String str = result.toString();
+ assertNotNull(str);
+ assertTrue(str.contains("100"));
+ }
+
+ @Test
+ void testNoArgsConstructor() {
+ UserSearchResultDTO result = new UserSearchResultDTO();
+ assertNull(result.getUsers());
+ assertNull(result.getTotalCount());
+ assertNull(result.getCurrentPage());
+ }
+
+ @Test
+ void testAllArgsConstructor() {
+ List users = Collections.singletonList(UserDTO.builder().username("test").build());
+ UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder().build();
+
+ UserSearchResultDTO result = new UserSearchResultDTO(
+ users, 100L, 0, 20, 5, true, false, 0, 19, false, true, false, criteria, 150L);
+
+ assertEquals(users, result.getUsers());
+ assertEquals(100L, result.getTotalCount());
+ assertEquals(0, result.getCurrentPage());
+ assertEquals(20, result.getPageSize());
+ assertEquals(5, result.getTotalPages());
+ assertTrue(result.getHasNextPage());
+ assertFalse(result.getHasPreviousPage());
+ assertEquals(0, result.getFirstElement());
+ assertEquals(19, result.getLastElement());
+ assertFalse(result.getIsEmpty());
+ assertTrue(result.getIsFirstPage());
+ assertFalse(result.getIsLastPage());
+ assertEquals(criteria, result.getCriteria());
+ assertEquals(150L, result.getExecutionTimeMs());
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/enums/audit/TypeActionAuditTest.java b/src/test/java/dev/lions/user/manager/enums/audit/TypeActionAuditTest.java
index ea615b2..020bc26 100644
--- a/src/test/java/dev/lions/user/manager/enums/audit/TypeActionAuditTest.java
+++ b/src/test/java/dev/lions/user/manager/enums/audit/TypeActionAuditTest.java
@@ -1,59 +1,59 @@
-package dev.lions.user.manager.enums.audit;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour TypeActionAudit
- */
-class TypeActionAuditTest {
-
- @Test
- void testValues() {
- TypeActionAudit[] values = TypeActionAudit.values();
-
- assertNotNull(values);
- assertTrue(values.length > 0);
- }
-
- @Test
- void testValueOf() {
- TypeActionAudit userCreate = TypeActionAudit.valueOf("USER_CREATE");
- TypeActionAudit userUpdate = TypeActionAudit.valueOf("USER_UPDATE");
- TypeActionAudit userDelete = TypeActionAudit.valueOf("USER_DELETE");
- TypeActionAudit roleCreate = TypeActionAudit.valueOf("ROLE_CREATE");
- TypeActionAudit roleUpdate = TypeActionAudit.valueOf("ROLE_UPDATE");
- TypeActionAudit roleDelete = TypeActionAudit.valueOf("ROLE_DELETE");
- TypeActionAudit roleAssign = TypeActionAudit.valueOf("ROLE_ASSIGN");
- TypeActionAudit roleRevoke = TypeActionAudit.valueOf("ROLE_REVOKE");
-
- assertEquals(TypeActionAudit.USER_CREATE, userCreate);
- assertEquals(TypeActionAudit.USER_UPDATE, userUpdate);
- assertEquals(TypeActionAudit.USER_DELETE, userDelete);
- assertEquals(TypeActionAudit.ROLE_CREATE, roleCreate);
- assertEquals(TypeActionAudit.ROLE_UPDATE, roleUpdate);
- assertEquals(TypeActionAudit.ROLE_DELETE, roleDelete);
- assertEquals(TypeActionAudit.ROLE_ASSIGN, roleAssign);
- assertEquals(TypeActionAudit.ROLE_REVOKE, roleRevoke);
- }
-
- @Test
- void testValueOf_Invalid() {
- assertThrows(IllegalArgumentException.class, () -> {
- TypeActionAudit.valueOf("INVALID");
- });
- }
-
- @Test
- void testEnumValues() {
- assertNotNull(TypeActionAudit.USER_CREATE);
- assertNotNull(TypeActionAudit.USER_UPDATE);
- assertNotNull(TypeActionAudit.USER_DELETE);
- assertNotNull(TypeActionAudit.ROLE_CREATE);
- assertNotNull(TypeActionAudit.ROLE_UPDATE);
- assertNotNull(TypeActionAudit.ROLE_DELETE);
- assertNotNull(TypeActionAudit.ROLE_ASSIGN);
- assertNotNull(TypeActionAudit.ROLE_REVOKE);
- }
-}
+package dev.lions.user.manager.enums.audit;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour TypeActionAudit
+ */
+class TypeActionAuditTest {
+
+ @Test
+ void testValues() {
+ TypeActionAudit[] values = TypeActionAudit.values();
+
+ assertNotNull(values);
+ assertTrue(values.length > 0);
+ }
+
+ @Test
+ void testValueOf() {
+ TypeActionAudit userCreate = TypeActionAudit.valueOf("USER_CREATE");
+ TypeActionAudit userUpdate = TypeActionAudit.valueOf("USER_UPDATE");
+ TypeActionAudit userDelete = TypeActionAudit.valueOf("USER_DELETE");
+ TypeActionAudit roleCreate = TypeActionAudit.valueOf("ROLE_CREATE");
+ TypeActionAudit roleUpdate = TypeActionAudit.valueOf("ROLE_UPDATE");
+ TypeActionAudit roleDelete = TypeActionAudit.valueOf("ROLE_DELETE");
+ TypeActionAudit roleAssign = TypeActionAudit.valueOf("ROLE_ASSIGN");
+ TypeActionAudit roleRevoke = TypeActionAudit.valueOf("ROLE_REVOKE");
+
+ assertEquals(TypeActionAudit.USER_CREATE, userCreate);
+ assertEquals(TypeActionAudit.USER_UPDATE, userUpdate);
+ assertEquals(TypeActionAudit.USER_DELETE, userDelete);
+ assertEquals(TypeActionAudit.ROLE_CREATE, roleCreate);
+ assertEquals(TypeActionAudit.ROLE_UPDATE, roleUpdate);
+ assertEquals(TypeActionAudit.ROLE_DELETE, roleDelete);
+ assertEquals(TypeActionAudit.ROLE_ASSIGN, roleAssign);
+ assertEquals(TypeActionAudit.ROLE_REVOKE, roleRevoke);
+ }
+
+ @Test
+ void testValueOf_Invalid() {
+ assertThrows(IllegalArgumentException.class, () -> {
+ TypeActionAudit.valueOf("INVALID");
+ });
+ }
+
+ @Test
+ void testEnumValues() {
+ assertNotNull(TypeActionAudit.USER_CREATE);
+ assertNotNull(TypeActionAudit.USER_UPDATE);
+ assertNotNull(TypeActionAudit.USER_DELETE);
+ assertNotNull(TypeActionAudit.ROLE_CREATE);
+ assertNotNull(TypeActionAudit.ROLE_UPDATE);
+ assertNotNull(TypeActionAudit.ROLE_DELETE);
+ assertNotNull(TypeActionAudit.ROLE_ASSIGN);
+ assertNotNull(TypeActionAudit.ROLE_REVOKE);
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/enums/role/TypeRoleTest.java b/src/test/java/dev/lions/user/manager/enums/role/TypeRoleTest.java
index 706497f..5ca7b9d 100644
--- a/src/test/java/dev/lions/user/manager/enums/role/TypeRoleTest.java
+++ b/src/test/java/dev/lions/user/manager/enums/role/TypeRoleTest.java
@@ -1,41 +1,41 @@
-package dev.lions.user.manager.enums.role;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour TypeRole
- */
-class TypeRoleTest {
-
- @Test
- void testValues() {
- TypeRole[] values = TypeRole.values();
-
- assertNotNull(values);
- assertTrue(values.length > 0);
- }
-
- @Test
- void testValueOf() {
- TypeRole realmRole = TypeRole.valueOf("REALM_ROLE");
- TypeRole clientRole = TypeRole.valueOf("CLIENT_ROLE");
-
- assertEquals(TypeRole.REALM_ROLE, realmRole);
- assertEquals(TypeRole.CLIENT_ROLE, clientRole);
- }
-
- @Test
- void testValueOf_Invalid() {
- assertThrows(IllegalArgumentException.class, () -> {
- TypeRole.valueOf("INVALID");
- });
- }
-
- @Test
- void testEnumValues() {
- assertNotNull(TypeRole.REALM_ROLE);
- assertNotNull(TypeRole.CLIENT_ROLE);
- }
-}
+package dev.lions.user.manager.enums.role;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour TypeRole
+ */
+class TypeRoleTest {
+
+ @Test
+ void testValues() {
+ TypeRole[] values = TypeRole.values();
+
+ assertNotNull(values);
+ assertTrue(values.length > 0);
+ }
+
+ @Test
+ void testValueOf() {
+ TypeRole realmRole = TypeRole.valueOf("REALM_ROLE");
+ TypeRole clientRole = TypeRole.valueOf("CLIENT_ROLE");
+
+ assertEquals(TypeRole.REALM_ROLE, realmRole);
+ assertEquals(TypeRole.CLIENT_ROLE, clientRole);
+ }
+
+ @Test
+ void testValueOf_Invalid() {
+ assertThrows(IllegalArgumentException.class, () -> {
+ TypeRole.valueOf("INVALID");
+ });
+ }
+
+ @Test
+ void testEnumValues() {
+ assertNotNull(TypeRole.REALM_ROLE);
+ assertNotNull(TypeRole.CLIENT_ROLE);
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/enums/user/StatutUserTest.java b/src/test/java/dev/lions/user/manager/enums/user/StatutUserTest.java
index 16e98ad..15ca4d4 100644
--- a/src/test/java/dev/lions/user/manager/enums/user/StatutUserTest.java
+++ b/src/test/java/dev/lions/user/manager/enums/user/StatutUserTest.java
@@ -1,44 +1,44 @@
-package dev.lions.user.manager.enums.user;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Tests unitaires pour StatutUser
- */
-class StatutUserTest {
-
- @Test
- void testValues() {
- StatutUser[] values = StatutUser.values();
-
- assertNotNull(values);
- assertTrue(values.length > 0);
- }
-
- @Test
- void testValueOf() {
- StatutUser actif = StatutUser.valueOf("ACTIF");
- StatutUser inactif = StatutUser.valueOf("INACTIF");
- StatutUser suspendu = StatutUser.valueOf("SUSPENDU");
-
- assertEquals(StatutUser.ACTIF, actif);
- assertEquals(StatutUser.INACTIF, inactif);
- assertEquals(StatutUser.SUSPENDU, suspendu);
- }
-
- @Test
- void testValueOf_Invalid() {
- assertThrows(IllegalArgumentException.class, () -> {
- StatutUser.valueOf("INVALID");
- });
- }
-
- @Test
- void testEnumValues() {
- assertNotNull(StatutUser.ACTIF);
- assertNotNull(StatutUser.INACTIF);
- assertNotNull(StatutUser.SUSPENDU);
- }
-}
+package dev.lions.user.manager.enums.user;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Tests unitaires pour StatutUser
+ */
+class StatutUserTest {
+
+ @Test
+ void testValues() {
+ StatutUser[] values = StatutUser.values();
+
+ assertNotNull(values);
+ assertTrue(values.length > 0);
+ }
+
+ @Test
+ void testValueOf() {
+ StatutUser actif = StatutUser.valueOf("ACTIF");
+ StatutUser inactif = StatutUser.valueOf("INACTIF");
+ StatutUser suspendu = StatutUser.valueOf("SUSPENDU");
+
+ assertEquals(StatutUser.ACTIF, actif);
+ assertEquals(StatutUser.INACTIF, inactif);
+ assertEquals(StatutUser.SUSPENDU, suspendu);
+ }
+
+ @Test
+ void testValueOf_Invalid() {
+ assertThrows(IllegalArgumentException.class, () -> {
+ StatutUser.valueOf("INVALID");
+ });
+ }
+
+ @Test
+ void testEnumValues() {
+ assertNotNull(StatutUser.ACTIF);
+ assertNotNull(StatutUser.INACTIF);
+ assertNotNull(StatutUser.SUSPENDU);
+ }
+}
diff --git a/src/test/java/dev/lions/user/manager/validation/ValidationConstantsTest.java b/src/test/java/dev/lions/user/manager/validation/ValidationConstantsTest.java
index 282b798..b126bed 100644
--- a/src/test/java/dev/lions/user/manager/validation/ValidationConstantsTest.java
+++ b/src/test/java/dev/lions/user/manager/validation/ValidationConstantsTest.java
@@ -1,18 +1,18 @@
-package dev.lions.user.manager.validation;
-
-import org.junit.jupiter.api.Test;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import static org.junit.jupiter.api.Assertions.*;
-
-class ValidationConstantsTest {
-
- @Test
- void testPrivateConstructor() throws Exception {
- Constructor constructor = ValidationConstants.class.getDeclaredConstructor();
- assertTrue(Modifier.isPrivate(constructor.getModifiers()));
- constructor.setAccessible(true);
- ValidationConstants instance = constructor.newInstance();
- assertNotNull(instance);
- }
-}
+package dev.lions.user.manager.validation;
+
+import org.junit.jupiter.api.Test;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import static org.junit.jupiter.api.Assertions.*;
+
+class ValidationConstantsTest {
+
+ @Test
+ void testPrivateConstructor() throws Exception {
+ Constructor constructor = ValidationConstants.class.getDeclaredConstructor();
+ assertTrue(Modifier.isPrivate(constructor.getModifiers()));
+ constructor.setAccessible(true);
+ ValidationConstants instance = constructor.newInstance();
+ assertNotNull(instance);
+ }
+}