wip: LoggerService

This commit is contained in:
Thibaut Valentin 2025-07-02 23:07:01 +02:00
parent 0c4b88b5cd
commit ad58958f49
6 changed files with 212 additions and 31 deletions

View File

@ -0,0 +1,45 @@
package fr.titionfire.ffsaf.data.model;
import io.quarkus.runtime.annotations.RegisterForReflection;
import jakarta.persistence.*;
import lombok.*;
import java.util.Date;
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@RegisterForReflection
@Entity
@Table(name = "log")
public class LogModel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String subject;
Date dateTime;
ActionType action;
ObjectType object;
Long target_id;
String target_name;
String message;
public enum ActionType {
ADD, REMOVE, UPDATE
}
public enum ObjectType {
Membre, Affiliation, Licence, Club, Competition, Register
}
}

View File

@ -0,0 +1,7 @@
package fr.titionfire.ffsaf.data.model;
public interface LoggableModel {
Long getId();
String getObjectName();
LogModel.ObjectType getObjectType();
}

View File

@ -21,7 +21,7 @@ import java.util.List;
@Entity
@Table(name = "membre")
public class MembreModel {
public class MembreModel implements LoggableModel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ -72,4 +72,14 @@ public class MembreModel {
@OneToMany(mappedBy = "membre", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@Schema(description = "Les licences du membre. (optionnel)")
List<LicenceModel> licences;
@Override
public String getObjectName() {
return fname + " " + lname;
}
@Override
public LogModel.ObjectType getObjectType() {
return LogModel.ObjectType.Membre;
}
}

View File

@ -0,0 +1,9 @@
package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.LogModel;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class LogRepository implements PanacheRepositoryBase<LogModel, Long> {
}

View File

@ -0,0 +1,99 @@
package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.LogModel;
import fr.titionfire.ffsaf.data.model.LogModel.ActionType;
import fr.titionfire.ffsaf.data.model.LogModel.ObjectType;
import fr.titionfire.ffsaf.data.model.LoggableModel;
import fr.titionfire.ffsaf.data.repository.LogRepository;
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;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@WithSession
@RequestScoped
public class LoggerService {
@Inject
LogRepository repository;
@Inject
SecurityCtx securityCtx;
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)));
}
public Uni<?> logA(ActionType action, String message, LoggableModel model) {
return logA(action, model.getObjectType(), message, model.getObjectName(), model.getId());
}
public Uni<?> logAAdd(LoggableModel model) {
return logA(ActionType.ADD, "", model);
}
public Uni<?> logAUpdate(String message, LoggableModel model) {
return logA(ActionType.UPDATE, message, model);
}
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);
}
public Uni<?> logADelete(LoggableModel model) {
return logA(ActionType.REMOVE, "", model);
}
public Uni<?> append() {
return Panache.withTransaction(() -> repository.persist(buffer))
.invoke(__ -> buffer.clear());
}
public void clear() {
buffer.clear();
}
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));
}
public void log(ActionType action, String message, LoggableModel model) {
log(action, model.getObjectType(), message, model.getObjectName(), model.getId());
}
public void logAdd(LoggableModel model) {
log(ActionType.ADD, "", model);
}
public void logUpdate(String message, LoggableModel model) {
log(ActionType.UPDATE, message, model);
}
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);
}
public void logDelete(LoggableModel model) {
log(ActionType.REMOVE, "", model);
}
}

View File

@ -69,6 +69,9 @@ public class MembreService {
@Inject
RegisterRepository registerRepository;
@Inject
LoggerService ls;
public SimpleCombModel find(int licence, String np) throws Throwable {
return VertxContextSupport.subscribeAndAwait(() -> Panache.withTransaction(() ->
repository.find(
@ -139,16 +142,6 @@ public class MembreService {
.map(l -> membres.stream().map(m -> SimpleMembreInOutData.fromModel(m, l)).toList()));
}
/*
public Uni<List<SimpleMembre>> getSimilar(String fname, String lname) {
return repository.listAll().map(membreModels -> membreModels.stream()
.filter(m -> StringSimilarity.similarity(m.getFname(), fname) <= 3 &&
StringSimilarity.similarity(m.getLname(), lname) <= 3)
.map(SimpleMembre::fromModel).toList());
}+
*/
public Uni<String> allImporte(String subject, List<SimpleMembreInOutData> data) {
if (data == null)
return Uni.createFrom().nullItem();
@ -187,40 +180,58 @@ public class MembreService {
return mm;
});
if ((model.getId() != null && StringSimilarity.similarity(model.getLname().toUpperCase(),
dataIn.getNom()
.toUpperCase()) > 3) || (model.getId() != null && StringSimilarity.similarity(
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(
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3)) {
throw new DBadRequestException(
"Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide.");
}
ls.logChange("Nom", model.getLname(), dataIn.getNom().toUpperCase(), model);
ls.logChange("Prénom", model.getFname(),
dataIn.getPrenom().toUpperCase().charAt(0) + dataIn.getPrenom().substring(1), model);
model.setLname(dataIn.getNom().toUpperCase());
model.setFname(dataIn.getPrenom().toUpperCase().charAt(0) + dataIn.getPrenom().substring(1));
if (dataIn.getEmail() != null && !dataIn.getEmail().isBlank())
if (dataIn.getEmail() != null && !dataIn.getEmail().isBlank()) {
ls.logChange("Email", model.getEmail(), dataIn.getEmail(), model);
model.setEmail(dataIn.getEmail());
}
model.setGenre(Genre.fromString(dataIn.getGenre()));
if (dataIn.getBirthdate() != null) {
if (!Objects.equals(model.getBirth_date().getTime(), dataIn.getBirthdate().getTime()))
ls.logChange("Date de naissance", model.getBirth_date(), dataIn.getBirthdate(), model);
model.setBirth_date(dataIn.getBirthdate());
model.setCategorie(Utils.getCategoryFormBirthDate(model.getBirth_date(), new Date()));
}
uniResult = uniResult.call(() -> Panache.withTransaction(() -> repository.persist(model)
.chain(membreModel1 -> dataIn.isLicenceCurrent() ? licenceRepository.find(
"membre.id = ?1 AND saison = ?2", membreModel1.getId(), Utils.getSaison())
.firstResult()
.call(l -> {
if (l == null) {
l = new LicenceModel();
l.setMembre(membreModel1);
l.setValidate(false);
l.setSaison(Utils.getSaison());
}
l.setCertificate(dataIn.getCertif());
return licenceRepository.persist(l);
}) : licenceRepository.delete(
"membre = ?1 AND saison = ?2 AND validate = false", membreModel1,
Utils.getSaison()))));
uniResult = uniResult
.call(() -> Panache.withTransaction(() -> repository.persist(model)
.chain(membreModel1 -> dataIn.isLicenceCurrent() ? licenceRepository.find(
"membre.id = ?1 AND saison = ?2", membreModel1.getId(),
Utils.getSaison())
.firstResult()
.call(l -> {
if (l == null) {
l = new LicenceModel();
l.setMembre(membreModel1);
l.setValidate(false);
l.setSaison(Utils.getSaison());
}
l.setCertificate(dataIn.getCertif());
return licenceRepository.persist(l);
}) : licenceRepository.delete(
"membre = ?1 AND saison = ?2 AND validate = false", membreModel1,
Utils.getSaison()))));
if (add)
uniResult = uniResult.call(() -> ls.logAAdd(model));
else
uniResult = uniResult.call(() -> ls.append());
}
return uniResult;
}))