Initial commit
This commit is contained in:
258
src/main/java/dev/lions/btpxpress/adapter/http/AuthResource.java
Normal file
258
src/main/java/dev/lions/btpxpress/adapter/http/AuthResource.java
Normal 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"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user