package dev.lions.btpxpress.adapter.http; import dev.lions.btpxpress.application.service.PermissionService; import dev.lions.btpxpress.domain.core.entity.Permission; import dev.lions.btpxpress.domain.core.entity.Permission.PermissionCategory; import dev.lions.btpxpress.domain.core.entity.UserRole; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * API REST pour la gestion des permissions EXPOSITION: Consultation des droits d'accès et * permissions par rôle */ @Path("/api/permissions") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class PermissionResource { private static final Logger logger = LoggerFactory.getLogger(PermissionResource.class); @Inject PermissionService permissionService; // === ENDPOINTS DE CONSULTATION === /** Récupère toutes les permissions disponibles */ @GET @Path("/all") public Response getAllPermissions() { try { logger.debug("GET /api/permissions/all"); List permissions = Arrays.stream(Permission.values()) .map( p -> Map.of( "code", p.getCode(), "description", p.getDescription(), "category", p.getCategory().name(), "categoryDisplay", p.getCategory().getDisplayName())) .collect(Collectors.toList()); return Response.ok(permissions).build(); } catch (Exception e) { logger.error("Erreur lors de la récupération des permissions", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la récupération des permissions: " + e.getMessage()) .build(); } } /** Récupère les permissions par catégorie */ @GET @Path("/categories") public Response getPermissionsByCategory() { try { logger.debug("GET /api/permissions/categories"); Map result = Arrays.stream(PermissionCategory.values()) .collect( Collectors.toMap( category -> category.name(), category -> Map.of( "displayName", category.getDisplayName(), "permissions", Permission.getByCategory(category).stream() .map( p -> Map.of( "code", p.getCode(), "description", p.getDescription())) .collect(Collectors.toList())))); return Response.ok(result).build(); } catch (Exception e) { logger.error("Erreur lors de la récupération des permissions par catégorie", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la récupération des permissions: " + e.getMessage()) .build(); } } /** Récupère les permissions d'un rôle spécifique */ @GET @Path("/role/{role}") public Response getPermissionsByRole(@PathParam("role") String roleStr) { try { logger.debug("GET /api/permissions/role/{}", roleStr); UserRole role = UserRole.valueOf(roleStr.toUpperCase()); Map summary = permissionService.getPermissionSummary(role); return Response.ok(summary).build(); } catch (IllegalArgumentException e) { return Response.status(Response.Status.BAD_REQUEST) .entity("Rôle invalide: " + roleStr) .build(); } catch (Exception e) { logger.error("Erreur lors de la récupération des permissions pour le rôle: " + roleStr, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la récupération des permissions: " + e.getMessage()) .build(); } } /** Vérifie si un rôle a une permission spécifique */ @GET @Path("/check/{role}/{permission}") public Response checkPermission( @PathParam("role") String roleStr, @PathParam("permission") String permissionCode) { try { logger.debug("GET /api/permissions/check/{}/{}", roleStr, permissionCode); UserRole role = UserRole.valueOf(roleStr.toUpperCase()); boolean hasPermission = permissionService.hasPermission(role, permissionCode); return Response.ok( Map.of( "role", role.getDisplayName(), "permission", permissionCode, "hasPermission", hasPermission)) .build(); } catch (IllegalArgumentException e) { return Response.status(Response.Status.BAD_REQUEST) .entity("Rôle invalide: " + roleStr) .build(); } catch (Exception e) { logger.error("Erreur lors de la vérification de permission", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la vérification de permission: " + e.getMessage()) .build(); } } /** Récupère tous les rôles avec leurs permissions */ @GET @Path("/roles") public Response getAllRolesWithPermissions() { try { logger.debug("GET /api/permissions/roles"); Map result = Arrays.stream(UserRole.values()) .collect( Collectors.toMap( role -> role.name(), role -> Map.of( "displayName", role.getDisplayName(), "description", role.getDescription(), "hierarchyLevel", role.getHierarchyLevel(), "isManagementRole", role.isManagementRole(), "isFieldRole", role.isFieldRole(), "isAdministrativeRole", role.isAdministrativeRole(), "permissions", permissionService.getPermissions(role).stream() .map(Permission::getCode) .collect(Collectors.toList()), "permissionCount", permissionService.getPermissions(role).size()))); return Response.ok(result).build(); } catch (Exception e) { logger.error("Erreur lors de la récupération des rôles et permissions", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la récupération des rôles: " + e.getMessage()) .build(); } } /** Compare les permissions entre deux rôles */ @GET @Path("/compare/{role1}/{role2}") public Response compareRoles( @PathParam("role1") String role1Str, @PathParam("role2") String role2Str) { try { logger.debug("GET /api/permissions/compare/{}/{}", role1Str, role2Str); UserRole role1 = UserRole.valueOf(role1Str.toUpperCase()); UserRole role2 = UserRole.valueOf(role2Str.toUpperCase()); Set permissions1 = permissionService.getPermissions(role1); Set permissions2 = permissionService.getPermissions(role2); Set missing1to2 = permissionService.getMissingPermissions(role1, role2); Set missing2to1 = permissionService.getMissingPermissions(role2, role1); Set common = permissions1.stream().filter(permissions2::contains).collect(Collectors.toSet()); return Response.ok( Map.of( "role1", Map.of( "name", role1.getDisplayName(), "permissionCount", permissions1.size(), "permissions", permissions1.stream() .map(Permission::getCode) .collect(Collectors.toList())), "role2", Map.of( "name", role2.getDisplayName(), "permissionCount", permissions2.size(), "permissions", permissions2.stream() .map(Permission::getCode) .collect(Collectors.toList())), "common", Map.of( "count", common.size(), "permissions", common.stream() .map(Permission::getCode) .collect(Collectors.toList())), "onlyInRole1", Map.of( "count", missing2to1.size(), "permissions", missing2to1.stream() .map(Permission::getCode) .collect(Collectors.toList())), "onlyInRole2", Map.of( "count", missing1to2.size(), "permissions", missing1to2.stream() .map(Permission::getCode) .collect(Collectors.toList())))) .build(); } catch (IllegalArgumentException e) { return Response.status(Response.Status.BAD_REQUEST).entity("Rôle invalide").build(); } catch (Exception e) { logger.error("Erreur lors de la comparaison des rôles", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la comparaison: " + e.getMessage()) .build(); } } /** Récupère les permissions spécifiques au gestionnaire de projet */ @GET @Path("/gestionnaire") public Response getGestionnairePermissions() { try { logger.debug("GET /api/permissions/gestionnaire"); UserRole gestionnaireRole = UserRole.GESTIONNAIRE_PROJET; Map summary = permissionService.getPermissionSummary(gestionnaireRole); // Ajout d'informations spécifiques au gestionnaire Map> byCategory = permissionService.getPermissionsByCategory(gestionnaireRole); return Response.ok( Map.of( "role", gestionnaireRole.getDisplayName(), "description", gestionnaireRole.getDescription(), "summary", summary, "specificities", Map.of( "clientManagement", "Gestion limitée aux clients assignés", "projectScope", "Chantiers et projets sous sa responsabilité uniquement", "budgetAccess", "Consultation et planification budgétaire", "materialReservation", "Réservation de matériel pour ses chantiers", "reportingLevel", "Rapports et statistiques de ses projets"), "categoriesDetails", byCategory.entrySet().stream() .collect( Collectors.toMap( entry -> entry.getKey().getDisplayName(), entry -> entry.getValue().stream() .map( p -> Map.of( "code", p.getCode(), "description", p.getDescription())) .collect(Collectors.toList()))))) .build(); } catch (Exception e) { logger.error("Erreur lors de la récupération des permissions gestionnaire", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la récupération des permissions: " + e.getMessage()) .build(); } } /** Valide les permissions requises pour une fonctionnalité */ @POST @Path("/validate") public Response validatePermissions(ValidationRequest request) { try { logger.debug("POST /api/permissions/validate"); UserRole role = UserRole.valueOf(request.role.toUpperCase()); Set requiredPermissions = request.requiredPermissions.stream() .map(Permission::fromCode) .collect(Collectors.toSet()); boolean hasMinimum = permissionService.hasMinimumPermissions(role, requiredPermissions); Map permissionChecks = request.requiredPermissions.stream() .collect( Collectors.toMap( code -> code, code -> permissionService.hasPermission(role, code))); return Response.ok( Map.of( "role", role.getDisplayName(), "hasMinimumPermissions", hasMinimum, "permissionChecks", permissionChecks, "missingPermissions", request.requiredPermissions.stream() .filter(code -> !permissionService.hasPermission(role, code)) .collect(Collectors.toList()))) .build(); } catch (Exception e) { logger.error("Erreur lors de la validation des permissions", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Erreur lors de la validation: " + e.getMessage()) .build(); } } // === CLASSES DE REQUÊTE === public static class ValidationRequest { public String role; public List requiredPermissions; } }