- Nouveau MembreRoleSyncService.ensureOrgAdminRole : auto-crée un MembreRole ORGADMIN quand un user avec rôle Keycloak ADMIN_ORGANISATION se connecte sans entrée DB (couvre les comptes créés directement dans Keycloak). - OrganisationContextFilter appelle syncService.ensureOrgAdminRole quand le rôle Keycloak est présent mais MembreRole absent (non bloquant sur erreur). - MembreRoleRepository.countAdminsByOrganisationId : count strict (ORGADMIN + actif + dateDebut/dateFin valides) avec fallback sur codes alternatifs si strict=0. - OrganisationService.convertToResponse : nombreAdministrateurs dynamique via MembreRoleRepository (remplace le champ Organisation jamais mis à jour).
83 lines
3.0 KiB
Java
83 lines
3.0 KiB
Java
package dev.lions.unionflow.server.service;
|
|
|
|
import dev.lions.unionflow.server.entity.MembreOrganisation;
|
|
import dev.lions.unionflow.server.entity.MembreRole;
|
|
import dev.lions.unionflow.server.repository.MembreRoleRepository;
|
|
import dev.lions.unionflow.server.repository.RoleRepository;
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.persistence.EntityManager;
|
|
import jakarta.persistence.PersistenceContext;
|
|
import jakarta.transaction.Transactional;
|
|
import java.time.LocalDate;
|
|
import org.jboss.logging.Logger;
|
|
|
|
/**
|
|
* Synchronise le rôle DB (MembreRole) avec le rôle Keycloak au premier accès.
|
|
*
|
|
* <p>Lorsqu'un utilisateur est admin dans Keycloak (rôle {@code ADMIN_ORGANISATION})
|
|
* mais n'a pas encore de ligne {@code MembreRole ORGADMIN} en base, ce service la
|
|
* crée à la volée. Cela couvre deux cas :
|
|
* <ol>
|
|
* <li>Comptes créés directement dans Keycloak sans passer par
|
|
* {@code MembreService#promouvoirAdminOrganisation}.</li>
|
|
* <li>Bases de données en dev qui ont démarré avant la migration V30.</li>
|
|
* </ol>
|
|
*/
|
|
@ApplicationScoped
|
|
public class MembreRoleSyncService {
|
|
|
|
private static final Logger LOG = Logger.getLogger(MembreRoleSyncService.class);
|
|
|
|
@Inject
|
|
MembreRoleRepository membreRoleRepository;
|
|
|
|
@Inject
|
|
RoleRepository roleRepository;
|
|
|
|
@PersistenceContext
|
|
EntityManager entityManager;
|
|
|
|
/**
|
|
* Assure qu'un MembreRole ORGADMIN existe pour ce MembreOrganisation.
|
|
* Idempotent : sans effet si l'entrée existe déjà.
|
|
*
|
|
* @param mo MembreOrganisation de l'admin (non null)
|
|
*/
|
|
@Transactional
|
|
public void ensureOrgAdminRole(MembreOrganisation mo) {
|
|
if (mo == null || mo.getId() == null || mo.getOrganisation() == null) {
|
|
return;
|
|
}
|
|
|
|
// Vérifier si un MembreRole ORGADMIN actif existe déjà pour ce membre dans cette org
|
|
long existing = membreRoleRepository.count(
|
|
"membreOrganisation.id = ?1 AND role.code = ?2 AND actif = true",
|
|
mo.getId(), "ORGADMIN");
|
|
|
|
if (existing > 0) {
|
|
return; // Déjà en place — rien à faire
|
|
}
|
|
|
|
// Chercher le rôle ORGADMIN dans la table roles
|
|
roleRepository.findByCode("ORGADMIN").ifPresentOrElse(
|
|
role -> {
|
|
MembreRole mr = new MembreRole();
|
|
mr.setMembreOrganisation(mo);
|
|
mr.setOrganisation(mo.getOrganisation());
|
|
mr.setRole(role);
|
|
mr.setActif(true);
|
|
mr.setDateDebut(LocalDate.now());
|
|
entityManager.persist(mr);
|
|
LOG.infof(
|
|
"MembreRole ORGADMIN auto-sync créé pour membre %s dans org %s",
|
|
mo.getMembre() != null ? mo.getMembre().getId() : "?",
|
|
mo.getOrganisation().getId());
|
|
},
|
|
() -> LOG.warnf(
|
|
"Rôle ORGADMIN introuvable dans la table roles — "
|
|
+ "vérifier que V13__Seed_Standard_Roles.sql a été appliqué")
|
|
);
|
|
}
|
|
}
|