Initial commit

This commit is contained in:
dahoud
2025-10-01 01:37:34 +00:00
commit f2bb633142
310 changed files with 86051 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
package dev.lions.btpxpress.adapter.http;
import jakarta.annotation.security.PermitAll;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
import java.security.Principal;
import java.util.Map;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Resource REST pour l'authentification et les informations utilisateur
* Permet de récupérer les informations de l'utilisateur connecté depuis le token JWT Keycloak
*/
@Path("/api/v1/auth")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Authentification", description = "Gestion de l'authentification et informations utilisateur")
public class AuthResource {
private static final Logger logger = LoggerFactory.getLogger(AuthResource.class);
@Inject
JsonWebToken jwt;
/**
* Récupère les informations de l'utilisateur connecté depuis le token JWT
*/
@GET
@Path("/user")
@PermitAll // Accessible même sans authentification pour les tests
@Operation(
summary = "Informations utilisateur connecté",
description = "Récupère les informations de l'utilisateur connecté depuis le token JWT Keycloak")
@APIResponse(responseCode = "200", description = "Informations utilisateur récupérées")
@APIResponse(responseCode = "401", description = "Non authentifié")
public Response getCurrentUser(@Context SecurityContext securityContext) {
try {
logger.debug("Récupération des informations utilisateur connecté");
// Vérifier si l'utilisateur est authentifié
Principal principal = securityContext.getUserPrincipal();
if (principal == null || jwt == null) {
logger.warn("Aucun utilisateur authentifié trouvé");
// En mode développement, retourner un utilisateur de test
return Response.ok(createTestUser()).build();
}
// Extraire les informations du token JWT
String userId = jwt.getSubject();
String username = jwt.getClaim("preferred_username");
String email = jwt.getClaim("email");
String firstName = jwt.getClaim("given_name");
String lastName = jwt.getClaim("family_name");
String fullName = jwt.getClaim("name");
// Extraire les rôles
Object realmAccess = jwt.getClaim("realm_access");
Object resourceAccess = jwt.getClaim("resource_access");
// Construire la réponse avec les informations utilisateur
Map<String, Object> userInfo = new java.util.HashMap<>();
userInfo.put("id", userId != null ? userId : "unknown");
userInfo.put("username", username != null ? username : email);
userInfo.put("email", email != null ? email : "unknown@btpxpress.com");
userInfo.put("firstName", firstName != null ? firstName : "Utilisateur");
userInfo.put("lastName", lastName != null ? lastName : "Connecté");
userInfo.put("fullName", fullName != null ? fullName : (firstName + " " + lastName).trim());
userInfo.put("roles", extractRoles(realmAccess, resourceAccess));
userInfo.put("permissions", extractPermissions(realmAccess, resourceAccess));
userInfo.put("isAdmin", isAdmin(realmAccess, resourceAccess));
userInfo.put("isManager", isManager(realmAccess, resourceAccess));
userInfo.put("isEmployee", isEmployee(realmAccess, resourceAccess));
userInfo.put("isClient", isClient(realmAccess, resourceAccess));
logger.info("Informations utilisateur récupérées: {} ({})", username, email);
return Response.ok(userInfo).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des informations utilisateur", e);
// En cas d'erreur, retourner un utilisateur de test en mode développement
return Response.ok(createTestUser()).build();
}
}
/**
* Endpoint de test pour vérifier l'état de l'authentification
*/
@GET
@Path("/status")
@PermitAll
@Operation(
summary = "Statut d'authentification",
description = "Vérifie l'état de l'authentification de l'utilisateur")
@APIResponse(responseCode = "200", description = "Statut récupéré")
public Response getAuthStatus(@Context SecurityContext securityContext) {
try {
Principal principal = securityContext.getUserPrincipal();
boolean isAuthenticated = principal != null && jwt != null;
Map<String, Object> status = Map.of(
"authenticated", isAuthenticated,
"principal", principal != null ? principal.getName() : null,
"hasJWT", jwt != null,
"timestamp", System.currentTimeMillis()
);
return Response.ok(status).build();
} catch (Exception e) {
logger.error("Erreur lors de la vérification du statut d'authentification", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la vérification du statut"))
.build();
}
}
/**
* Crée un utilisateur de test pour le mode développement
*/
private Map<String, Object> createTestUser() {
Map<String, Object> testUser = new java.util.HashMap<>();
testUser.put("id", "dev-user-001");
testUser.put("username", "admin.btpxpress");
testUser.put("email", "admin@btpxpress.com");
testUser.put("firstName", "Jean-Michel");
testUser.put("lastName", "Martineau");
testUser.put("fullName", "Jean-Michel Martineau");
testUser.put("roles", java.util.List.of("SUPER_ADMIN", "ADMIN", "DIRECTEUR"));
testUser.put("permissions", java.util.List.of("ALL_PERMISSIONS"));
testUser.put("isAdmin", true);
testUser.put("isManager", true);
testUser.put("isEmployee", false);
testUser.put("isClient", false);
return testUser;
}
/**
* Extrait les rôles depuis les claims JWT
*/
private java.util.List<String> extractRoles(Object realmAccess, Object resourceAccess) {
java.util.List<String> roles = new java.util.ArrayList<>();
// Ajouter les rôles du realm
if (realmAccess instanceof Map) {
Object realmRoles = ((Map<?, ?>) realmAccess).get("roles");
if (realmRoles instanceof java.util.List) {
((java.util.List<?>) realmRoles).forEach(role -> {
if (role instanceof String) {
roles.add((String) role);
}
});
}
}
// Ajouter les rôles des ressources
if (resourceAccess instanceof Map) {
((Map<?, ?>) resourceAccess).values().forEach(resource -> {
if (resource instanceof Map) {
Object resourceRoles = ((Map<?, ?>) resource).get("roles");
if (resourceRoles instanceof java.util.List) {
((java.util.List<?>) resourceRoles).forEach(role -> {
if (role instanceof String) {
roles.add((String) role);
}
});
}
}
});
}
return roles.isEmpty() ? java.util.List.of("USER") : roles;
}
/**
* Extrait les permissions depuis les rôles
*/
private java.util.List<String> extractPermissions(Object realmAccess, Object resourceAccess) {
java.util.List<String> roles = extractRoles(realmAccess, resourceAccess);
java.util.List<String> permissions = new java.util.ArrayList<>();
// Mapper les rôles vers les permissions
for (String role : roles) {
switch (role.toUpperCase()) {
case "SUPER_ADMIN":
case "BTPXPRESS_SUPER_ADMIN":
permissions.add("ALL_PERMISSIONS");
break;
case "ADMIN":
case "BTPXPRESS_ADMIN":
permissions.addAll(java.util.List.of("MANAGE_USERS", "MANAGE_CHANTIERS", "MANAGE_CLIENTS"));
break;
case "DIRECTEUR":
case "MANAGER":
permissions.addAll(java.util.List.of("VIEW_REPORTS", "MANAGE_CHANTIERS"));
break;
case "CHEF_CHANTIER":
permissions.addAll(java.util.List.of("MANAGE_CHANTIER", "VIEW_PLANNING"));
break;
default:
permissions.add("VIEW_BASIC");
break;
}
}
return permissions.isEmpty() ? java.util.List.of("VIEW_BASIC") : permissions;
}
/**
* Vérifie si l'utilisateur est administrateur
*/
private boolean isAdmin(Object realmAccess, Object resourceAccess) {
java.util.List<String> roles = extractRoles(realmAccess, resourceAccess);
return roles.stream().anyMatch(role ->
role.toUpperCase().contains("ADMIN") || role.toUpperCase().contains("SUPER_ADMIN"));
}
/**
* Vérifie si l'utilisateur est manager
*/
private boolean isManager(Object realmAccess, Object resourceAccess) {
java.util.List<String> roles = extractRoles(realmAccess, resourceAccess);
return roles.stream().anyMatch(role ->
role.toUpperCase().contains("DIRECTEUR") ||
role.toUpperCase().contains("MANAGER") ||
role.toUpperCase().contains("CHEF"));
}
/**
* Vérifie si l'utilisateur est employé
*/
private boolean isEmployee(Object realmAccess, Object resourceAccess) {
java.util.List<String> roles = extractRoles(realmAccess, resourceAccess);
return roles.stream().anyMatch(role ->
role.toUpperCase().contains("EMPLOYE") ||
role.toUpperCase().contains("OUVRIER"));
}
/**
* Vérifie si l'utilisateur est client
*/
private boolean isClient(Object realmAccess, Object resourceAccess) {
java.util.List<String> roles = extractRoles(realmAccess, resourceAccess);
return roles.stream().anyMatch(role ->
role.toUpperCase().contains("CLIENT"));
}
}