chore(quarkus-327): bump to Quarkus 3.27.3 LTS, make pom autonomous, bump to 1.1.0, add maven-compiler-plugin version

This commit is contained in:
2026-04-23 14:47:04 +00:00
parent 5b33384e9f
commit e40bebd120
58 changed files with 6124 additions and 6080 deletions

228
.gitignore vendored
View File

@@ -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/

248
README.md
View File

@@ -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
<dependency>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-server-api</artifactId>
<version>1.0.0</version>
</dependency>
```
```xml
<repositories>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</repository>
</repositories>
```
---
## 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
<dependency>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-server-api</artifactId>
<version>1.0.0</version>
</dependency>
```
```xml
<repositories>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</repository>
</repositories>
```
---
## 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

View File

@@ -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

View File

@@ -1,265 +1,266 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Lions User Manager - Parent</name>
<description>Module de gestion centralisée des utilisateurs via Keycloak Admin API</description>
<distributionManagement>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</repository>
<snapshotRepository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Quarkus & Dependencies -->
<quarkus.version>3.20.0</quarkus.version>
<quarkus-primefaces.version>3.15.1</quarkus-primefaces.version>
<primefaces.version>14.0.5</primefaces.version>
<primefaces-freya-extension.version>1.0.0</primefaces-freya-extension.version>
<keycloak.version>26.0.7</keycloak.version>
<lombok.version>1.18.36</lombok.version>
<mapstruct.version>1.6.3</mapstruct.version>
<!-- Testing -->
<junit.version>5.11.4</junit.version>
<mockito.version>5.14.2</mockito.version>
<testcontainers.version>1.20.6</testcontainers.version>
<rest-assured.version>5.5.0</rest-assured.version>
<!-- Plugins -->
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version>
<jacoco-maven-plugin.version>0.8.12</jacoco-maven-plugin.version>
</properties>
<modules>
<module>lions-user-manager-server-api</module>
<module>lions-user-manager-server-impl-quarkus</module>
<module>lions-user-manager-client-quarkus-primefaces-freya</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- Quarkus BOM -->
<dependency>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Internal modules -->
<dependency>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-server-api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- PrimeFaces Freya Extension -->
<dependency>
<groupId>dev.lions</groupId>
<artifactId>primefaces-freya-extension</artifactId>
<version>${primefaces-freya-extension.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- MapStruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<quarkus.profile>dev</quarkus.profile>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<quarkus.profile>prod</quarkus.profile>
</properties>
</profile>
<profile>
<id>native</id>
<properties>
<quarkus.profile>prod</quarkus.profile>
<quarkus.package.jar.type>native</quarkus.package.jar.type>
</properties>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-parent</artifactId>
<version>1.1.0</version>
<packaging>pom</packaging>
<name>Lions User Manager - Parent</name>
<description>Module de gestion centralisée des utilisateurs via Keycloak Admin API</description>
<distributionManagement>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</repository>
<snapshotRepository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Quarkus & Dependencies — 3.27.3 LTS (Testcontainers 1.21.3, Hibernate ORM 7.0) -->
<quarkus.version>3.27.3</quarkus.version>
<quarkus-primefaces.version>3.15.1</quarkus-primefaces.version>
<primefaces.version>14.0.5</primefaces.version>
<primefaces-freya-extension.version>1.0.0</primefaces-freya-extension.version>
<keycloak.version>26.0.7</keycloak.version>
<lombok.version>1.18.38</lombok.version>
<mapstruct.version>1.6.3</mapstruct.version>
<!-- Testing — overrides BOM (BOM bundles TC 1.21.3 / docker-java 3.4.2) -->
<junit.version>5.11.4</junit.version>
<mockito.version>5.14.2</mockito.version>
<testcontainers.version>1.21.4</testcontainers.version>
<docker-java.version>3.4.2</docker-java.version>
<rest-assured.version>5.5.0</rest-assured.version>
<!-- Plugins -->
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version>
<jacoco-maven-plugin.version>0.8.12</jacoco-maven-plugin.version>
</properties>
<modules>
<module>lions-user-manager-server-api</module>
<module>lions-user-manager-server-impl-quarkus</module>
<module>lions-user-manager-client-quarkus-primefaces-freya</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- Quarkus BOM -->
<dependency>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Internal modules -->
<dependency>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-server-api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- PrimeFaces Freya Extension -->
<dependency>
<groupId>dev.lions</groupId>
<artifactId>primefaces-freya-extension</artifactId>
<version>${primefaces-freya-extension.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- MapStruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>${rest-assured.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<quarkus.profile>dev</quarkus.profile>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<quarkus.profile>prod</quarkus.profile>
</properties>
</profile>
<profile>
<id>native</id>
<properties>
<quarkus.profile>prod</quarkus.profile>
<quarkus.package.jar.type>native</quarkus.package.jar.type>
</properties>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

225
pom.xml
View File

@@ -1,91 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>lions-user-manager-server-api</artifactId>
<packaging>jar</packaging>
<name>Lions User Manager - Server API</name>
<description>Contrats API: DTOs, interfaces de services, enums et validations</description>
<dependencies>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Jakarta EE APIs -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
</dependency>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<!-- OpenAPI annotations -->
<dependency>
<groupId>org.eclipse.microprofile.openapi</groupId>
<artifactId>microprofile-openapi-api</artifactId>
</dependency>
<!-- Quarkus Runtime API (pour @RegisterForReflection) -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>21</release>
</configuration>
</plugin>
<!-- Jandex Maven Plugin pour générer l'index Jandex -->
<plugin>
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.lions.user.manager</groupId>
<version>1.1.0</version>
<properties>
<java.version>21</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<quarkus.platform.version>3.27.3</quarkus.platform.version>
<lombok.version>1.18.38</lombok.version>
</properties>
<artifactId>lions-user-manager-server-api</artifactId>
<packaging>jar</packaging>
<name>Lions User Manager - Server API</name>
<description>Contrats API: DTOs, interfaces de services, enums et validations</description>
<distributionManagement>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>gitea-lionsdev</id>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<!-- Quarkus BOM : gère Jakarta, Jackson, MicroProfile OpenAPI, quarkus-core, JUnit -->
<dependency>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Lombok : pas dans Quarkus BOM -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Jakarta EE APIs -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
</dependency>
<!-- Jackson for JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<!-- OpenAPI annotations -->
<dependency>
<groupId>org.eclipse.microprofile.openapi</groupId>
<artifactId>microprofile-openapi-api</artifactId>
</dependency>
<!-- Quarkus Runtime API (pour @RegisterForReflection) -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- Testing -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>21</release>
</configuration>
</plugin>
<!-- Jandex Maven Plugin pour générer l'index Jandex -->
<plugin>
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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

View File

@@ -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"

View File

@@ -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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<TypeActionAudit, Long> 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<String, Long> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<TypeActionAudit, Long> 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<String, Long> 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);
}

View File

@@ -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<RealmAssignmentDTO> getAllAssignments();
@GET
@Path("/user/{userId}")
@Operation(summary = "Affectations par utilisateur", description = "Liste les realms assignés à un utilisateur")
List<RealmAssignmentDTO> 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<RealmAssignmentDTO> 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<RealmAssignmentDTO> getAllAssignments();
@GET
@Path("/user/{userId}")
@Operation(summary = "Affectations par utilisateur", description = "Liste les realms assignés à un utilisateur")
List<RealmAssignmentDTO> 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<RealmAssignmentDTO> 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);
}

View File

@@ -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<String> 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<String> 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<String> 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<String> getRealmClients(
@Parameter(description = "Nom du realm") @PathParam("realm") String realmName);
}

View File

@@ -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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> getComposites(
@PathParam("roleName") String roleName,
@QueryParam("realm") String realmName);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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<String> 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<String> 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);
}

View File

@@ -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<String, String> 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<String, String> 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
);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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<ImportErrorDTO> 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<ImportErrorDTO> 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
}
}

View File

@@ -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<String> 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<String> realms;
@Schema(description = "L'utilisateur est super admin")
private boolean isSuperAdmin;
}

View File

@@ -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;
}

View File

@@ -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)" : ""
);
}
}

View File

@@ -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<String> roleNames;
@Schema(description = "Liste des IDs de rôles à attribuer ou révoquer")
private List<String> 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<String> roleNames;
@Schema(description = "Liste des IDs de rôles à attribuer ou révoquer")
private List<String> 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;
}
}

View File

@@ -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<String> 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<String> roleNames;
}

View File

@@ -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<String> compositeRoles;
@Schema(description = "Rôles Realm composites")
private List<RoleCompositeDTO> compositeRealmRoles;
@Schema(description = "Rôles Client composites par client")
private Map<String, List<RoleCompositeDTO>> compositeClientRoles;
@Schema(description = "Attributs personnalisés du rôle")
private Map<String, List<String>> 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<String> compositeRoles;
@Schema(description = "Rôles Realm composites")
private List<RoleCompositeDTO> compositeRealmRoles;
@Schema(description = "Rôles Client composites par client")
private Map<String, List<RoleCompositeDTO>> compositeClientRoles;
@Schema(description = "Attributs personnalisés du rôle")
private Map<String, List<String>> 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;
}
}

View File

@@ -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;
}

View File

@@ -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<String> missingUsersInLocal;
private Set<String> missingUsersInKeycloak;
private Integer rolesKeycloakCount;
private Integer rolesLocalCount;
private Set<String> missingRolesInLocal;
private Set<String> 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<String> missingUsersInLocal;
private Set<String> missingUsersInKeycloak;
private Integer rolesKeycloakCount;
private Integer rolesLocalCount;
private Set<String> missingRolesInLocal;
private Set<String> missingRolesInKeycloak;
private String error;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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<String> realmRoles;
@Schema(description = "Liste des rôles Client assignés")
private Map<String, List<String>> clientRoles;
@Schema(description = "Liste des groupes auxquels appartient l'utilisateur")
private List<String> 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<String, List<String>> attributes;
// Actions requises
@Schema(description = "Actions requises (ex: UPDATE_PASSWORD, VERIFY_EMAIL)")
private List<String> 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<FederatedIdentityDTO> 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<String> realmRoles;
@Schema(description = "Liste des rôles Client assignés")
private Map<String, List<String>> clientRoles;
@Schema(description = "Liste des groupes auxquels appartient l'utilisateur")
private List<String> 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<String, List<String>> attributes;
// Actions requises
@Schema(description = "Actions requises (ex: UPDATE_PASSWORD, VERIFY_EMAIL)")
private List<String> 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<FederatedIdentityDTO> 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;
}
}

View File

@@ -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<String> realmRoles;
@Schema(description = "Liste des rôles Client à filtrer")
private List<String> clientRoles;
@Schema(description = "Liste des groupes à filtrer")
private List<String> 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<String> realmRoles;
@Schema(description = "Liste des rôles Client à filtrer")
private List<String> clientRoles;
@Schema(description = "Liste des groupes à filtrer")
private List<String> 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;
}
}

View File

@@ -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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<TypeActionAudit, Long> 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<String, Long> 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<String, Long> 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<String, Object> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<AuditLogDTO> 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<TypeActionAudit, Long> 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<String, Long> 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<String, Long> 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<String, Object> getAuditStatistics(@NotBlank String realmName,
LocalDateTime dateDebut,
LocalDateTime dateFin);
}

View File

@@ -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<RealmAssignmentDTO> 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<RealmAssignmentDTO> 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<RealmAssignmentDTO> getAssignmentsByRealm(@NotBlank String realmName);
/**
* Récupère une assignation spécifique
* @param assignmentId ID de l'assignation
* @return assignation ou Optional vide
*/
Optional<RealmAssignmentDTO> 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<String> 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<RealmAssignmentDTO> 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<RealmAssignmentDTO> 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<RealmAssignmentDTO> getAssignmentsByRealm(@NotBlank String realmName);
/**
* Récupère une assignation spécifique
* @param assignmentId ID de l'assignation
* @return assignation ou Optional vide
*/
Optional<RealmAssignmentDTO> 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<String> 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);
}

View File

@@ -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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<String> 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<String> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<RoleDTO> 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<String> 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<String> 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<RoleDTO> 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);
}

View File

@@ -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<String, Integer> 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<String, Object> checkDataConsistency(@NotBlank String realmName);
/**
* Force la resynchronisation complète d'un realm
* @param realmName nom du realm
* @return statistiques de synchronisation
*/
Map<String, Object> forceSyncRealm(@NotBlank String realmName);
/**
* Récupère le statut de la dernière synchronisation
* @param realmName nom du realm
* @return statut de synchronisation
*/
Map<String, Object> 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<String, Object> 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<String, Integer> 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<String, Object> checkDataConsistency(@NotBlank String realmName);
/**
* Force la resynchronisation complète d'un realm
* @param realmName nom du realm
* @return statistiques de synchronisation
*/
Map<String, Object> forceSyncRealm(@NotBlank String realmName);
/**
* Récupère le statut de la dernière synchronisation
* @param realmName nom du realm
* @return statut de synchronisation
*/
Map<String, Object> 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<String, Object> getKeycloakHealthInfo();
}

View File

@@ -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<UserDTO> 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<UserDTO> 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<UserDTO> 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<String> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<String> 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);
}

View File

@@ -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";
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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"));
}
}

View File

@@ -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<String> 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<String> 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);
}
}

View File

@@ -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<String, List<RoleDTO.RoleCompositeDTO>> 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<String, List<String>> attrs = new HashMap<>();
attrs.put("key", Collections.singletonList("value"));
Map<String, List<RoleDTO.RoleCompositeDTO>> 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<String, List<String>> attrs = new HashMap<>();
Map<String, List<RoleDTO.RoleCompositeDTO>> clientComposites = new HashMap<>();
List<String> compositeRoles = Collections.emptyList();
List<RoleDTO.RoleCompositeDTO> 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<String, List<RoleDTO.RoleCompositeDTO>> 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<String, List<String>> attrs = new HashMap<>();
attrs.put("key", Collections.singletonList("value"));
Map<String, List<RoleDTO.RoleCompositeDTO>> 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<String, List<String>> attrs = new HashMap<>();
Map<String, List<RoleDTO.RoleCompositeDTO>> clientComposites = new HashMap<>();
List<String> compositeRoles = Collections.emptyList();
List<RoleDTO.RoleCompositeDTO> 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());
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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<String, List<String>> clientRoles = new HashMap<>();
clientRoles.put("app", Arrays.asList("user", "admin"));
Map<String, List<String>> attributes = new HashMap<>();
attributes.put("custom", Collections.singletonList("value"));
List<UserDTO.FederatedIdentityDTO> 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<String, List<String>> clientRoles = new HashMap<>();
Map<String, List<String>> attributes = new HashMap<>();
List<UserDTO.FederatedIdentityDTO> fedIds = Collections.emptyList();
List<String> roles = Collections.emptyList();
List<String> groups = Collections.emptyList();
List<String> 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<String, List<String>> clientRoles = new HashMap<>();
clientRoles.put("app", Arrays.asList("user", "admin"));
Map<String, List<String>> attributes = new HashMap<>();
attributes.put("custom", Collections.singletonList("value"));
List<UserDTO.FederatedIdentityDTO> 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<String, List<String>> clientRoles = new HashMap<>();
Map<String, List<String>> attributes = new HashMap<>();
List<UserDTO.FederatedIdentityDTO> fedIds = Collections.emptyList();
List<String> roles = Collections.emptyList();
List<String> groups = Collections.emptyList();
List<String> 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());
}
}

View File

@@ -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());
}
}

View File

@@ -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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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<UserDTO> 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());
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<ValidationConstants> 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<ValidationConstants> constructor = ValidationConstants.class.getDeclaredConstructor();
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
constructor.setAccessible(true);
ValidationConstants instance = constructor.newInstance();
assertNotNull(instance);
}
}