feat: refacto update membre

wip: Logger
This commit is contained in:
Thibaut Valentin 2025-07-03 17:12:22 +02:00
parent ad58958f49
commit 54e72cc705
5 changed files with 67 additions and 144 deletions

View File

@ -30,7 +30,6 @@ public class LoggerService {
private final List<LogModel> 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);

View File

@ -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<Void> 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<String> 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<String> 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<String> update(Uni<MembreModel> 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<String> 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<Long> 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());

View File

@ -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<String> 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);

View File

@ -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 +
'}';
}
}

View File

@ -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 +