package dev.lions.unionflow.server.entity; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import java.util.ArrayList; import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; /** * Entité Permission pour la gestion des permissions granulaires * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @Entity @Table( name = "permissions", indexes = { @Index(name = "idx_permission_code", columnList = "code", unique = true), @Index(name = "idx_permission_module", columnList = "module"), @Index(name = "idx_permission_ressource", columnList = "ressource") }) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = true) public class Permission extends BaseEntity { /** Code unique de la permission (format: MODULE > RESSOURCE > ACTION) */ @NotBlank @Column(name = "code", unique = true, nullable = false, length = 100) private String code; /** Module (ex: ORGANISATION, MEMBRE, COTISATION) */ @NotBlank @Column(name = "module", nullable = false, length = 50) private String module; /** Ressource (ex: MEMBRE, COTISATION, ADHESION) */ @NotBlank @Column(name = "ressource", nullable = false, length = 50) private String ressource; /** Action (ex: CREATE, READ, UPDATE, DELETE, VALIDATE) */ @NotBlank @Column(name = "action", nullable = false, length = 50) private String action; /** Libellé de la permission */ @Column(name = "libelle", length = 200) private String libelle; /** Description de la permission */ @Column(name = "description", length = 500) private String description; /** Rôles associés */ @OneToMany(mappedBy = "permission", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @Builder.Default private List roles = new ArrayList<>(); /** Méthode métier pour générer le code à partir des composants */ public static String genererCode(String module, String ressource, String action) { return String.format("%s > %s > %s", module.toUpperCase(), ressource.toUpperCase(), action.toUpperCase()); } /** Méthode métier pour vérifier si le code est valide */ public boolean isCodeValide() { return code != null && code.contains(" > ") && code.split(" > ").length == 3; } /** Callback JPA avant la persistance */ @PrePersist protected void onCreate() { super.onCreate(); // Générer le code si non fourni if (code == null || code.isEmpty()) { if (module != null && ressource != null && action != null) { code = genererCode(module, ressource, action); } } } }