From bd386d1b0ad90f65efe5a70ddc62386c198b8f8a Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Thu, 15 Aug 2024 11:44:54 +0200 Subject: [PATCH] feat: add SecurityContext class --- .../ffsaf/domain/service/ClubService.java | 11 ++- .../domain/service/CompetPermService.java | 36 +++++---- .../domain/service/CompetitionService.java | 74 +++++++++---------- .../ffsaf/domain/service/LicenceService.java | 8 +- .../ffsaf/domain/service/MembreService.java | 18 ++--- .../ffsaf/domain/service/PouleService.java | 11 +-- .../ffsaf/rest/AffiliationEndpoints.java | 12 +-- .../rest/AffiliationRequestEndpoints.java | 16 ++-- .../titionfire/ffsaf/rest/ClubEndpoints.java | 18 ++--- .../ffsaf/rest/CompetitionEndpoints.java | 22 +++--- .../ffsaf/rest/CompteEndpoints.java | 13 +--- .../ffsaf/rest/LicenceEndpoints.java | 14 +--- .../titionfire/ffsaf/rest/MatchEndpoints.java | 12 +-- .../ffsaf/rest/MembreAdminEndpoints.java | 13 +--- .../ffsaf/rest/MembreClubEndpoints.java | 17 ++--- .../ffsaf/rest/MembreEndpoints.java | 15 +--- .../titionfire/ffsaf/rest/PouleEndpoints.java | 14 +--- .../titionfire/ffsaf/utils/GroupeUtils.java | 25 ------- .../titionfire/ffsaf/utils/SecurityCtx.java | 56 ++++++++++++++ 19 files changed, 181 insertions(+), 224 deletions(-) delete mode 100644 src/main/java/fr/titionfire/ffsaf/utils/GroupeUtils.java create mode 100644 src/main/java/fr/titionfire/ffsaf/utils/SecurityCtx.java diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java index 61aed55..e64f69a 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java @@ -30,7 +30,6 @@ import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.hibernate.reactive.mutiny.Mutiny; import java.util.Collection; @@ -121,8 +120,8 @@ public class ClubService { return repository.find("clubId", clubId).firstResult(); } - public Uni getOfUser(JsonWebToken idToken) { - return combRepository.find("userId = ?1", idToken.getSubject()).firstResult().invoke(Unchecked.consumer(m -> { + public Uni getOfUser(SecurityCtx securityCtx) { + return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult().invoke(Unchecked.consumer(m -> { if (m == null || m.getClub() == null) throw new DNotFoundException("Club non trouvé"); })) @@ -140,14 +139,14 @@ public class ClubService { .toList()); } - public Uni updateOfUser(JsonWebToken idToken, PartClubForm form) { + public Uni updateOfUser(SecurityCtx securityCtx, PartClubForm form) { TypeReference> typeRef = new TypeReference<>() { }; - return combRepository.find("userId = ?1", idToken.getSubject()).firstResult().invoke(Unchecked.consumer(m -> { + return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult().invoke(Unchecked.consumer(m -> { if (m == null || m.getClub() == null) throw new DNotFoundException("Club non trouvé"); - if (!GroupeUtils.isInClubGroup(m.getClub().getId(), idToken)) + if (!securityCtx.isInClubGroup(m.getClub().getId())) throw new DForbiddenException(); })) .map(MembreModel::getClub) diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetPermService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetPermService.java index 5ec36b6..254a335 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetPermService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetPermService.java @@ -7,15 +7,13 @@ import fr.titionfire.ffsaf.net2.data.SimpleCompet; import fr.titionfire.ffsaf.net2.request.SReqCompet; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.utils.CompetitionSystem; -import fr.titionfire.ffsaf.utils.GroupeUtils; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.quarkus.cache.Cache; import io.quarkus.cache.CacheName; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.HashMap; import java.util.UUID; @@ -54,7 +52,7 @@ public class CompetPermService { }); } - public Uni> getAllHaveAccess (String subject) { + public Uni> getAllHaveAccess(String subject) { return cacheAccess.get(subject, k -> { CompletableFuture> f = new CompletableFuture<>(); SReqCompet.getAllHaveAccess(serverCustom.clients, subject, f); @@ -67,52 +65,52 @@ public class CompetPermService { }); } - public Uni hasViewPerm(JsonWebToken idToken, SecurityIdentity sid, long id) { + public Uni hasViewPerm(SecurityCtx securityCtx, long id) { return competitionRepository.findById(id).call(o -> ( - idToken.getSubject().equals(o.getOwner()) || sid.getRoles().contains("federation_admin")) ? + securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ? Uni.createFrom().nullItem() : o.getSystem() == CompetitionSystem.SAFCA ? - hasSafcaViewPerm(idToken, sid, id) + hasSafcaViewPerm(securityCtx, id) : Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> { - if (!GroupeUtils.isInClubGroup(o.getClub().getId(), idToken)) + if (!securityCtx.isInClubGroup(o.getClub().getId())) throw new DForbiddenException(); }) )); } - public Uni hasEditPerm(JsonWebToken idToken, SecurityIdentity sid, long id) { + public Uni hasEditPerm(SecurityCtx securityCtx, long id) { return competitionRepository.findById(id).call(o -> ( - idToken.getSubject().equals(o.getOwner()) || sid.getRoles().contains("federation_admin")) ? + securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ? Uni.createFrom().nullItem() : o.getSystem() == CompetitionSystem.SAFCA ? - hasSafcaEditPerm(idToken, sid, id) + hasSafcaEditPerm(securityCtx, id) : Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> { - if (!GroupeUtils.isInClubGroup(o.getClub().getId(), idToken)) + if (!securityCtx.isInClubGroup(o.getClub().getId())) throw new DForbiddenException(); }) )); } - private Uni hasSafcaViewPerm(JsonWebToken idToken, SecurityIdentity sid, long id) { - return sid.getRoles().contains("safca_super_admin") ? + private Uni hasSafcaViewPerm(SecurityCtx securityCtx, long id) { + return securityCtx.roleHas("safca_super_admin") ? Uni.createFrom().nullItem() : getSafcaConfig(id).chain(Unchecked.function(o -> { - if (!o.admin().contains(UUID.fromString(idToken.getSubject())) && !o.table() - .contains(UUID.fromString(idToken.getSubject()))) + if (!o.admin().contains(UUID.fromString(securityCtx.getSubject())) && !o.table() + .contains(UUID.fromString(securityCtx.getSubject()))) throw new DForbiddenException(); return Uni.createFrom().nullItem(); })); } - private Uni hasSafcaEditPerm(JsonWebToken idToken, SecurityIdentity sid, long id) { - return sid.getRoles().contains("safca_super_admin") ? + private Uni hasSafcaEditPerm(SecurityCtx securityCtx, long id) { + return securityCtx.roleHas("safca_super_admin") ? Uni.createFrom().nullItem() : getSafcaConfig(id).chain(Unchecked.function(o -> { - if (!o.admin().contains(UUID.fromString(idToken.getSubject()))) + if (!o.admin().contains(UUID.fromString(securityCtx.getSubject()))) throw new DForbiddenException(); return Uni.createFrom().nullItem(); })); diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java index b0997a0..3a338ac 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/CompetitionService.java @@ -13,16 +13,14 @@ import fr.titionfire.ffsaf.rest.data.SimpleCompetData; import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.utils.CompetitionSystem; -import fr.titionfire.ffsaf.utils.GroupeUtils; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.common.WithSession; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import io.vertx.mutiny.core.Vertx; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.keycloak.representations.idm.UserRepresentation; import java.util.*; @@ -53,13 +51,13 @@ public class CompetitionService { @Inject Vertx vertx; - public Uni getById(JsonWebToken idToken, SecurityIdentity sid, Long id) { + public Uni getById(SecurityCtx securityCtx, Long id) { if (id == 0) { return Uni.createFrom() .item(new CompetitionData(null, "", "", new Date(), CompetitionSystem.SAFCA, null, "", "")); } - return permService.hasViewPerm(idToken, sid, id) + return permService.hasViewPerm(securityCtx, id) .map(CompetitionData::fromModel) .chain(data -> vertx.getOrCreateContext().executeBlocking(() -> { @@ -70,40 +68,40 @@ public class CompetitionService { ); } - public Uni> getAll(JsonWebToken idToken, SecurityIdentity securityIdentity) { + public Uni> getAll(SecurityCtx securityCtx) { return repository.listAll() .chain(o -> - permService.getAllHaveAccess(idToken.getSubject()) + permService.getAllHaveAccess(securityCtx.getSubject()) .chain(map -> Uni.createFrom().item(o.stream() .filter(p -> { - if (idToken.getSubject().equals(p.getOwner())) + if (securityCtx.getSubject().equals(p.getOwner())) return true; if (p.getSystem() == CompetitionSystem.SAFCA) { if (map.containsKey(p.getId())) return map.get(p.getId()).equals("admin"); - return securityIdentity.getRoles().contains("federation_admin") - || securityIdentity.getRoles().contains("safca_super_admin"); + return securityCtx.roleHas("federation_admin") + || securityCtx.roleHas("safca_super_admin"); } - return securityIdentity.getRoles().contains("federation_admin"); + return securityCtx.roleHas("federation_admin"); }) .map(CompetitionData::fromModel).toList()) )); } - public Uni> getAllSystem(JsonWebToken idToken, SecurityIdentity securityIdentity, + public Uni> getAllSystem(SecurityCtx securityCtx, CompetitionSystem system) { if (system == CompetitionSystem.SAFCA) { - return permService.getAllHaveAccess(idToken.getSubject()) + return permService.getAllHaveAccess(securityCtx.getSubject()) .chain(map -> repository.list("system = ?1", system) .map(data -> data.stream() .filter(p -> { - if (idToken.getSubject().equals(p.getOwner())) + if (securityCtx.getSubject().equals(p.getOwner())) return true; if (map.containsKey(p.getId())) return map.get(p.getId()).equals("admin"); - return securityIdentity.getRoles().contains("federation_admin") - || securityIdentity.getRoles().contains("safca_super_admin"); + return securityCtx.roleHas("federation_admin") + || securityCtx.roleHas("safca_super_admin"); }) .map(CompetitionData::fromModel).toList()) ); @@ -112,18 +110,18 @@ public class CompetitionService { return repository.list("system = ?1", system) .map(data -> data.stream() .filter(p -> { - if (idToken.getSubject().equals(p.getOwner())) + if (securityCtx.getSubject().equals(p.getOwner())) return true; - return securityIdentity.getRoles().contains("federation_admin") || - GroupeUtils.isInClubGroup(p.getClub().getId(), idToken); + return securityCtx.roleHas("federation_admin") || + securityCtx.isInClubGroup(p.getClub().getId()); }) .map(CompetitionData::fromModel).toList()); } - public Uni addOrUpdate(JsonWebToken idToken, SecurityIdentity sid, CompetitionData data) { + public Uni addOrUpdate(SecurityCtx securityCtx, CompetitionData data) { if (data.getId() == null) { return new ClubRepository().findById(data.getClub()).invoke(Unchecked.consumer(clubModel -> { - if (!GroupeUtils.isInClubGroup(clubModel.getId(), idToken)) + if (!securityCtx.isInClubGroup(clubModel.getId())) throw new DForbiddenException(); })) // TODO check if user can create competition .chain(clubModel -> { @@ -136,13 +134,13 @@ public class CompetitionService { model.setInsc(new ArrayList<>()); model.setUuid(UUID.randomUUID().toString()); model.setName(data.getName()); - model.setOwner(idToken.getSubject()); + model.setOwner(securityCtx.getSubject()); return Panache.withTransaction(() -> repository.persist(model)); }).map(CompetitionData::fromModel) - .call(__ -> permService.cacheAccess.invalidate(idToken.getSubject())); + .call(__ -> permService.cacheAccess.invalidate(securityCtx.getSubject())); } else { - return permService.hasEditPerm(idToken, sid, data.getId()) + return permService.hasEditPerm(securityCtx, data.getId()) .chain(model -> { model.setDate(data.getDate()); model.setName(data.getName()); @@ -153,22 +151,22 @@ public class CompetitionService { if (newOwner == null) throw new DBadRequestException("User " + data.getOwner() + " not found"); if (!newOwner.equals(model.getOwner())) { - if (!sid.getRoles().contains("federation_admin") - && !sid.getRoles().contains("safca_super_admin") - && !idToken.getSubject().equals(model.getOwner())) + if (!securityCtx.roleHas("federation_admin") + && !securityCtx.roleHas("safca_super_admin") + && !securityCtx.getSubject().equals(model.getOwner())) throw new DForbiddenException(); model.setOwner(newOwner); } })) .chain(__ -> Panache.withTransaction(() -> repository.persist(model))); }).map(CompetitionData::fromModel) - .call(__ -> permService.cacheAccess.invalidate(idToken.getSubject())); + .call(__ -> permService.cacheAccess.invalidate(securityCtx.getSubject())); } } - public Uni delete(JsonWebToken idToken, SecurityIdentity sid, Long id) { + public Uni delete(SecurityCtx securityCtx, Long id) { return repository.findById(id).invoke(Unchecked.consumer(c -> { - if (!idToken.getSubject().equals(c.getOwner()) || sid.getRoles().contains("federation_admin")) + if (!securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")) throw new DForbiddenException(); })) .call(competitionModel -> pouleRepository.list("compet = ?1", competitionModel) @@ -185,14 +183,14 @@ public class CompetitionService { .call(__ -> permService.cache.invalidate(id)); } - public Uni getSafcaData(JsonWebToken idToken, SecurityIdentity sid, Long id) { + public Uni getSafcaData(SecurityCtx securityCtx, Long id) { return permService.getSafcaConfig(id) .call(Unchecked.function(o -> { - if (!idToken.getSubject().equals(o.owner()) - && !sid.getRoles().contains("federation_admin") - && !sid.getRoles().contains("safca_super_admin") - && !o.admin().contains(UUID.fromString(idToken.getSubject())) - && !o.table().contains(UUID.fromString(idToken.getSubject()))) + if (!securityCtx.getSubject().equals(o.owner()) + && !securityCtx.roleHas("federation_admin") + && !securityCtx.roleHas("safca_super_admin") + && !o.admin().contains(UUID.fromString(securityCtx.getSubject())) + && !o.table().contains(UUID.fromString(securityCtx.getSubject()))) throw new DForbiddenException(); return Uni.createFrom().nullItem(); })) @@ -213,8 +211,8 @@ public class CompetitionService { }); } - public Uni setSafcaData(JsonWebToken idToken, SecurityIdentity sid, SimpleCompetData data) { - return permService.hasEditPerm(idToken, sid, data.getId()) + public Uni setSafcaData(SecurityCtx securityCtx, SimpleCompetData data) { + return permService.hasEditPerm(securityCtx, data.getId()) .chain(__ -> vertx.getOrCreateContext().executeBlocking(() -> { ArrayList admin = new ArrayList<>(); ArrayList table = new ArrayList<>(); diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/LicenceService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/LicenceService.java index 64fb1ab..ac99ae2 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/LicenceService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/LicenceService.java @@ -7,6 +7,7 @@ import fr.titionfire.ffsaf.data.repository.LicenceRepository; import fr.titionfire.ffsaf.data.repository.SequenceRepository; import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.from.LicenceForm; +import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.SequenceType; import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.hibernate.reactive.panache.Panache; @@ -15,7 +16,6 @@ import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.hibernate.reactive.mutiny.Mutiny; import java.util.List; @@ -39,11 +39,11 @@ public class LicenceService { .chain(combRepository -> Mutiny.fetch(combRepository.getLicences())); } - public Uni> getCurrentSaisonLicence(JsonWebToken idToken) { - if (idToken == null) + public Uni> getCurrentSaisonLicence(SecurityCtx securityCtx) { + if (securityCtx.getSubject() == null) return repository.find("saison = ?1", Utils.getSaison()).list(); - return combRepository.find("userId = ?1", idToken.getSubject()).firstResult().map(MembreModel::getClub) + return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult().map(MembreModel::getClub) .chain(clubModel -> combRepository.find("club = ?1", clubModel).list()) .chain(membres -> repository.find("saison = ?1 AND membre IN ?2", Utils.getSaison(), membres).list()); } diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java index 7306a23..6b6b4c4 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java @@ -21,14 +21,12 @@ 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 org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.hibernate.reactive.mutiny.Mutiny; import java.util.List; @@ -151,17 +149,17 @@ public class MembreService { .map(__ -> "OK"); } - public Uni update(long id, ClubMemberForm membre, JsonWebToken idToken, SecurityIdentity securityIdentity) { + public Uni update(long id, ClubMemberForm membre, SecurityCtx securityCtx) { return repository.findById(id) .invoke(Unchecked.consumer(membreModel -> { - if (!GroupeUtils.isInClubGroup(membreModel.getClub().getId(), idToken)) + if (!securityCtx.isInClubGroup(membreModel.getClub().getId())) throw new DForbiddenException(); })) .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.MEMBREBUREAU; + if (securityCtx.roleHas("club_president")) source = RoleAsso.PRESIDENT; + else if (securityCtx.roleHas("club_secretaire")) source = RoleAsso.SECRETAIRE; + else if (securityCtx.roleHas("club_respo_intra")) source = RoleAsso.MEMBREBUREAU; if (!membre.getRole().equals(membreModel.getRole()) && membre.getRole().level >= source.level) throw new DForbiddenException("Permission insuffisante"); })) @@ -173,7 +171,7 @@ public class MembreService { target.setGenre(membre.getGenre()); target.setCategorie(membre.getCategorie()); target.setEmail(membre.getEmail()); - if (!idToken.getSubject().equals(target.getUserId())) + if (!securityCtx.getSubject().equals(target.getUserId())) target.setRole(membre.getRole()); return Panache.withTransaction(() -> repository.persist(target)); }) @@ -221,10 +219,10 @@ public class MembreService { .map(__ -> "Ok"); } - public Uni delete(long id, JsonWebToken idToken) { + public Uni delete(long id, SecurityCtx securityCtx) { return repository.findById(id) .invoke(Unchecked.consumer(membreModel -> { - if (!GroupeUtils.isInClubGroup(membreModel.getClub().getId(), idToken)) + if (!securityCtx.isInClubGroup(membreModel.getClub().getId())) throw new DForbiddenException(); })) .call(membreModel -> licenceRepository.find("membre = ?1", membreModel).count() diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/PouleService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/PouleService.java index cab86e6..90585ae 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/PouleService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/PouleService.java @@ -6,14 +6,12 @@ import fr.titionfire.ffsaf.rest.data.PouleData; import fr.titionfire.ffsaf.rest.data.PouleFullData; import fr.titionfire.ffsaf.rest.data.TreeData; import fr.titionfire.ffsaf.utils.CompetitionSystem; -import fr.titionfire.ffsaf.utils.GroupeUtils; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.common.WithSession; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.hibernate.reactive.mutiny.Mutiny; import java.util.ArrayList; @@ -50,12 +48,11 @@ public class PouleService { .map(PouleData::fromModel); } - public Uni> getAll(JsonWebToken idToken, SecurityIdentity securityIdentity, - CompetitionSystem system) { + public Uni> getAll(SecurityCtx securityCtx, CompetitionSystem system) { return repository.list("system = ?1", system) .map(data -> data.stream() - .filter(p -> securityIdentity.getRoles().contains("federation_admin") || - GroupeUtils.isInClubGroup(p.getCompet().getClub().getId(), idToken)) + .filter(p -> securityCtx.roleHas("federation_admin") || + securityCtx.isInClubGroup(p.getCompet().getClub().getId())) .map(PouleData::fromModel).toList()); } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/AffiliationEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/AffiliationEndpoints.java index 1ebc52b..a65e9a7 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/AffiliationEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/AffiliationEndpoints.java @@ -3,16 +3,13 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.domain.service.AffiliationService; import fr.titionfire.ffsaf.rest.data.SimpleAffiliation; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; -import fr.titionfire.ffsaf.utils.GroupeUtils; -import io.quarkus.oidc.IdToken; -import io.quarkus.security.identity.SecurityIdentity; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -30,13 +27,10 @@ public class AffiliationEndpoints { AffiliationService service; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; Consumer checkPerm = Unchecked.consumer(id -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(id, idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(id)) throw new DForbiddenException(); }); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/AffiliationRequestEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/AffiliationRequestEndpoints.java index b4f5c7e..1ad6b57 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/AffiliationRequestEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/AffiliationRequestEndpoints.java @@ -6,10 +6,8 @@ import fr.titionfire.ffsaf.rest.data.SimpleReqAffiliationResume; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.from.AffiliationRequestForm; import fr.titionfire.ffsaf.rest.from.AffiliationRequestSaveForm; -import fr.titionfire.ffsaf.utils.GroupeUtils; +import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; -import io.quarkus.oidc.IdToken; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; @@ -18,7 +16,6 @@ import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -35,16 +32,13 @@ public class AffiliationRequestEndpoints { AffiliationService service; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; @ConfigProperty(name = "upload_dir") String media; Consumer checkPerm = Unchecked.consumer(id -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(id, idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(id)) throw new DForbiddenException(); }); @@ -91,7 +85,7 @@ public class AffiliationRequestEndpoints { public Uni getAffRequest( @Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) { return service.getRequest(id).invoke(Unchecked.consumer(o -> { - if (o.getClub() == null && !securityIdentity.getRoles().contains("federation_admin")) + if (o.getClub() == null && !securityCtx.roleHas("federation_admin")) throw new DForbiddenException(); })).invoke(o -> checkPerm.accept(o.getClub())); } @@ -110,7 +104,7 @@ public class AffiliationRequestEndpoints { public Uni getDelAffRequest( @Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) { return service.getRequest(id).invoke(Unchecked.consumer(o -> { - if (o.getClub() == null && !securityIdentity.getRoles().contains("federation_admin")) + if (o.getClub() == null && !securityCtx.roleHas("federation_admin")) throw new DForbiddenException(); })).invoke(o -> checkPerm.accept(o.getClub())) .chain(o -> service.deleteReqAffiliation(id)); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java index c05a165..c9acaf9 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java @@ -12,11 +12,10 @@ import fr.titionfire.ffsaf.rest.exception.DInternalError; import fr.titionfire.ffsaf.rest.from.FullClubForm; import fr.titionfire.ffsaf.rest.from.PartClubForm; import fr.titionfire.ffsaf.utils.Contact; -import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.PageResult; +import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.security.Authenticated; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; @@ -25,7 +24,6 @@ import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -45,21 +43,17 @@ public class ClubEndpoints { ClubService clubService; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; @ConfigProperty(name = "upload_dir") String media; Consumer checkPerm = Unchecked.consumer(clubModel -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(clubModel.getId(), - idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(clubModel.getId())) throw new DForbiddenException(); }); Consumer checkPerm2 = Unchecked.consumer(id -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(id, idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(id)) throw new DForbiddenException(); }); @@ -229,7 +223,7 @@ public class ClubEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getOfUser() { - return clubService.getOfUser(idToken).map(SimpleClub::fromModel) + return clubService.getOfUser(securityCtx).map(SimpleClub::fromModel) .invoke(m -> m.setContactMap(Contact.toSite())); } @@ -247,7 +241,7 @@ public class ClubEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni setClubOfUser(PartClubForm form) { - return clubService.updateOfUser(idToken, form); + return clubService.updateOfUser(securityCtx, form); } @GET diff --git a/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java index e2b282f..3cde90e 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/CompetitionEndpoints.java @@ -4,13 +4,12 @@ import fr.titionfire.ffsaf.domain.service.CompetitionService; import fr.titionfire.ffsaf.rest.data.CompetitionData; import fr.titionfire.ffsaf.rest.data.SimpleCompetData; import fr.titionfire.ffsaf.utils.CompetitionSystem; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.quarkus.security.Authenticated; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.List; @@ -21,17 +20,14 @@ public class CompetitionEndpoints { CompetitionService service; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; @GET @Path("{id}") @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni getById(@PathParam("id") Long id) { - return service.getById(idToken, securityIdentity, id); + return service.getById(securityCtx, id); } @GET @@ -39,7 +35,7 @@ public class CompetitionEndpoints { @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni getSafcaData(@PathParam("id") Long id) { - return service.getSafcaData(idToken, securityIdentity, id); + return service.getSafcaData(securityCtx, id); } @@ -48,7 +44,7 @@ public class CompetitionEndpoints { @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni> getAll() { - return service.getAll(idToken, securityIdentity); + return service.getAll(securityCtx); } @GET @@ -56,14 +52,14 @@ public class CompetitionEndpoints { @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni> getAllSystem(@PathParam("system") CompetitionSystem system) { - return service.getAllSystem(idToken, securityIdentity, system); + return service.getAllSystem(securityCtx, system); } @POST @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni addOrUpdate(CompetitionData data) { - return service.addOrUpdate(idToken, securityIdentity, data); + return service.addOrUpdate(securityCtx, data); } @POST @@ -71,7 +67,7 @@ public class CompetitionEndpoints { @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni setSafcaData(SimpleCompetData data) { - return service.setSafcaData(idToken, securityIdentity, data); + return service.setSafcaData(securityCtx, data); } @DELETE @@ -79,6 +75,6 @@ public class CompetitionEndpoints { @Authenticated @Produces(MediaType.APPLICATION_JSON) public Uni delete(@PathParam("id") Long id) { - return service.delete(idToken, securityIdentity, id); + return service.delete(securityCtx, id); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/CompteEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/CompteEndpoints.java index f2bf094..4d08b15 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/CompteEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/CompteEndpoints.java @@ -3,9 +3,8 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.domain.service.KeycloakService; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.from.MemberPermForm; -import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.Pair; -import io.quarkus.security.identity.SecurityIdentity; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.smallrye.mutiny.Uni; import io.vertx.mutiny.core.Vertx; import jakarta.annotation.security.RolesAllowed; @@ -14,7 +13,6 @@ import jakarta.ws.rs.GET; import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; -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.responses.APIResponses; @@ -32,10 +30,7 @@ public class CompteEndpoints { KeycloakService service; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; @Inject Vertx vertx; @@ -53,9 +48,9 @@ public class CompteEndpoints { }) public Uni getCompte(@PathParam("id") String id) { return service.fetchCompte(id).call(pair -> vertx.getOrCreateContext().executeBlocking(() -> { - if (!securityIdentity.getRoles().contains("federation_admin") && pair.getKey().groups().stream() + if (!securityCtx.roleHas("federation_admin") && pair.getKey().groups().stream() .map(GroupRepresentation::getPath) - .noneMatch(s -> s.startsWith("/club/") && GroupeUtils.contains(s, idToken))) + .noneMatch(s -> s.startsWith("/club/") && securityCtx.contains(s))) throw new DForbiddenException(); return pair; })).map(Pair::getValue); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/LicenceEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/LicenceEndpoints.java index 5eaabd9..f3ddb59 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/LicenceEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/LicenceEndpoints.java @@ -5,16 +5,13 @@ import fr.titionfire.ffsaf.domain.service.LicenceService; import fr.titionfire.ffsaf.rest.data.SimpleLicence; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.from.LicenceForm; -import fr.titionfire.ffsaf.utils.GroupeUtils; -import io.quarkus.oidc.IdToken; -import io.quarkus.security.identity.SecurityIdentity; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -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.responses.APIResponses; @@ -29,13 +26,10 @@ public class LicenceEndpoints { LicenceService licenceService; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; Consumer checkPerm = Unchecked.consumer(membreModel -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(membreModel.getClub().getId(), idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(membreModel.getClub().getId())) throw new DForbiddenException(); }); @@ -80,7 +74,7 @@ public class LicenceEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni> getCurrentSaisonLicenceClub() { - return licenceService.getCurrentSaisonLicence(idToken).map(licenceModels -> licenceModels.stream().map(SimpleLicence::fromModel).toList()); + return licenceService.getCurrentSaisonLicence(securityCtx).map(licenceModels -> licenceModels.stream().map(SimpleLicence::fromModel).toList()); } @POST diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MatchEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MatchEndpoints.java index d67fec7..370a624 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MatchEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MatchEndpoints.java @@ -5,16 +5,14 @@ import fr.titionfire.ffsaf.domain.service.MatchService; import fr.titionfire.ffsaf.rest.data.MatchData; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.utils.CompetitionSystem; -import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.ScoreEmbeddable; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.quarkus.security.Authenticated; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.List; import java.util.function.Consumer; @@ -30,14 +28,10 @@ public class MatchEndpoints { MatchService service; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; Consumer checkPerm = Unchecked.consumer(clubModel -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(clubModel.getId(), - idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(clubModel.getId())) throw new DForbiddenException(); }); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java index b65df9b..82865fd 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreAdminEndpoints.java @@ -6,11 +6,9 @@ import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.exception.DInternalError; import fr.titionfire.ffsaf.rest.from.FullMemberForm; -import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.PageResult; +import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; -import io.quarkus.oidc.IdToken; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; @@ -18,7 +16,6 @@ import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -40,14 +37,10 @@ public class MembreAdminEndpoints { String media; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; Consumer checkPerm = Unchecked.consumer(membreModel -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup( - membreModel.getClub().getId(), idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(membreModel.getClub().getId())) throw new DForbiddenException(); }); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java index 41e24c5..aa9b49e 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java @@ -6,9 +6,8 @@ import fr.titionfire.ffsaf.rest.exception.DInternalError; import fr.titionfire.ffsaf.rest.from.ClubMemberForm; import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.utils.PageResult; +import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; -import io.quarkus.oidc.IdToken; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; @@ -16,7 +15,6 @@ import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -35,10 +33,7 @@ public class MembreClubEndpoints { String media; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; @GET @Path("/find/club") @@ -57,7 +52,7 @@ public class MembreClubEndpoints { limit = 50; if (page == null || page < 1) page = 1; - return membreService.search(limit, page - 1, search, idToken.getSubject()); + return membreService.search(limit, page - 1, search, securityCtx.getSubject()); } @PUT @@ -74,7 +69,7 @@ public class MembreClubEndpoints { }) public Uni setMembre( @Parameter(description = "Identifiant de membre") @PathParam("id") long id, ClubMemberForm input) { - return membreService.update(id, input, idToken, securityIdentity) + return membreService.update(id, input, securityCtx) .invoke(Unchecked.consumer(out -> { if (!out.equals("OK")) throw new InternalError("Fail to update data: " + out); })).chain(() -> { @@ -101,7 +96,7 @@ public class MembreClubEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni addMembre(FullMemberForm input) { - return membreService.add(input, idToken.getSubject()) + return membreService.add(input, securityCtx.getSubject()) .invoke(Unchecked.consumer(id -> { if (id == null) throw new InternalError("Fail to creat member data"); })).call(id -> { @@ -126,6 +121,6 @@ public class MembreClubEndpoints { }) public Uni deleteMembre( @Parameter(description = "Identifiant de membre") @PathParam("id") long id) { - return membreService.delete(id, idToken); + return membreService.delete(id, securityCtx); } } diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java index e06a2c9..c281ea1 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java @@ -5,11 +5,9 @@ import fr.titionfire.ffsaf.domain.service.MembreService; import fr.titionfire.ffsaf.rest.data.MeData; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; -import fr.titionfire.ffsaf.utils.GroupeUtils; +import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; -import io.quarkus.oidc.IdToken; import io.quarkus.security.Authenticated; -import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; @@ -18,7 +16,6 @@ import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -40,14 +37,10 @@ public class MembreEndpoints { String media; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; Consumer checkPerm = Unchecked.consumer(membreModel -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup( - membreModel.getClub().getId(), idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(membreModel.getClub().getId())) throw new DForbiddenException(); }); @@ -95,7 +88,7 @@ public class MembreEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getMe() { - return membreService.getMembre(idToken.getSubject()); + return membreService.getMembre(securityCtx.getSubject()); } @GET diff --git a/src/main/java/fr/titionfire/ffsaf/rest/PouleEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/PouleEndpoints.java index d0c299a..88f908e 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/PouleEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/PouleEndpoints.java @@ -6,14 +6,12 @@ import fr.titionfire.ffsaf.rest.data.PouleData; import fr.titionfire.ffsaf.rest.data.PouleFullData; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.utils.CompetitionSystem; -import fr.titionfire.ffsaf.utils.GroupeUtils; -import io.quarkus.security.identity.SecurityIdentity; +import fr.titionfire.ffsaf.utils.SecurityCtx; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; -import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.List; import java.util.function.Consumer; @@ -29,14 +27,10 @@ public class PouleEndpoints { PouleService service; @Inject - JsonWebToken idToken; - - @Inject - SecurityIdentity securityIdentity; + SecurityCtx securityCtx; Consumer checkPerm = Unchecked.consumer(clubModel -> { - if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup(clubModel.getId(), - idToken)) + if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(clubModel.getId())) throw new DForbiddenException(); }); @@ -50,7 +44,7 @@ public class PouleEndpoints { @GET @Produces(MediaType.APPLICATION_JSON) public Uni> getAll() { - return service.getAll(idToken, securityIdentity, system); + return service.getAll(securityCtx, system); } @POST diff --git a/src/main/java/fr/titionfire/ffsaf/utils/GroupeUtils.java b/src/main/java/fr/titionfire/ffsaf/utils/GroupeUtils.java deleted file mode 100644 index 3910ea9..0000000 --- a/src/main/java/fr/titionfire/ffsaf/utils/GroupeUtils.java +++ /dev/null @@ -1,25 +0,0 @@ -package fr.titionfire.ffsaf.utils; - -import org.eclipse.microprofile.jwt.JsonWebToken; - -public class GroupeUtils { - public static boolean isInClubGroup(long id, JsonWebToken accessToken) { - if (accessToken.getClaim("user_groups") instanceof Iterable) { - for (Object str : (Iterable) accessToken.getClaim("user_groups")) { - if (str.toString().substring(1, str.toString().length() - 1).startsWith("/club/" + id + "-")) - return true; - } - } - return false; - } - - public static boolean contains(String string, JsonWebToken accessToken) { - if (accessToken.getClaim("user_groups") instanceof Iterable) { - for (Object str : (Iterable) accessToken.getClaim("user_groups")) { - if (str.toString().substring(1, str.toString().length() - 1).contains(string)) - return true; - } - } - return false; - } -} diff --git a/src/main/java/fr/titionfire/ffsaf/utils/SecurityCtx.java b/src/main/java/fr/titionfire/ffsaf/utils/SecurityCtx.java new file mode 100644 index 0000000..348e1b3 --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/utils/SecurityCtx.java @@ -0,0 +1,56 @@ +package fr.titionfire.ffsaf.utils; + +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import org.eclipse.microprofile.jwt.JsonWebToken; + +import java.util.Set; + +@RequestScoped +public class SecurityCtx { + @Inject + JsonWebToken idToken; + + @Inject + SecurityIdentity securityIdentity; + + public Set getRoles() { + return securityIdentity.getRoles(); + } + + public String getSubject() { + if (idToken == null) + return null; + return idToken.getSubject(); + } + + public boolean roleHas(String role) { + if (role == null) + return false; + return securityIdentity.getRoles().contains(role); + } + + public boolean isInClubGroup(long id) { + if (idToken == null || idToken.getClaim("user_groups") == null) + return false; + + if (idToken.getClaim("user_groups") instanceof Iterable) { + for (Object str : (Iterable) idToken.getClaim("user_groups")) { + if (str.toString().substring(1, str.toString().length() - 1).startsWith("/club/" + id + "-")) + return true; + } + } + return false; + } + + public boolean contains(String string) { + if (idToken.getClaim("user_groups") instanceof Iterable) { + for (Object str : (Iterable) idToken.getClaim("user_groups")) { + if (str.toString().substring(1, str.toString().length() - 1).contains(string)) + return true; + } + } + return false; + } +}