From 54e72cc705fcfa393f95347a738a0245371f28b4 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Thu, 3 Jul 2025 17:12:22 +0200 Subject: [PATCH] feat: refacto update membre wip: Logger --- .../ffsaf/domain/service/LoggerService.java | 4 - .../ffsaf/domain/service/MembreService.java | 118 ++++++++++-------- .../ffsaf/rest/MembreClubEndpoints.java | 3 +- .../ffsaf/rest/from/ClubMemberForm.java | 72 ----------- .../ffsaf/rest/from/FullMemberForm.java | 14 +-- 5 files changed, 67 insertions(+), 144 deletions(-) delete mode 100644 src/main/java/fr/titionfire/ffsaf/rest/from/ClubMemberForm.java diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/LoggerService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/LoggerService.java index f658850..0e73c54 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/LoggerService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/LoggerService.java @@ -30,7 +30,6 @@ public class LoggerService { private final List buffer = new ArrayList<>(); public Uni logA(ActionType action, ObjectType object, String message, String target_name, Long target_id) { - System.out.println("log"); return Panache.withTransaction(() -> repository.persist( new LogModel(null, securityCtx.getSubject(), new Date(), action, object, target_id, target_name, message))); @@ -49,7 +48,6 @@ public class LoggerService { } public Uni logAChange(String champ, Object o1, Object o2, LoggableModel model) { - System.out.println(o1 + " " + o2); if (Objects.equals(o1, o2)) return Uni.createFrom().nullItem(); return logA(ActionType.UPDATE, champ + ": " + o1.toString() + " -> " + o2.toString(), model); @@ -69,7 +67,6 @@ public class LoggerService { } public void log(ActionType action, ObjectType object, String message, String target_name, Long target_id) { - System.out.println("log"); buffer.add(new LogModel(null, securityCtx.getSubject(), new Date(), action, object, target_id, target_name, message)); } @@ -87,7 +84,6 @@ public class LoggerService { } public void logChange(String champ, Object o1, Object o2, LoggableModel model) { - System.out.println(o1 + " " + o2); if (Objects.equals(o1, o2)) return; log(ActionType.UPDATE, champ + ": " + o1.toString() + " -> " + o2.toString(), model); 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 e3614be..6d01875 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java @@ -14,7 +14,6 @@ import fr.titionfire.ffsaf.rest.data.SimpleMembreInOutData; import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.exception.DNotFoundException; -import fr.titionfire.ffsaf.rest.from.ClubMemberForm; import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.utils.*; import io.quarkus.hibernate.reactive.panache.Panache; @@ -181,7 +180,6 @@ public class MembreService { }); boolean add = model.getId() == null; - Uni log = Uni.createFrom().voidItem(); if ((!add && StringSimilarity.similarity(model.getLname().toUpperCase(), dataIn.getNom().toUpperCase()) > 3) || (!add && StringSimilarity.similarity( @@ -256,26 +254,68 @@ public class MembreService { } public Uni update(long id, FullMemberForm membre) { - return repository.findById(id) + return update(repository.findById(id) .chain(membreModel -> clubRepository.findById(membre.getClub()) .map(club -> new Pair<>(membreModel, club))) - .onItem().transformToUni(pair -> { + .onItem().transform(pair -> { MembreModel m = pair.getKey(); - m.setFname(membre.getFname()); - m.setLname(membre.getLname().toUpperCase()); - m.setClub(pair.getValue()); - m.setCountry(membre.getCountry()); - m.setBirth_date(membre.getBirth_date()); - m.setGenre(membre.getGenre()); - m.setCategorie(membre.getCategorie()); + + ls.logChange("Rôle", m.getRole(), membre.getRole(), m); m.setRole(membre.getRole()); + ls.logChange("Club", m.getClub(), pair.getValue(), m); + m.setClub(pair.getValue()); + ls.logChange("Grade d'arbitrage", m.getGrade_arbitrage(), membre.getGrade_arbitrage(), m); m.setGrade_arbitrage(membre.getGrade_arbitrage()); - m.setEmail(membre.getEmail()); - return Panache.withTransaction(() -> repository.persist(m)); + return m; + }), membre, true); + } + + public Uni update(long id, FullMemberForm membre, SecurityCtx securityCtx) { + return update(repository.findById(id) + .invoke(Unchecked.consumer(membreModel -> { + if (!securityCtx.isInClubGroup(membreModel.getClub().getId())) + throw new DForbiddenException(); + })) + .invoke(Unchecked.consumer(membreModel -> { + RoleAsso source = RoleAsso.MEMBRE; + 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"); + })) + .onItem().transform(target -> { + if (!securityCtx.getSubject().equals(target.getUserId())) { + ls.logChange("Rôle", target.getRole(), membre.getRole(), target); + target.setRole(membre.getRole()); + } + return target; + }), membre, false); + } + + private Uni update(Uni uni, FullMemberForm membre, boolean admin) { + return uni.chain(target -> { + ls.logChange("Prénom", target.getFname(), membre.getFname(), target); + target.setFname(membre.getFname()); + ls.logChange("Nom", target.getLname(), membre.getLname(), target); + target.setLname(membre.getLname().toUpperCase()); + ls.logChange("Pays", target.getCountry(), membre.getCountry(), target); + target.setCountry(membre.getCountry()); + if (!Objects.equals(target.getBirth_date().getTime(), membre.getBirth_date().getTime())) { + ls.logChange("Date de naissance", target.getBirth_date(), membre.getBirth_date(), target); + target.setBirth_date(membre.getBirth_date()); + target.setCategorie(Utils.getCategoryFormBirthDate(membre.getBirth_date(), new Date())); + } + ls.logChange("Genre", target.getGenre(), membre.getGenre(), target); + target.setGenre(membre.getGenre()); + ls.logChange("Email", target.getEmail(), membre.getEmail(), target); + target.setEmail(membre.getEmail()); + + return Panache.withTransaction(() -> repository.persist(target)).call(() -> ls.append()); }) .invoke(membreModel -> SReqComb.sendIfNeed(serverCustom.clients, SimpleCombModel.fromModel(membreModel))) - .call(membreModel -> (membreModel.getUserId() != null) ? + .call(membreModel -> (admin && membreModel.getUserId() != null) ? ((membreModel.getClub() != null) ? keycloakService.setClubGroupMembre(membreModel, membreModel.getClub()) : keycloakService.clearUser(membreModel.getUserId())) @@ -292,7 +332,7 @@ public class MembreService { Date dateLimit = calendar.getTime(); return competitionRepository.list("date > ?1", dateLimit) - .call(l -> + .call(l -> l.isEmpty() ? Uni.createFrom().nullItem() : Uni.join().all(l.stream().map(competitionModel -> registerRepository.update( "categorie = ?1, club = ?2 where competition = ?3 AND membre = ?4", @@ -300,45 +340,11 @@ public class MembreService { membreModel) ).toList()).andFailFast()); }) + .call(membreModel -> membre.getPhoto_data().length > 0 ? ls.logAUpdate("Photo", + membreModel) : Uni.createFrom().nullItem()) .map(__ -> "OK"); } - public Uni update(long id, ClubMemberForm membre, SecurityCtx securityCtx) { - return repository.findById(id) - .invoke(Unchecked.consumer(membreModel -> { - if (!securityCtx.isInClubGroup(membreModel.getClub().getId())) - throw new DForbiddenException(); - })) - .invoke(Unchecked.consumer(membreModel -> { - RoleAsso source = RoleAsso.MEMBRE; - 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"); - })) - .onItem().transformToUni(target -> { - target.setFname(membre.getFname()); - target.setLname(membre.getLname().toUpperCase()); - target.setCountry(membre.getCountry()); - target.setBirth_date(membre.getBirth_date()); - target.setGenre(membre.getGenre()); - target.setCategorie(membre.getCategorie()); - target.setEmail(membre.getEmail()); - if (!securityCtx.getSubject().equals(target.getUserId())) - target.setRole(membre.getRole()); - return Panache.withTransaction(() -> repository.persist(target)); - }) - .invoke(membreModel -> SReqComb.sendIfNeed(serverCustom.clients, - SimpleCombModel.fromModel(membreModel))) - .call(membreModel -> (membreModel.getUserId() != null) ? - keycloakService.setAutoRoleMembre(membreModel.getUserId(), membreModel.getRole(), - membreModel.getGrade_arbitrage()) : Uni.createFrom().nullItem()) - .call(membreModel -> (membreModel.getUserId() != null) ? - keycloakService.setEmail(membreModel.getUserId(), membreModel.getEmail()) : Uni.createFrom() - .nullItem()) - .map(__ -> "OK"); - } public Uni add(FullMemberForm input) { return clubRepository.findById(input.getClub()) @@ -346,6 +352,7 @@ public class MembreService { MembreModel model = getMembreModel(input, clubModel); return Panache.withTransaction(() -> repository.persist(model)); }) + .call(membreModel -> ls.logAAdd(membreModel)) .invoke(membreModel -> SReqComb.sendIfNeedAdd(serverCustom.clients, SimpleCombModel.fromModel(membreModel))) .map(MembreModel::getId); @@ -359,6 +366,7 @@ public class MembreService { model.setGrade_arbitrage(GradeArbitrage.NA); return Panache.withTransaction(() -> repository.persist(model)); }) + .call(membreModel -> ls.logAAdd(membreModel)) .invoke(membreModel -> SReqComb.sendIfNeedAdd(serverCustom.clients, SimpleCombModel.fromModel(membreModel))) .map(MembreModel::getId); @@ -368,6 +376,7 @@ public class MembreService { return repository.findById(id) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.removeAccount(membreModel.getUserId()) : Uni.createFrom().nullItem()) + .call(membreModel -> ls.logADelete(membreModel)) .call(membreModel -> Panache.withTransaction(() -> repository.delete(membreModel))) .invoke(membreModel -> SReqComb.sendRm(serverCustom.clients, id)) .map(__ -> "Ok"); @@ -392,6 +401,7 @@ public class MembreService { }))) .call(membreModel -> (membreModel.getUserId() != null) ? keycloakService.removeAccount(membreModel.getUserId()) : Uni.createFrom().nullItem()) + .call(membreModel -> ls.logADelete(membreModel)) .call(membreModel -> Panache.withTransaction(() -> repository.delete(membreModel))) .invoke(membreModel -> SReqComb.sendRm(serverCustom.clients, id)) .call(__ -> Utils.deleteMedia(id, media, "ppMembre")) @@ -400,8 +410,10 @@ public class MembreService { public Uni setUserId(Long id, String id1) { return repository.findById(id).chain(membreModel -> { + ls.logChange("KC UUID", membreModel.getUserId(), id1, membreModel); membreModel.setUserId(id1); - return Panache.withTransaction(() -> repository.persist(membreModel)); + return Panache.withTransaction(() -> repository.persist(membreModel)) + .call(() -> ls.append()); }); } @@ -414,7 +426,7 @@ public class MembreService { model.setGenre(input.getGenre()); model.setCountry(input.getCountry()); model.setBirth_date(input.getBirth_date()); - model.setCategorie(input.getCategorie()); + model.setCategorie(Utils.getCategoryFormBirthDate(input.getBirth_date(), new Date())); model.setClub(clubModel); model.setRole(input.getRole()); model.setGrade_arbitrage(input.getGrade_arbitrage()); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java index b8f50ec..2c6a3ce 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreClubEndpoints.java @@ -4,7 +4,6 @@ import fr.titionfire.ffsaf.domain.service.MembreService; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.data.SimpleMembreInOutData; 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; @@ -99,7 +98,7 @@ public class MembreClubEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni setMembre( - @Parameter(description = "Identifiant de membre") @PathParam("id") long id, ClubMemberForm input) { + @Parameter(description = "Identifiant de membre") @PathParam("id") long id, FullMemberForm input) { return membreService.update(id, input, securityCtx) .invoke(Unchecked.consumer(out -> { if (!out.equals("OK")) throw new InternalError("Fail to update data: " + out); diff --git a/src/main/java/fr/titionfire/ffsaf/rest/from/ClubMemberForm.java b/src/main/java/fr/titionfire/ffsaf/rest/from/ClubMemberForm.java deleted file mode 100644 index d65f4bc..0000000 --- a/src/main/java/fr/titionfire/ffsaf/rest/from/ClubMemberForm.java +++ /dev/null @@ -1,72 +0,0 @@ -package fr.titionfire.ffsaf.rest.from; - -import fr.titionfire.ffsaf.utils.Categorie; -import fr.titionfire.ffsaf.utils.Genre; -import fr.titionfire.ffsaf.utils.RoleAsso; -import jakarta.ws.rs.FormParam; -import jakarta.ws.rs.core.MediaType; -import lombok.Getter; -import org.eclipse.microprofile.openapi.annotations.media.Schema; -import org.jboss.resteasy.reactive.PartType; - -import java.util.Date; - -@Getter -public class ClubMemberForm { - @Schema(description = "L'identifiant du membre.", example = "1234567", required = true) - @FormParam("id") - private String id = null; - - @Schema(description = "Le nom du membre.", example = "Dupont", required = true) - @FormParam("lname") - private String lname = null; - - @Schema(description = "Le prénom du membre.", example = "Jean", required = true) - @FormParam("fname") - private String fname = null; - - @Schema(description = "La catégorie du membre.", example = "SENIOR", required = true) - @FormParam("categorie") - private Categorie categorie = null; - - @Schema(description = "Le genre du membre.", example = "H", required = true) - @FormParam("genre") - private Genre genre; - - @Schema(description = "Le pays du membre.", example = "FR", required = true) - @FormParam("country") - private String country; - - @Schema(description = "La date de naissance du membre.", required = true) - @FormParam("birth_date") - private Date birth_date; - - @Schema(description = "L'adresse e-mail du membre.", example = "jean.dupont@example.com", required = true) - @FormParam("email") - private String email; - - @Schema(description = "Le rôle du membre dans l'association.", example = "MEMBRE", required = true) - @FormParam("role") - private RoleAsso role; - - @Schema(description = "La photo du membre.") - @FormParam("photo_data") - @PartType(MediaType.APPLICATION_OCTET_STREAM) - private byte[] photo_data = new byte[0]; - - @Override - public String toString() { - return "ClubMemberForm{" + - "id='" + id + '\'' + - ", lname='" + lname + '\'' + - ", fname='" + fname + '\'' + - ", categorie=" + categorie + - ", genre=" + genre + - ", country='" + country + '\'' + - ", birth_date=" + birth_date + - ", email='" + email + '\'' + - ", role=" + role + - ", url_photo=" + photo_data.length + - '}'; - } -} diff --git a/src/main/java/fr/titionfire/ffsaf/rest/from/FullMemberForm.java b/src/main/java/fr/titionfire/ffsaf/rest/from/FullMemberForm.java index e08aa2d..5f67731 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/from/FullMemberForm.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/from/FullMemberForm.java @@ -1,6 +1,5 @@ package fr.titionfire.ffsaf.rest.from; -import fr.titionfire.ffsaf.utils.Categorie; import fr.titionfire.ffsaf.utils.Genre; import fr.titionfire.ffsaf.utils.GradeArbitrage; import fr.titionfire.ffsaf.utils.RoleAsso; @@ -26,10 +25,6 @@ public class FullMemberForm { @FormParam("fname") private String fname = null; - @Schema(description = "La catégorie du membre.", example = "SENIOR") - @FormParam("categorie") - private Categorie categorie = null; - @Schema(description = "L'identifiant du club du membre.", example = "1") @FormParam("club") private Long club = null; @@ -38,10 +33,6 @@ public class FullMemberForm { @FormParam("genre") private Genre genre; - @Schema(description = "Le numéro de licence du membre.", example = "12345") - @FormParam("licence") - private int licence; - @Schema(description = "Le pays du membre.", example = "FR") @FormParam("country") private String country; @@ -60,7 +51,7 @@ public class FullMemberForm { @Schema(description = "Le grade d'arbitrage du membre.", example = "ASSESSEUR") @FormParam("grade_arbitrage") - private GradeArbitrage grade_arbitrage; + private GradeArbitrage grade_arbitrage = GradeArbitrage.NA; @Schema(description = "La photo du membre.") @FormParam("photo_data") @@ -73,11 +64,8 @@ public class FullMemberForm { "id='" + id + '\'' + ", lname='" + lname + '\'' + ", fname='" + fname + '\'' + - ", categorie=" + categorie + ", club=" + club + ", genre=" + genre + - ", licence=" + licence + - ", country='" + country + '\'' + ", birth_date=" + birth_date + ", email='" + email + '\'' + ", role=" + role +