feat: add SecurityContext class

This commit is contained in:
2024-08-15 11:44:54 +02:00
parent 7f80c876d3
commit bd386d1b0a
19 changed files with 181 additions and 224 deletions

View File

@@ -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<CompetitionData> getById(JsonWebToken idToken, SecurityIdentity sid, Long id) {
public Uni<CompetitionData> 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<List<CompetitionData>> getAll(JsonWebToken idToken, SecurityIdentity securityIdentity) {
public Uni<List<CompetitionData>> 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<List<CompetitionData>> getAllSystem(JsonWebToken idToken, SecurityIdentity securityIdentity,
public Uni<List<CompetitionData>> 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<CompetitionData> addOrUpdate(JsonWebToken idToken, SecurityIdentity sid, CompetitionData data) {
public Uni<CompetitionData> 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<SimpleCompetData> getSafcaData(JsonWebToken idToken, SecurityIdentity sid, Long id) {
public Uni<SimpleCompetData> 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<UUID> admin = new ArrayList<>();
ArrayList<UUID> table = new ArrayList<>();