612 lines
33 KiB
Java
612 lines
33 KiB
Java
package fr.titionfire.ffsaf.domain.service;
|
|
|
|
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
|
import fr.titionfire.ffsaf.data.model.HelloAssoRegisterModel;
|
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
|
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
|
import fr.titionfire.ffsaf.data.repository.*;
|
|
import fr.titionfire.ffsaf.net2.ServerCustom;
|
|
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
|
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
|
import fr.titionfire.ffsaf.net2.request.SReqRegister;
|
|
import fr.titionfire.ffsaf.rest.client.dto.NotificationData;
|
|
import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
|
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
|
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
|
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
|
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.RegisterMode;
|
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
|
import fr.titionfire.ffsaf.utils.Utils;
|
|
import io.quarkus.cache.Cache;
|
|
import io.quarkus.cache.CacheName;
|
|
import io.quarkus.hibernate.reactive.panache.Panache;
|
|
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
|
import io.quarkus.mailer.Mail;
|
|
import io.quarkus.mailer.reactive.ReactiveMailer;
|
|
import io.smallrye.mutiny.Multi;
|
|
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 jakarta.ws.rs.NotFoundException;
|
|
import jakarta.ws.rs.core.Response;
|
|
import org.hibernate.reactive.mutiny.Mutiny;
|
|
import org.jboss.logging.Logger;
|
|
import org.keycloak.representations.idm.UserRepresentation;
|
|
|
|
import java.util.*;
|
|
import java.util.stream.Stream;
|
|
|
|
@WithSession
|
|
@ApplicationScoped
|
|
public class CompetitionService {
|
|
private static final Logger LOGGER = Logger.getLogger(CompetitionService.class);
|
|
|
|
@Inject
|
|
CompetitionRepository repository;
|
|
|
|
@Inject
|
|
CategoryRepository categoryRepository;
|
|
|
|
@Inject
|
|
MatchRepository matchRepository;
|
|
|
|
@Inject
|
|
RegisterRepository registerRepository;
|
|
|
|
@Inject
|
|
KeycloakService keycloakService;
|
|
|
|
@Inject
|
|
CombRepository combRepository;
|
|
|
|
@Inject
|
|
ServerCustom serverCustom;
|
|
|
|
@Inject
|
|
MembreService membreService;
|
|
|
|
@Inject
|
|
CompetPermService permService;
|
|
|
|
@Inject
|
|
HelloAssoRegisterRepository helloAssoRepository;
|
|
|
|
@SuppressWarnings("CdiInjectionPointsInspection")
|
|
@Inject
|
|
ReactiveMailer reactiveMailer;
|
|
|
|
@Inject
|
|
Vertx vertx;
|
|
|
|
@Inject
|
|
@CacheName("safca-config")
|
|
Cache cache;
|
|
|
|
@Inject
|
|
@CacheName("safca-have-access")
|
|
Cache cacheAccess;
|
|
|
|
@Inject
|
|
@CacheName("have-access")
|
|
Cache cacheNoneAccess;
|
|
|
|
public Uni<CompetitionData> getById(SecurityCtx securityCtx, Long id) {
|
|
return permService.hasViewPerm(securityCtx, id).map(CompetitionData::fromModelLight);
|
|
}
|
|
|
|
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
|
if (id == 0) {
|
|
return Uni.createFrom()
|
|
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
|
CompetitionSystem.NONE, RegisterMode.FREE, new Date(), new Date(), true,
|
|
null, "", "", null, true, "", "", "", ""));
|
|
}
|
|
return permService.hasAdminViewPerm(securityCtx, id)
|
|
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
|
.map(insc -> CompetitionData.fromModel(competitionModel).addInsc(insc)))
|
|
.chain(data ->
|
|
vertx.getOrCreateContext().executeBlocking(() -> {
|
|
keycloakService.getUser(UUID.fromString(data.getOwner()))
|
|
.ifPresent(user -> data.setOwner(user.getUsername()));
|
|
return data;
|
|
})
|
|
);
|
|
}
|
|
|
|
public Uni<List<CompetitionData>> getAll(SecurityCtx securityCtx) {
|
|
List<CompetitionData> out = new ArrayList<>();
|
|
return permService.getAllHaveAdminAccess(securityCtx)
|
|
.call(ids -> repository.list("id IN ?1", ids)
|
|
.invoke(cm -> {
|
|
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList());
|
|
out.forEach(competition -> competition.setCanEdit(true));
|
|
}))
|
|
.call(ids ->
|
|
repository.list("id NOT IN ?1 AND (publicVisible = TRUE OR registerMode IN ?2)", ids,
|
|
securityCtx.isClubAdmin() ? List.of(RegisterMode.FREE, RegisterMode.HELLOASSO,
|
|
RegisterMode.CLUB_ADMIN) : List.of(RegisterMode.FREE, RegisterMode.HELLOASSO))
|
|
.invoke(cm -> out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList()))
|
|
.call(cm -> registerRepository.list(
|
|
"membre.userId = ?1 AND competition.id NOT IN ?2 AND competition NOT IN ?3",
|
|
securityCtx.getSubject(), ids, cm)
|
|
.chain(registerModels -> {
|
|
Uni<Void> uni = Uni.createFrom().nullItem();
|
|
for (RegisterModel registerModel : registerModels) {
|
|
uni = uni.call(__ -> Mutiny.fetch(registerModel.getCompetition())
|
|
.invoke(cm2 -> out.add(CompetitionData.fromModelLight(cm2))));
|
|
}
|
|
return uni;
|
|
})
|
|
))
|
|
.map(__ -> out);
|
|
}
|
|
|
|
public Uni<List<CompetitionData>> getAllAdmin(SecurityCtx securityCtx) {
|
|
return permService.getAllHaveAdminAccess(securityCtx)
|
|
.chain(ids -> repository.list("id IN ?1", ids))
|
|
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
|
}
|
|
|
|
public Uni<List<CompetitionData>> getAllSystemAdmin(SecurityCtx securityCtx,
|
|
CompetitionSystem system) {
|
|
return permService.getAllHaveAdminAccess(securityCtx)
|
|
.chain(ids -> repository.list("system = ?1 AND id IN ?2", system, ids))
|
|
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
|
}
|
|
|
|
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
|
|
if (data.getId() == null) {
|
|
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
|
|
.invoke(Unchecked.consumer(combModel -> {
|
|
if (!securityCtx.getRoles().contains("create_compet") && !securityCtx.getRoles()
|
|
.contains("federation_admin"))
|
|
throw new DForbiddenException("Vous ne pouvez pas créer de compétition");
|
|
}))
|
|
.map(MembreModel::getClub)
|
|
.chain(clubModel -> {
|
|
CompetitionModel model = new CompetitionModel();
|
|
|
|
model.setId(null);
|
|
model.setSystem(data.getSystem());
|
|
model.setClub(clubModel);
|
|
model.setInsc(new ArrayList<>());
|
|
model.setUuid(UUID.randomUUID().toString());
|
|
model.setOwner(securityCtx.getSubject());
|
|
|
|
copyData(data, model);
|
|
|
|
return Panache.withTransaction(() -> repository.persist(model));
|
|
}).map(CompetitionData::fromModel)
|
|
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
|
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
|
.call(c -> (c.getSystem() == CompetitionSystem.NONE) ? cacheNoneAccess.invalidate(
|
|
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
|
} else {
|
|
return permService.hasEditPerm(securityCtx, data.getId())
|
|
.chain(model -> {
|
|
copyData(data, model);
|
|
|
|
return vertx.getOrCreateContext().executeBlocking(() -> // Update owner
|
|
keycloakService.getUser(data.getOwner()).map(UserRepresentation::getId).orElse(null))
|
|
.invoke(Unchecked.consumer(newOwner -> {
|
|
if (newOwner == null)
|
|
throw new DBadRequestException("User " + data.getOwner() + " not found");
|
|
if (!newOwner.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(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
|
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
|
.call(c -> (c.getSystem() == CompetitionSystem.NONE) ? cacheNoneAccess.invalidate(
|
|
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
|
}
|
|
}
|
|
|
|
private void copyData(CompetitionData data, CompetitionModel model) {
|
|
if (model.getBanMembre() == null)
|
|
model.setBanMembre(new ArrayList<>());
|
|
|
|
model.setName(data.getName());
|
|
model.setAdresse(data.getAdresse());
|
|
model.setDescription(data.getDescription());
|
|
model.setDate(data.getDate());
|
|
model.setTodate(data.getDate());
|
|
model.setPublicVisible(data.isPublicVisible());
|
|
model.setStartRegister(data.getStartRegister());
|
|
model.setEndRegister(data.getEndRegister());
|
|
model.setRegisterMode(data.getRegisterMode());
|
|
model.setData1(data.getData1());
|
|
model.setData2(data.getData2());
|
|
model.setData3(data.getData3());
|
|
model.setData4(data.getData4());
|
|
}
|
|
|
|
public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id, String source) {
|
|
if ("admin".equals(source))
|
|
return permService.hasEditPerm(securityCtx, id)
|
|
.chain(c -> Mutiny.fetch(c.getInsc()))
|
|
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
|
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
|
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences()))
|
|
.collect().asList();
|
|
if ("club".equals(source))
|
|
return Uni.createFrom().nullItem()
|
|
.invoke(Unchecked.consumer(__ -> {
|
|
if (!securityCtx.isClubAdmin())
|
|
throw new DForbiddenException();
|
|
}))
|
|
.chain(__ -> membreService.getByAccountId(securityCtx.getSubject()))
|
|
.chain(model -> registerRepository.list("competition.id = ?1 AND membre.club = ?2", id,
|
|
model.getClub()))
|
|
.onItem().transformToMulti(Multi.createFrom()::iterable)
|
|
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
|
|
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences()))
|
|
.collect().asList();
|
|
|
|
return membreService.getByAccountId(securityCtx.getSubject())
|
|
.chain(model -> registerRepository.find("competition.id = ?1 AND membre = ?2", id, model).firstResult()
|
|
.map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of()))));
|
|
}
|
|
|
|
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data,
|
|
String source) {
|
|
if ("admin".equals(source))
|
|
return permService.hasEditPerm(securityCtx, id)
|
|
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
|
.call(combModel -> {
|
|
if (c.getBanMembre() == null)
|
|
c.setBanMembre(new ArrayList<>());
|
|
c.getBanMembre().remove(combModel.getId());
|
|
return Panache.withTransaction(() -> repository.persist(c));
|
|
})
|
|
.chain(combModel -> updateRegister(data, c, combModel, true)))
|
|
.chain(r -> Mutiny.fetch(r.getMembre().getLicences())
|
|
.map(licences -> SimpleRegisterComb.fromModel(r, licences)));
|
|
if ("club".equals(source))
|
|
return repository.findById(id)
|
|
.invoke(Unchecked.consumer(cm -> {
|
|
if (!(cm.getRegisterMode() == RegisterMode.CLUB_ADMIN || cm.getRegisterMode() == RegisterMode.FREE)
|
|
|| !securityCtx.isClubAdmin())
|
|
throw new DForbiddenException();
|
|
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
|
throw new DBadRequestException("Inscription fermée");
|
|
}))
|
|
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
|
|
.invoke(Unchecked.consumer(model -> {
|
|
if (!securityCtx.isInClubGroup(model.getClub().getId()))
|
|
throw new DForbiddenException();
|
|
if (c.getBanMembre().contains(model.getId()))
|
|
throw new DForbiddenException(
|
|
"Vous n'avez pas le droit d'inscrire ce membre (par décision de l'administrateur de la compétition)");
|
|
}))
|
|
.chain(combModel -> updateRegister(data, c, combModel, false)))
|
|
.chain(r -> Mutiny.fetch(r.getMembre().getLicences())
|
|
.map(licences -> SimpleRegisterComb.fromModel(r, licences)));
|
|
|
|
return repository.findById(id)
|
|
.invoke(Unchecked.consumer(cm -> {
|
|
if (cm.getRegisterMode() != RegisterMode.FREE)
|
|
throw new DForbiddenException();
|
|
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
|
throw new DBadRequestException("Inscription fermée");
|
|
}))
|
|
.chain(c -> membreService.getByAccountId(securityCtx.getSubject())
|
|
.invoke(Unchecked.consumer(model -> {
|
|
if (c.getBanMembre().contains(model.getId()))
|
|
throw new DForbiddenException(
|
|
"Vous n'avez pas le droit de vous inscrire (par décision de l'administrateur de la compétition)");
|
|
}))
|
|
.chain(combModel -> updateRegister(data, c, combModel, false)))
|
|
.map(r -> SimpleRegisterComb.fromModel(r, List.of()));
|
|
}
|
|
|
|
private Uni<RegisterModel> updateRegister(RegisterRequestData data, CompetitionModel c,
|
|
MembreModel combModel, boolean admin) {
|
|
return registerRepository.find("competition = ?1 AND membre = ?2", c, combModel).firstResult()
|
|
.onFailure().recoverWithNull()
|
|
.map(Unchecked.function(r -> {
|
|
if (r != null) {
|
|
if (!admin && r.isLockEdit())
|
|
throw new DForbiddenException(
|
|
"Modification bloquée par l'administrateur de la compétition");
|
|
r.setWeight(data.getWeight());
|
|
r.setOverCategory(data.getOverCategory());
|
|
r.setCategorie(
|
|
(combModel.getBirth_date() == null) ? combModel.getCategorie() :
|
|
Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
|
|
c.getDate()));
|
|
int days = Utils.getDaysBeforeCompetition(c.getDate());
|
|
if (days > -7)
|
|
r.setClub(combModel.getClub());
|
|
if (admin)
|
|
r.setLockEdit(data.isLockEdit());
|
|
} else {
|
|
r = new RegisterModel(c, combModel, data.getWeight(), data.getOverCategory(),
|
|
(combModel.getBirth_date() == null) ? combModel.getCategorie() :
|
|
Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
|
|
c.getDate()),
|
|
(combModel.getClub() == null) ? null : combModel.getClub());
|
|
if (admin)
|
|
r.setLockEdit(data.isLockEdit());
|
|
else
|
|
r.setLockEdit(false);
|
|
}
|
|
|
|
if (c.getSystem() == CompetitionSystem.SAFCA) {
|
|
SReqRegister.sendIfNeed(serverCustom.clients,
|
|
new CompetitionData.SimpleRegister(r.getMembre().getId(),
|
|
r.getOverCategory(), r.getWeight(), r.getCategorie(),
|
|
(r.getClub() == null) ? null : r.getClub().getId()), c.getId());
|
|
}
|
|
return r;
|
|
}))
|
|
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r)));
|
|
}
|
|
|
|
private Uni<MembreModel> findComb(Long licence, String fname, String lname) {
|
|
if (licence != null && licence != 0) {
|
|
return combRepository.find("licence = ?1", licence).firstResult()
|
|
.invoke(Unchecked.consumer(combModel -> {
|
|
if (combModel == null)
|
|
throw new DForbiddenException("Licence " + licence + " non trouvé");
|
|
}));
|
|
} else {
|
|
if (fname == null || lname == null)
|
|
return Uni.createFrom().failure(new DBadRequestException("Nom et prénom requis"));
|
|
return combRepository.find("unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2)",
|
|
lname,
|
|
fname).firstResult()
|
|
.invoke(Unchecked.consumer(combModel -> {
|
|
if (combModel == null)
|
|
throw new DForbiddenException("Combattant " + fname + " " + lname + " non trouvé");
|
|
}));
|
|
}
|
|
}
|
|
|
|
public Uni<Void> removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId, String source, boolean ban) {
|
|
if ("admin".equals(source))
|
|
return permService.hasEditPerm(securityCtx, id)
|
|
.chain(cm -> {
|
|
if (cm.getBanMembre() == null)
|
|
cm.setBanMembre(new ArrayList<>());
|
|
if (ban) {
|
|
if (!cm.getBanMembre().contains(combId))
|
|
cm.getBanMembre().add(combId);
|
|
} else {
|
|
cm.getBanMembre().remove(combId);
|
|
}
|
|
return Panache.withTransaction(() -> repository.persist(cm));
|
|
})
|
|
.chain(c -> deleteRegister(combId, c, true));
|
|
if ("club".equals(source))
|
|
return repository.findById(id)
|
|
.invoke(Unchecked.consumer(cm -> {
|
|
if (!(cm.getRegisterMode() == RegisterMode.CLUB_ADMIN || cm.getRegisterMode() == RegisterMode.FREE)
|
|
|| !securityCtx.isClubAdmin())
|
|
throw new DForbiddenException();
|
|
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
|
throw new DBadRequestException("Inscription fermée");
|
|
}))
|
|
.call(cm -> membreService.getByAccountId(securityCtx.getSubject())
|
|
.invoke(Unchecked.consumer(model -> {
|
|
if (!securityCtx.isInClubGroup(model.getClub().getId()))
|
|
throw new DForbiddenException();
|
|
})))
|
|
.chain(c -> deleteRegister(combId, c, false));
|
|
|
|
return repository.findById(id)
|
|
.invoke(Unchecked.consumer(cm -> {
|
|
if (cm.getRegisterMode() != RegisterMode.FREE)
|
|
throw new DForbiddenException();
|
|
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
|
|
throw new DBadRequestException("Inscription fermée");
|
|
}))
|
|
.chain(c -> deleteRegister(combId, c, false));
|
|
}
|
|
|
|
private Uni<Void> deleteRegister(Long combId, CompetitionModel c, boolean admin) {
|
|
return registerRepository.find("competition = ?1 AND membre.id = ?2", c, combId).firstResult()
|
|
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
|
|
.call(Unchecked.function(registerModel -> {
|
|
if (!admin && registerModel.isLockEdit())
|
|
throw new DForbiddenException("Modification bloquée par l'administrateur de la compétition");
|
|
return Panache.withTransaction(() -> registerRepository.delete(registerModel));
|
|
}))
|
|
.replaceWithVoid();
|
|
}
|
|
|
|
public Uni<?> delete(SecurityCtx securityCtx, Long id) {
|
|
return repository.findById(id).invoke(Unchecked.consumer(c -> {
|
|
if (!(securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")))
|
|
throw new DForbiddenException();
|
|
}))
|
|
.call(competitionModel -> categoryRepository.list("compet = ?1", competitionModel)
|
|
.call(pouleModels -> pouleModels.isEmpty() ? Uni.createFrom().nullItem() :
|
|
Uni.join().all(pouleModels.stream()
|
|
.map(pouleModel -> Panache.withTransaction(
|
|
() -> matchRepository.delete("poule = ?1", pouleModel.getId())))
|
|
.toList())
|
|
.andCollectFailures()))
|
|
.call(competitionModel -> Panache.withTransaction(
|
|
() -> categoryRepository.delete("compet = ?1", competitionModel)))
|
|
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))
|
|
.invoke(o -> SReqCompet.rmCompet(serverCustom.clients, id))
|
|
.call(__ -> cache.invalidate(id));
|
|
}
|
|
|
|
public Uni<SimpleCompetData> getSafcaData(SecurityCtx securityCtx, Long id) {
|
|
return permService.getSafcaConfig(id)
|
|
.call(Unchecked.function(o -> {
|
|
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();
|
|
}))
|
|
.chain(simpleCompet -> {
|
|
SimpleCompetData data = SimpleCompetData.fromModel(simpleCompet);
|
|
return vertx.getOrCreateContext().executeBlocking(() -> {
|
|
data.setAdmin(simpleCompet.admin().stream().map(uuid -> keycloakService.getUser(uuid))
|
|
.filter(Optional::isPresent)
|
|
.map(user -> user.get().getUsername())
|
|
.toList());
|
|
data.setTable(simpleCompet.table().stream().map(uuid -> keycloakService.getUser(uuid))
|
|
.filter(Optional::isPresent)
|
|
.map(user -> user.get().getUsername())
|
|
.toList());
|
|
|
|
return data;
|
|
});
|
|
});
|
|
}
|
|
|
|
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<>();
|
|
for (String username : data.getAdmin()) {
|
|
Optional<UserRepresentation> opt = keycloakService.getUser(username);
|
|
if (opt.isEmpty())
|
|
throw new DBadRequestException("User " + username + " not found");
|
|
admin.add(UUID.fromString(opt.get().getId()));
|
|
}
|
|
for (String username : data.getTable()) {
|
|
Optional<UserRepresentation> opt = keycloakService.getUser(username);
|
|
if (opt.isEmpty())
|
|
throw new DBadRequestException("User " + username + " not found");
|
|
table.add(UUID.fromString(opt.get().getId()));
|
|
}
|
|
|
|
return new SimpleCompet(data.getId(), "", data.isShow_blason(),
|
|
data.isShow_flag(), admin, table);
|
|
}))
|
|
.invoke(simpleCompet -> SReqCompet.sendUpdate(serverCustom.clients, simpleCompet))
|
|
.call(simpleCompet -> permService.getSafcaConfig(data.getId())
|
|
.call(c -> {
|
|
List<Uni<Void>> list = Stream.concat(
|
|
Stream.concat(
|
|
c.admin().stream().filter(uuid -> !simpleCompet.admin().contains(uuid)),
|
|
simpleCompet.admin().stream().filter(uuid -> !c.admin().contains(uuid))),
|
|
Stream.concat(
|
|
c.table().stream().filter(uuid -> !simpleCompet.table().contains(uuid)),
|
|
simpleCompet.table().stream().filter(uuid -> !c.table().contains(uuid)))
|
|
).map(uuid -> cacheAccess.invalidate(uuid.toString())).toList();
|
|
|
|
if (list.isEmpty())
|
|
return Uni.createFrom().nullItem();
|
|
return Uni.join().all(list).andCollectFailures();
|
|
}))
|
|
.call(__ -> cache.invalidate(data.getId()));
|
|
}
|
|
|
|
public Uni<Response> unregisterHelloAsso(NotificationData data) {
|
|
if (!data.getState().equals("Refunded"))
|
|
return Uni.createFrom().item(Response.ok().build());
|
|
|
|
return helloAssoRepository.list("orderId = ?1", data.getOrder().getId())
|
|
.chain(regs -> {
|
|
Uni<?> uni = Uni.createFrom().nullItem();
|
|
|
|
for (HelloAssoRegisterModel reg : regs) {
|
|
if (reg.getCompetition().getRegisterMode() != RegisterMode.HELLOASSO)
|
|
continue;
|
|
if (!data.getOrder().getOrganizationSlug().equalsIgnoreCase(reg.getCompetition().getData1()))
|
|
continue;
|
|
|
|
uni = uni.call(__ -> Panache.withTransaction(
|
|
() -> registerRepository.delete("competition = ?1 AND membre = ?2",
|
|
reg.getCompetition(), reg.getMembre())));
|
|
}
|
|
|
|
return uni;
|
|
})
|
|
.onFailure().invoke(Throwable::printStackTrace)
|
|
.map(__ -> Response.ok().build());
|
|
}
|
|
|
|
public Uni<Response> registerHelloAsso(NotificationData data) {
|
|
String organizationSlug = data.getOrganizationSlug();
|
|
String formSlug = data.getFormSlug();
|
|
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false);
|
|
|
|
return repository.find("data1 = ?1 AND data2 = ?2", organizationSlug, formSlug).firstResult()
|
|
.onFailure().recoverWithNull()
|
|
.chain(cm -> {
|
|
Uni<?> uni = Uni.createFrom().nullItem();
|
|
if (cm == null || cm.getRegisterMode() != RegisterMode.HELLOASSO)
|
|
return uni;
|
|
|
|
List<String> place = List.of(cm.getData3().toLowerCase().split(";"));
|
|
List<String> fail = new ArrayList<>();
|
|
|
|
for (NotificationData.Item item : data.getItems()) {
|
|
if (!place.contains(item.getName().toLowerCase()))
|
|
continue;
|
|
if (item.getCustomFields() == null || item.getCustomFields().isEmpty()) {
|
|
fail.add("%s %s - licence n°???".formatted(item.getUser().getLastName(),
|
|
item.getUser().getFirstName()));
|
|
continue;
|
|
}
|
|
|
|
Optional<Long> optional = item.getCustomFields().stream()
|
|
.filter(cf -> cf.getName().equalsIgnoreCase("Numéro de licence")).findAny().map(
|
|
NotificationData.CustomField::getAnswer).map(Long::valueOf);
|
|
|
|
if (optional.isPresent()) {
|
|
uni = uni.call(__ -> membreService.getByLicence(optional.get())
|
|
.invoke(Unchecked.consumer(m -> {
|
|
if (m == null)
|
|
throw new NotFoundException();
|
|
}))
|
|
.call(m -> Panache.withTransaction(() ->
|
|
helloAssoRepository.persist(
|
|
new HelloAssoRegisterModel(cm, m, data.getId()))))
|
|
.chain(m -> updateRegister(req, cm, m, true)))
|
|
.onFailure().recoverWithItem(throwable -> {
|
|
fail.add("%s %s - licence n°%d".formatted(item.getUser().getLastName(),
|
|
item.getUser().getFirstName(), optional.get()));
|
|
return null;
|
|
})
|
|
.replaceWithVoid();
|
|
} else {
|
|
fail.add("%s %s - licence n°???".formatted(item.getUser().getLastName(),
|
|
item.getUser().getFirstName()));
|
|
}
|
|
}
|
|
|
|
return uni.call(__ -> fail.isEmpty() ? Uni.createFrom().nullItem() :
|
|
reactiveMailer.send(
|
|
Mail.withText(cm.getData4(),
|
|
"FFSAF - Compétition - Erreur HelloAsso",
|
|
String.format(
|
|
"""
|
|
Bonjour,
|
|
|
|
Une erreur a été rencontrée lors de l'enregistrement d'une inscription à votre compétition %s pour les combattants suivants:
|
|
%s
|
|
|
|
Cordialement,
|
|
L'intranet de la FFSAF
|
|
""", cm.getName(), String.join("\r\n", fail))
|
|
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
|
|
).onFailure().invoke(e -> LOGGER.error("Fail to send email", e)));
|
|
})
|
|
.onFailure().invoke(Throwable::printStackTrace)
|
|
.map(__ -> Response.ok().build());
|
|
}
|
|
}
|