Merge pull request 'dev' (#35) from dev into master

Reviewed-on: #35
This commit is contained in:
Thibaut Valentin 2025-03-11 11:16:18 +01:00
commit bda1a6ef2a
2 changed files with 28 additions and 18 deletions

View File

@ -2,7 +2,10 @@ package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.CompetitionModel; import fr.titionfire.ffsaf.data.model.CompetitionModel;
import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.data.model.MembreModel;
import fr.titionfire.ffsaf.data.repository.*; import fr.titionfire.ffsaf.data.repository.CombRepository;
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
import fr.titionfire.ffsaf.data.repository.MatchRepository;
import fr.titionfire.ffsaf.data.repository.PouleRepository;
import fr.titionfire.ffsaf.net2.ServerCustom; import fr.titionfire.ffsaf.net2.ServerCustom;
import fr.titionfire.ffsaf.net2.data.SimpleCompet; import fr.titionfire.ffsaf.net2.data.SimpleCompet;
import fr.titionfire.ffsaf.net2.request.SReqCompet; import fr.titionfire.ffsaf.net2.request.SReqCompet;
@ -13,6 +16,7 @@ import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb; import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.utils.CompetitionSystem; import fr.titionfire.ffsaf.utils.CompetitionSystem;
import fr.titionfire.ffsaf.utils.RegisterEmbeddable; import fr.titionfire.ffsaf.utils.RegisterEmbeddable;
import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.SecurityCtx;
@ -138,10 +142,15 @@ public class CompetitionService {
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) { public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
if (data.getId() == null) { if (data.getId() == null) {
return new ClubRepository().findById(data.getClub()).invoke(Unchecked.consumer(clubModel -> { return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
if (!securityCtx.isInClubGroup(clubModel.getId())) .invoke(Unchecked.consumer(combModel -> {
throw new DForbiddenException(); if (combModel == null)
})) // TODO check if user can create competition throw new DNotFoundException("Profile non trouvé");
if (data.getSystem() == CompetitionSystem.SAFCA)
if (!securityCtx.getRoles().contains("safca_create_compet"))
throw new DForbiddenException("Vous ne pouvez pas créer de compétition SAFCA");
}))
.map(MembreModel::getClub)
.chain(clubModel -> { .chain(clubModel -> {
CompetitionModel model = new CompetitionModel(); CompetitionModel model = new CompetitionModel();
@ -256,16 +265,16 @@ public class CompetitionService {
public Uni<?> delete(SecurityCtx securityCtx, Long id) { public Uni<?> delete(SecurityCtx securityCtx, Long id) {
return repository.findById(id).invoke(Unchecked.consumer(c -> { return repository.findById(id).invoke(Unchecked.consumer(c -> {
if (!securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")) if (!(securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")))
throw new DForbiddenException(); throw new DForbiddenException();
})) }))
.call(competitionModel -> pouleRepository.list("compet = ?1", competitionModel) .call(competitionModel -> pouleRepository.list("compet = ?1", competitionModel)
.call(pouleModels -> Uni.join() .call(pouleModels -> pouleModels.isEmpty() ? Uni.createFrom().nullItem() :
.all(pouleModels.stream() Uni.join().all(pouleModels.stream()
.map(pouleModel -> Panache.withTransaction( .map(pouleModel -> Panache.withTransaction(
() -> matchRepository.delete("poule = ?1", pouleModel.getId()))) () -> matchRepository.delete("poule = ?1", pouleModel.getId())))
.toList()) .toList())
.andCollectFailures())) .andCollectFailures()))
.call(competitionModel -> Panache.withTransaction( .call(competitionModel -> Panache.withTransaction(
() -> pouleRepository.delete("compet = ?1", competitionModel))) () -> pouleRepository.delete("compet = ?1", competitionModel)))
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId()))) .chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))

View File

@ -46,8 +46,8 @@ export function CompetitionEdit() {
<Content data={data} refresh={refresh}/> <Content data={data} refresh={refresh}/>
{data.id !== null && <button style={{marginBottom: "1.5em", width: "100%"}} className="btn btn-primary" {data.id !== null && <button style={{marginBottom: "1.5em", width: "100%"}} className="btn btn-primary"
onClick={_ => navigate(`/competition/${data.id}/register`)}>Voir/Modifier les participants</button>} onClick={_ => navigate(`/competition/${data.id}/register`)}>Voir/Modifier les participants</button>}
{data.id !== null && <ContentSAFCA data2={data}/>} {data.id !== null && <ContentSAFCA data2={data}/>}
@ -259,10 +259,11 @@ function Content({data}) {
<OptionField name="system" text="System" value={data.system} values={{SAFCA: 'SAFCA'}} disabled={data.id !== null}/> <OptionField name="system" text="System" value={data.system} values={{SAFCA: 'SAFCA'}} disabled={data.id !== null}/>
<div className="row"> {data.id !== null &&
<ClubSelect defaultValue={data.club} name="club" na={false} disabled={data.id !== null}/> <div className="row">
</div> <ClubSelect defaultValue={data.club} name="club" na={false} disabled={true}/>
</div>
}
</div> </div>
<div className="row mb-3"> <div className="row mb-3">