feat: secure match ans poule endpoints
This commit is contained in:
parent
bd386d1b0a
commit
6b38405e94
@ -29,7 +29,7 @@ public class PouleModel {
|
||||
|
||||
String name = "";
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "id_compet", referencedColumnName = "id")
|
||||
CompetitionModel compet;
|
||||
|
||||
|
||||
@ -65,13 +65,21 @@ public class CompetPermService {
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasViewPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, long id) {
|
||||
return competitionRepository.findById(id).call(o -> (
|
||||
return hasViewPerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
private Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(o -> (
|
||||
securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
o.getSystem() == CompetitionSystem.SAFCA ?
|
||||
hasSafcaViewPerm(securityCtx, id)
|
||||
hasSafcaViewPerm(securityCtx, o.getId())
|
||||
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
@ -79,13 +87,21 @@ public class CompetPermService {
|
||||
));
|
||||
}
|
||||
|
||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||
return hasEditPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||
}
|
||||
|
||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, long id) {
|
||||
return competitionRepository.findById(id).call(o -> (
|
||||
return hasEditPerm(securityCtx, competitionRepository.findById(id));
|
||||
}
|
||||
|
||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||
return in.call(o -> (
|
||||
securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
|
||||
Uni.createFrom().nullItem()
|
||||
:
|
||||
o.getSystem() == CompetitionSystem.SAFCA ?
|
||||
hasSafcaEditPerm(securityCtx, id)
|
||||
hasSafcaEditPerm(securityCtx, o.getId())
|
||||
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
|
||||
if (!securityCtx.isInClubGroup(o.getClub().getId()))
|
||||
throw new DForbiddenException();
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||
@ -8,6 +7,7 @@ import fr.titionfire.ffsaf.data.repository.PouleRepository;
|
||||
import fr.titionfire.ffsaf.rest.data.MatchData;
|
||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
@ -15,7 +15,6 @@ import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@WithSession
|
||||
@ApplicationScoped
|
||||
@ -30,30 +29,32 @@ public class MatchService {
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
public Uni<MatchData> getById(Consumer<ClubModel> checkPerm, CompetitionSystem system, Long id) {
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
public Uni<MatchData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Match not found"))
|
||||
.call(data -> pouleRepository.findById(data.getPoule().getId())
|
||||
.invoke(data2 -> checkPerm.accept(data2.getCompet().getClub())))
|
||||
.call(data -> permService.hasViewPerm(securityCtx, data.getPoule().getCompet()))
|
||||
.map(MatchData::fromModel);
|
||||
}
|
||||
|
||||
public Uni<List<MatchData>> getAllByPoule(Consumer<ClubModel> checkPerm, CompetitionSystem system, Long id) {
|
||||
public Uni<List<MatchData>> getAllByPoule(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return pouleRepository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.invoke(data -> checkPerm.accept(data.getCompet().getClub()))
|
||||
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
||||
.chain(data -> repository.list("poule = ?1", data.getId())
|
||||
.map(o -> o.stream().map(MatchData::fromModel).toList()));
|
||||
}
|
||||
|
||||
public Uni<MatchData> addOrUpdate(Consumer<ClubModel> checkPerm, CompetitionSystem system, MatchData data) {
|
||||
public Uni<MatchData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, MatchData data) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
||||
.chain(o -> {
|
||||
if (o == null) {
|
||||
return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.invoke(data2 -> checkPerm.accept(data2.getCompet().getClub()))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||
.map(pouleModel -> {
|
||||
MatchModel model = new MatchModel();
|
||||
|
||||
@ -67,7 +68,7 @@ public class MatchService {
|
||||
return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.invoke(data2 -> checkPerm.accept(data2.getCompet().getClub()))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||
.map(__ -> o);
|
||||
}
|
||||
}
|
||||
@ -91,9 +92,11 @@ public class MatchService {
|
||||
.map(MatchData::fromModel);
|
||||
}
|
||||
|
||||
public Uni<?> updateScore(CompetitionSystem system, Long id, List<ScoreEmbeddable> scores) {
|
||||
public Uni<?> updateScore(SecurityCtx securityCtx, CompetitionSystem system, Long id,
|
||||
List<ScoreEmbeddable> scores) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Match not found"))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
|
||||
.invoke(data -> {
|
||||
data.getScores().clear();
|
||||
data.getScores().addAll(scores);
|
||||
@ -102,11 +105,10 @@ public class MatchService {
|
||||
.map(o -> "OK");
|
||||
}
|
||||
|
||||
public Uni<?> delete(Consumer<ClubModel> checkPerm, CompetitionSystem system, Long id) {
|
||||
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Match not found"))
|
||||
.chain(data -> pouleRepository.findById(data.getPoule().getId())
|
||||
.invoke(data2 -> checkPerm.accept(data2.getCompet().getClub()))
|
||||
.chain(data2 -> Panache.withTransaction(() -> repository.delete(data))));
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
|
||||
.chain(data -> Panache.withTransaction(() -> repository.delete(data)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
package fr.titionfire.ffsaf.domain.service;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.*;
|
||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||
import fr.titionfire.ffsaf.data.repository.*;
|
||||
import fr.titionfire.ffsaf.rest.data.PouleData;
|
||||
import fr.titionfire.ffsaf.rest.data.PouleFullData;
|
||||
@ -18,7 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@WithSession
|
||||
@ -40,29 +42,44 @@ public class PouleService {
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
public Uni<PouleData> getById(Consumer<ClubModel> checkPerm, CompetitionSystem system, Long id) {
|
||||
@Inject
|
||||
CompetPermService permService;
|
||||
|
||||
public Uni<PouleData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system)
|
||||
.firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.invoke(data -> checkPerm.accept(data.getCompet().getClub()))
|
||||
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
||||
.map(PouleData::fromModel);
|
||||
}
|
||||
|
||||
public Uni<List<PouleData>> getAll(SecurityCtx securityCtx, CompetitionSystem system) {
|
||||
return repository.list("system = ?1", system)
|
||||
.map(data -> data.stream()
|
||||
.filter(p -> securityCtx.roleHas("federation_admin") ||
|
||||
securityCtx.isInClubGroup(p.getCompet().getClub().getId()))
|
||||
.map(PouleData::fromModel).toList());
|
||||
.chain(o ->
|
||||
permService.getAllHaveAccess(securityCtx.getSubject())
|
||||
.chain(map -> Uni.createFrom().item(o.stream()
|
||||
.filter(p -> {
|
||||
if (securityCtx.getSubject().equals(p.getCompet().getOwner()))
|
||||
return true;
|
||||
if (p.getSystem() == CompetitionSystem.SAFCA) {
|
||||
if (map.containsKey(p.getCompet().getId()))
|
||||
return map.get(p.getId()).equals("admin");
|
||||
return securityCtx.roleHas("federation_admin")
|
||||
|| securityCtx.roleHas("safca_super_admin");
|
||||
}
|
||||
return securityCtx.roleHas("federation_admin");
|
||||
})
|
||||
.map(PouleData::fromModel).toList())
|
||||
));
|
||||
}
|
||||
|
||||
public Uni<PouleData> addOrUpdate(Consumer<ClubModel> checkPerm, CompetitionSystem system, PouleData data) {
|
||||
public Uni<PouleData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, PouleData data) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
||||
.chain(o -> {
|
||||
if (o == null) {
|
||||
return competRepository.findById(data.getCompet())
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Competition not found"))
|
||||
.invoke(o2 -> checkPerm.accept(o2.getClub()))
|
||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2))
|
||||
.chain(competitionModel -> {
|
||||
PouleModel model = new PouleModel();
|
||||
|
||||
@ -130,13 +147,14 @@ public class PouleService {
|
||||
.chain(o -> Panache.withTransaction(() -> treeRepository.persist(o)));
|
||||
}
|
||||
|
||||
public Uni<?> syncPoule(CompetitionSystem system, PouleFullData data) {
|
||||
System.out.println(data);
|
||||
public Uni<?> syncPoule(SecurityCtx securityCtx, CompetitionSystem system, PouleFullData data) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system)
|
||||
.firstResult()
|
||||
.onItem().ifNotNull().call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||
.onItem().ifNull().switchTo(
|
||||
() -> competRepository.findById(data.getCompet())
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Compet not found"))
|
||||
.call(o -> permService.hasEditPerm(securityCtx, o))
|
||||
.map(o -> {
|
||||
PouleModel model = new PouleModel();
|
||||
model.setId(null);
|
||||
@ -240,9 +258,10 @@ public class PouleService {
|
||||
List<Long> toRmNode;
|
||||
}
|
||||
|
||||
public Uni<?> delete(Consumer<ClubModel> checkPerm, CompetitionSystem system, Long id) {
|
||||
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||
.call(o -> permService.hasEditPerm(securityCtx, o.getCompet()))
|
||||
.call(o -> Mutiny.fetch(o.getMatchs()))
|
||||
.call(o -> Mutiny.fetch(o.getTree())
|
||||
.call(o2 -> o2.isEmpty() ? Uni.createFrom().nullItem() :
|
||||
|
||||
@ -274,7 +274,6 @@ public class ClubEndpoints {
|
||||
|
||||
@GET
|
||||
@Path("{clubId}/logo")
|
||||
@RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"})
|
||||
@Operation(summary = "Renvoie le logo du club", description = "Renvoie le logo du club spécifié")
|
||||
@APIResponses(value = {
|
||||
@APIResponse(responseCode = "200", description = "Le logo du club"),
|
||||
@ -284,7 +283,7 @@ public class ClubEndpoints {
|
||||
})
|
||||
public Uni<Response> getLogo(
|
||||
@Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) {
|
||||
return clubService.getByClubId(clubId).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> {
|
||||
return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> {
|
||||
try {
|
||||
return Utils.getMediaFile((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
|
||||
Uni.createFrom().nullItem());
|
||||
|
||||
@ -1,21 +1,17 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||
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.ScoreEmbeddable;
|
||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
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 java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Authenticated
|
||||
@Path("api/match/{system}/")
|
||||
@ -30,42 +26,38 @@ public class MatchEndpoints {
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
Consumer<ClubModel> checkPerm = Unchecked.consumer(clubModel -> {
|
||||
if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(clubModel.getId()))
|
||||
throw new DForbiddenException();
|
||||
});
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<MatchData> getById(@PathParam("id") Long id) {
|
||||
return service.getById(checkPerm, system, id);
|
||||
return service.getById(securityCtx, system, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("getAllByPoule/{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<MatchData>> getAllByPoule(@PathParam("id") Long id) {
|
||||
return service.getAllByPoule(checkPerm, system, id);
|
||||
return service.getAllByPoule(securityCtx, system, id);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<MatchData> addOrUpdate(MatchData data) {
|
||||
return service.addOrUpdate(checkPerm, system, data);
|
||||
return service.addOrUpdate(securityCtx, system, data);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("score/{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<?> updateScore(@PathParam("id") Long id, List<ScoreEmbeddable> scores) {
|
||||
return service.updateScore(system, id, scores);
|
||||
return service.updateScore(securityCtx, system, id, scores);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<?> delete(@PathParam("id") Long id) {
|
||||
return service.delete(checkPerm, system, id);
|
||||
return service.delete(securityCtx, system, id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,19 @@
|
||||
package fr.titionfire.ffsaf.rest;
|
||||
|
||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||
import fr.titionfire.ffsaf.domain.service.PouleService;
|
||||
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.SecurityCtx;
|
||||
import io.quarkus.security.Authenticated;
|
||||
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 java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
// @Authenticated
|
||||
@Authenticated
|
||||
@Path("api/poule/{system}/")
|
||||
public class PouleEndpoints {
|
||||
|
||||
@ -29,16 +26,12 @@ public class PouleEndpoints {
|
||||
@Inject
|
||||
SecurityCtx securityCtx;
|
||||
|
||||
Consumer<ClubModel> checkPerm = Unchecked.consumer(clubModel -> {
|
||||
if (!securityCtx.roleHas("federation_admin") && !securityCtx.isInClubGroup(clubModel.getId()))
|
||||
throw new DForbiddenException();
|
||||
});
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<PouleData> getById(@PathParam("id") Long id) {
|
||||
return service.getById(checkPerm, system, id);
|
||||
return service.getById(securityCtx, system, id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@ -51,20 +44,20 @@ public class PouleEndpoints {
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<PouleData> addOrUpdate(PouleData data) {
|
||||
return service.addOrUpdate(checkPerm, system, data);
|
||||
return service.addOrUpdate(securityCtx, system, data);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("sync")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Uni<?> syncPoule(PouleFullData data) {
|
||||
return service.syncPoule(system, data);
|
||||
return service.syncPoule(securityCtx, system, data);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<?> delete(@PathParam("id") Long id) {
|
||||
return service.delete(checkPerm, system, id);
|
||||
return service.delete(securityCtx, system, id);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user