package fr.titionfire.ffsaf.domain.service; import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.data.repository.ClubRepository; import fr.titionfire.ffsaf.data.repository.CombRepository; import fr.titionfire.ffsaf.net2.ServerCustom; import fr.titionfire.ffsaf.net2.data.SimpleCombModel; import fr.titionfire.ffsaf.net2.request.SReqComb; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.from.ClubMemberForm; import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.PageResult; import fr.titionfire.ffsaf.utils.Pair; import fr.titionfire.ffsaf.utils.RoleAsso; import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.PanacheQuery; import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.quarkus.panache.common.Page; import io.quarkus.panache.common.Sort; import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.vertx.VertxContextSupport; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.ForbiddenException; import org.eclipse.microprofile.jwt.JsonWebToken; @WithSession @ApplicationScoped public class MembreService { @Inject CombRepository repository; @Inject ClubRepository clubRepository; @Inject ServerCustom serverCustom; @Inject KeycloakService keycloakService; public SimpleCombModel find(int licence, String np) throws Throwable { return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() -> repository.find("licence = ?1 AND (lname collate UTF8_GENERAL_CI LIKE ?2 OR fname collate UTF8_GENERAL_CI LIKE ?2)", licence, np).firstResult().map(SimpleCombModel::fromModel))); } public SimpleCombModel findByIdOptionalComb(long id) throws Throwable { return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() -> repository.findById(id).map(SimpleCombModel::fromModel))); } public Uni> searchAdmin(int limit, int page, String search, String club) { if (search == null) search = ""; search = search + "%"; PanacheQuery query; if (club == null || club.isBlank()) query = repository.find("(lname LIKE ?1 OR fname LIKE ?1)", Sort.ascending("fname", "lname"), search).page(Page.ofSize(limit)); else query = repository.find("club.name LIKE ?2 AND (lname LIKE ?1 OR fname LIKE ?1)", Sort.ascending("fname", "lname"), search, club + "%").page(Page.ofSize(limit)); return getPageResult(query, limit, page); } public Uni> search(int limit, int page, String search, String subject) { if (search == null) search = ""; search = search + "%"; String finalSearch = search; return repository.find("userId = ?1", subject).firstResult() .chain(membreModel -> { PanacheQuery query = repository.find("club = ?1 AND (lname LIKE ?2 OR fname LIKE ?2)", Sort.ascending("fname", "lname"), membreModel.getClub(), finalSearch).page(Page.ofSize(limit)); return getPageResult(query, limit, page); }); } private Uni> getPageResult(PanacheQuery query, int limit, int page) { return Uni.createFrom().item(new PageResult()) .invoke(result -> result.setPage(page)) .invoke(result -> result.setPage_size(limit)) .call(result -> query.count().invoke(result::setResult_count)) .call(result -> query.pageCount() .invoke(Unchecked.consumer(pages -> { if (page > pages) throw new BadRequestException(); })) .invoke(result::setPage_count)) .call(result -> query.page(Page.of(page, limit)).list() .map(membreModels -> membreModels.stream().map(SimpleMembre::fromModel).toList()) .invoke(result::setResult)); } public Uni getById(long id) { return repository.findById(id); } public Uni update(long id, FullMemberForm membre) { return repository.findById(id) .chain(membreModel -> clubRepository.findById(membre.getClub()).map(club -> new Pair<>(membreModel, club))) .onItem().transformToUni(pair -> { MembreModel m = pair.getKey(); m.setFname(membre.getFname()); m.setLname(membre.getLname()); m.setClub(pair.getValue()); m.setCountry(membre.getCountry()); m.setBirth_date(membre.getBirth_date()); m.setGenre(membre.getGenre()); m.setCategorie(membre.getCategorie()); m.setRole(membre.getRole()); m.setGrade_arbitrage(membre.getGrade_arbitrage()); m.setEmail(membre.getEmail()); return Panache.withTransaction(() -> repository.persist(m)); }) .invoke(membreModel -> SReqComb.sendIfNeed(serverCustom.clients, SimpleCombModel.fromModel(membreModel))) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.setClubGroupMembre(membreModel, membreModel.getClub()) : Uni.createFrom().nullItem()) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.setAutoRoleMembre(membreModel.getUserId(), membreModel.getRole(), membreModel.getGrade_arbitrage()) : Uni.createFrom().nullItem()) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.setEmail(membreModel.getUserId(), membreModel.getEmail()) : Uni.createFrom().nullItem()) .map(__ -> "OK"); } public Uni update(long id, ClubMemberForm membre, JsonWebToken idToken, SecurityIdentity securityIdentity) { return repository.findById(id) .invoke(Unchecked.consumer(membreModel -> { if (!GroupeUtils.isInClubGroup(membreModel.getClub().getId(), idToken)) throw new ForbiddenException(); })) .invoke(Unchecked.consumer(membreModel -> { RoleAsso source = RoleAsso.MEMBRE; if (securityIdentity.getRoles().contains("club_president")) source = RoleAsso.PRESIDENT; else if (securityIdentity.getRoles().contains("club_secretaire")) source = RoleAsso.SECRETAIRE; else if (securityIdentity.getRoles().contains("club_respo_intra")) source = RoleAsso.SECRETAIRE; if (!membre.getRole().equals(membreModel.getRole()) && membre.getRole().level > source.level) throw new ForbiddenException(); })) .onItem().transformToUni(target -> { target.setFname(membre.getFname()); target.setLname(membre.getLname()); target.setCountry(membre.getCountry()); target.setBirth_date(membre.getBirth_date()); target.setGenre(membre.getGenre()); target.setCategorie(membre.getCategorie()); target.setEmail(membre.getEmail()); if (!idToken.getSubject().equals(target.getUserId())) target.setRole(membre.getRole()); return Panache.withTransaction(() -> repository.persist(target)); }) .invoke(membreModel -> SReqComb.sendIfNeed(serverCustom.clients, SimpleCombModel.fromModel(membreModel))) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.setAutoRoleMembre(membreModel.getUserId(), membreModel.getRole(), membreModel.getGrade_arbitrage()) : Uni.createFrom().nullItem()) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.setEmail(membreModel.getUserId(), membreModel.getEmail()) : Uni.createFrom().nullItem()) .map(__ -> "OK"); } public Uni setUserId(Long id, String id1) { return repository.findById(id).chain(membreModel -> { membreModel.setUserId(id1); return Panache.withTransaction(() -> repository.persist(membreModel)); }); } }