Files
unionflow-client-quarkus-pr…/src/main/java/dev/lions/unionflow/client/view/AuditBean.java
2026-03-01 22:00:28 +00:00

561 lines
21 KiB
Java

package dev.lions.unionflow.client.view;
import dev.lions.unionflow.server.api.dto.admin.response.AuditLogResponse;
import dev.lions.unionflow.client.service.AuditService;
import dev.lions.unionflow.client.service.NotificationClientService;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* Bean JSF pour la gestion des logs d'audit
* Refactorisé pour utiliser directement AuditLogResponse et se connecter au backend
*
* @author UnionFlow Team
* @version 2.0
*/
@Named("auditBean")
@SessionScoped
public class AuditBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOG = Logger.getLogger(AuditBean.class);
@Inject
@RestClient
private AuditService auditService;
@Inject
@RestClient
private NotificationClientService notificationService;
@Inject
private UserSession userSession;
@Inject
ErrorHandlerService errorHandler;
@Inject
RetryService retryService;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
// Filtres
private Date dateDebut;
private Date dateFin;
private String typeAction = "";
private String severite = "";
private String utilisateur = "";
private String module = "";
private String ipAddress = "";
// Données - Utilisation directe de AuditLogResponse
private List<AuditLogResponse> tousLesLogs;
private List<AuditLogResponse> logsFiltres;
private AuditLogResponse logSelectionne;
// Statistiques
private Map<String, Object> statistiques;
// Export
private String formatExport = "EXCEL";
private boolean inclureFiltresExport = true;
@PostConstruct
public void init() {
LOG.info("Initialisation de AuditBean");
// Initialiser les dates à aujourd'hui - 7 jours
Calendar cal = Calendar.getInstance();
dateFin = cal.getTime();
cal.add(Calendar.DAY_OF_MONTH, -7);
dateDebut = cal.getTime();
chargerLogs();
chargerStatistiques();
}
/**
* Charge les logs depuis le backend
*/
public void chargerLogs() {
try {
LOG.info("Chargement des logs d'audit depuis le backend");
Map<String, Object> response = retryService.executeWithRetrySupplier(
() -> auditService.listerTous(0, 1000, "dateHeure", "desc"),
"chargement des logs d'audit"
);
tousLesLogs = new ArrayList<>();
if (response.containsKey("data")) {
@SuppressWarnings("unchecked")
List<Object> data = (List<Object>) response.get("data");
if (data != null) {
for (Object item : data) {
if (item instanceof AuditLogResponse) {
tousLesLogs.add((AuditLogResponse) item);
} else if (item instanceof Map) {
@SuppressWarnings("unchecked")
AuditLogResponse dto = convertMapToDTO((Map<String, Object>) item);
tousLesLogs.add(dto);
}
}
}
}
appliquerFiltres();
LOG.infof("Logs chargés: %d", tousLesLogs.size());
} catch (Exception e) {
LOG.errorf(e, "Erreur lors du chargement des logs");
tousLesLogs = new ArrayList<>();
errorHandler.handleException(e, "lors du chargement des logs d'audit", null);
}
}
/**
* Charge les statistiques depuis le backend
*/
public void chargerStatistiques() {
try {
LOG.info("Chargement des statistiques d'audit");
statistiques = retryService.executeWithRetrySupplier(
() -> auditService.getStatistiques(),
"chargement des statistiques d'audit"
);
} catch (Exception e) {
LOG.errorf(e, "Erreur lors du chargement des statistiques");
statistiques = new HashMap<>();
statistiques.put("total", 0L);
statistiques.put("success", 0L);
statistiques.put("errors", 0L);
statistiques.put("warnings", 0L);
}
}
/**
* Convertit une Map en AuditLogResponse
*/
private AuditLogResponse convertMapToDTO(Map<String, Object> map) {
AuditLogResponse dto = new AuditLogResponse();
try {
if (map.get("id") != null) {
if (map.get("id") instanceof UUID) {
dto.setId((UUID) map.get("id"));
} else {
dto.setId(UUID.fromString(map.get("id").toString()));
}
}
if (map.get("typeAction") != null) dto.setTypeAction(map.get("typeAction").toString());
if (map.get("severite") != null) dto.setSeverite(map.get("severite").toString());
if (map.get("utilisateur") != null) dto.setUtilisateur(map.get("utilisateur").toString());
if (map.get("role") != null) dto.setRole(map.get("role").toString());
if (map.get("module") != null) dto.setModule(map.get("module").toString());
if (map.get("description") != null) dto.setDescription(map.get("description").toString());
if (map.get("details") != null) dto.setDetails(map.get("details").toString());
if (map.get("ipAddress") != null) dto.setIpAddress(map.get("ipAddress").toString());
if (map.get("userAgent") != null) dto.setUserAgent(map.get("userAgent").toString());
if (map.get("sessionId") != null) dto.setSessionId(map.get("sessionId").toString());
if (map.get("donneesAvant") != null) dto.setDonneesAvant(map.get("donneesAvant").toString());
if (map.get("donneesApres") != null) dto.setDonneesApres(map.get("donneesApres").toString());
if (map.get("entiteId") != null) dto.setEntiteId(map.get("entiteId").toString());
if (map.get("entiteType") != null) dto.setEntiteType(map.get("entiteType").toString());
// Conversion des dates
if (map.get("dateHeure") != null) {
Object date = map.get("dateHeure");
if (date instanceof LocalDateTime) {
dto.setDateHeure((LocalDateTime) date);
} else if (date instanceof String) {
dto.setDateHeure(LocalDateTime.parse(date.toString()));
}
}
} catch (Exception e) {
LOG.warnf(e, "Erreur lors de la conversion Map vers DTO");
}
return dto;
}
/**
* Applique les filtres sur les logs
*/
public void appliquerFiltres() {
if (tousLesLogs == null) {
logsFiltres = new ArrayList<>();
return;
}
logsFiltres = tousLesLogs.stream()
.filter(this::correspondAuxFiltres)
.collect(Collectors.toList());
}
private boolean correspondAuxFiltres(AuditLogResponse log) {
if (log.getDateHeure() == null) return false;
// Filtre par dates
LocalDateTime dateDebutLDT = dateDebut != null ?
LocalDateTime.ofInstant(dateDebut.toInstant(), ZoneId.systemDefault()) : null;
LocalDateTime dateFinLDT = dateFin != null ?
LocalDateTime.ofInstant(dateFin.toInstant(), ZoneId.systemDefault()).plusDays(1) : null;
if (dateDebutLDT != null && log.getDateHeure().isBefore(dateDebutLDT)) {
return false;
}
if (dateFinLDT != null && log.getDateHeure().isAfter(dateFinLDT)) {
return false;
}
// Filtre par type d'action
if (!typeAction.isEmpty() && !typeAction.equals(log.getTypeAction())) {
return false;
}
// Filtre par sévérité
if (!severite.isEmpty() && !severite.equals(log.getSeverite())) {
return false;
}
// Filtre par utilisateur
if (!utilisateur.isEmpty() && log.getUtilisateur() != null &&
!log.getUtilisateur().toLowerCase().contains(utilisateur.toLowerCase())) {
return false;
}
// Filtre par module
if (!module.isEmpty() && !module.equals(log.getModule())) {
return false;
}
// Filtre par IP
if (!ipAddress.isEmpty() && log.getIpAddress() != null &&
!log.getIpAddress().contains(ipAddress)) {
return false;
}
return true;
}
/**
* Recherche avec filtres via le backend
*/
public void rechercher() {
try {
LOG.info("Recherche de logs avec filtres");
String dateDebutStr = dateDebut != null ?
LocalDateTime.ofInstant(dateDebut.toInstant(), ZoneId.systemDefault()).toString() : null;
String dateFinStr = dateFin != null ?
LocalDateTime.ofInstant(dateFin.toInstant(), ZoneId.systemDefault()).toString() : null;
Map<String, Object> response = retryService.executeWithRetrySupplier(
() -> auditService.rechercher(
dateDebutStr, dateFinStr,
typeAction.isEmpty() ? null : typeAction,
severite.isEmpty() ? null : severite,
utilisateur.isEmpty() ? null : utilisateur,
module.isEmpty() ? null : module,
ipAddress.isEmpty() ? null : ipAddress,
0, 1000),
"recherche de logs d'audit"
);
logsFiltres = new ArrayList<>();
if (response.containsKey("data")) {
@SuppressWarnings("unchecked")
List<Object> data = (List<Object>) response.get("data");
if (data != null) {
for (Object item : data) {
if (item instanceof AuditLogResponse) {
logsFiltres.add((AuditLogResponse) item);
} else if (item instanceof Map) {
@SuppressWarnings("unchecked")
AuditLogResponse dto = convertMapToDTO((Map<String, Object>) item);
logsFiltres.add(dto);
}
}
}
}
errorHandler.showSuccess("Recherche", logsFiltres.size() + " log(s) trouvé(s)");
} catch (Exception e) {
LOG.errorf(e, "Erreur lors de la recherche");
errorHandler.handleException(e, "lors de la recherche de logs d'audit", null);
}
}
/**
* Réinitialise les filtres
*/
public void reinitialiserFiltres() {
Calendar cal = Calendar.getInstance();
dateFin = cal.getTime();
cal.add(Calendar.DAY_OF_MONTH, -7);
dateDebut = cal.getTime();
typeAction = "";
severite = "";
utilisateur = "";
module = "";
ipAddress = "";
appliquerFiltres();
}
/**
* Actualise les données
*/
public void actualiser() {
chargerLogs();
chargerStatistiques();
}
/**
* Sélectionne un log pour voir les détails
*/
public void selectionnerLog(AuditLogResponse log) {
this.logSelectionne = log;
}
/**
* Méthode pour compatibilité avec l'ancienne page
*/
public void voirDetails(AuditLogResponse log) {
selectionnerLog(log);
}
/**
* Signale un événement d'audit suspect
*/
public void signalerEvenement(AuditLogResponse log) {
if (log == null) {
errorHandler.showWarning("Attention", "Aucun log sélectionné");
return;
}
try {
LOG.infof("Signalement de l'événement: %s", log.getId());
// Envoyer une notification aux administrateurs
String message = String.format(
"Événement signalé - Type: %s, Utilisateur: %s, Date: %s, IP: %s",
log.getTypeAction(),
log.getUtilisateur(),
log.getDateHeure() != null ? log.getDateHeure().format(DATE_FORMATTER) : "N/A",
log.getIpAddress()
);
// Récupérer l'ID de l'utilisateur courant pour le signalement
String signaleurId = userSession.getCurrentUser() != null
? userSession.getCurrentUser().getId().toString()
: "anonyme";
retryService.executeWithRetrySupplier(
() -> {
notificationService.envoyerNotificationGroupe(
"SYSTEME",
"Signalement d'un événement d'audit",
message,
List.of(signaleurId) // Envoyer aux admins (à adapter selon votre logique)
);
return null;
},
"envoi d'une notification de signalement"
);
errorHandler.showSuccess("Signalement", "L'événement a été signalé aux administrateurs");
} catch (Exception e) {
LOG.errorf(e, "Erreur lors du signalement");
errorHandler.handleException(e, "lors du signalement d'un événement d'audit", null);
}
}
/**
* Exporte les logs d'audit en CSV
*/
public void exporter() {
try {
LOG.infof("Export de %d logs d'audit", logsFiltres != null ? logsFiltres.size() : 0);
List<AuditLogResponse> logsAExporter = logsFiltres != null && !logsFiltres.isEmpty()
? logsFiltres
: tousLesLogs;
if (logsAExporter == null || logsAExporter.isEmpty()) {
errorHandler.showWarning("Attention", "Aucun log à exporter");
return;
}
// Générer le CSV
StringBuilder csv = new StringBuilder();
csv.append("Date/Heure;Type Action;Utilisateur;Module;IP;Sévérité;Détails\n");
for (AuditLogResponse log : logsAExporter) {
csv.append(String.format("%s;%s;%s;%s;%s;%s;%s\n",
log.getDateHeure() != null ? log.getDateHeure().format(DATE_FORMATTER) : "",
log.getTypeAction() != null ? log.getTypeAction() : "",
log.getUtilisateur() != null ? log.getUtilisateur() : "",
log.getModule() != null ? log.getModule() : "",
log.getIpAddress() != null ? log.getIpAddress() : "",
log.getSeverite() != null ? log.getSeverite() : "",
log.getDetails() != null ? log.getDetails().replace(";", ",").replace("\n", " ") : ""
));
}
byte[] csvData = csv.toString().getBytes(StandardCharsets.UTF_8);
telechargerFichier(csvData, "audit-logs-export.csv", "text/csv");
errorHandler.showSuccess("Export", "Export de " + logsAExporter.size() + " log(s) terminé");
} catch (Exception e) {
LOG.errorf(e, "Erreur lors de l'export");
errorHandler.handleException(e, "lors de l'export des logs d'audit", null);
}
}
/**
* Télécharge un fichier via le navigateur
*/
private void telechargerFichier(byte[] data, String nomFichier, String contentType) {
try {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType(contentType + "; charset=UTF-8");
ec.setResponseContentLength(data.length);
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + nomFichier + "\"");
OutputStream output = ec.getResponseOutputStream();
output.write(data);
output.flush();
fc.responseComplete();
} catch (Exception e) {
LOG.errorf(e, "Erreur téléchargement fichier");
throw new RuntimeException("Erreur lors du téléchargement", e);
}
}
// Getters pour KPIs
public int getTotalEvenements() {
if (statistiques != null && statistiques.containsKey("total")) {
Object total = statistiques.get("total");
if (total instanceof Number) {
return ((Number) total).intValue();
}
}
return tousLesLogs != null ? tousLesLogs.size() : 0;
}
public long getConnexionsReussies() {
if (tousLesLogs == null) return 0;
LocalDateTime aujourdhui = LocalDateTime.now().toLocalDate().atStartOfDay();
return tousLesLogs.stream()
.filter(log -> "CONNEXION".equals(log.getTypeAction()) &&
"SUCCESS".equals(log.getSeverite()) &&
log.getDateHeure() != null &&
log.getDateHeure().isAfter(aujourdhui))
.count();
}
public long getTentativesEchouees() {
if (tousLesLogs == null) return 0;
LocalDateTime semainePassee = LocalDateTime.now().minusWeeks(1);
return tousLesLogs.stream()
.filter(log -> "CONNEXION".equals(log.getTypeAction()) &&
!"SUCCESS".equals(log.getSeverite()) &&
log.getDateHeure() != null &&
log.getDateHeure().isAfter(semainePassee))
.count();
}
public long getAlertesSecurite() {
if (tousLesLogs == null) return 0;
return tousLesLogs.stream()
.filter(log -> "CRITICAL".equals(log.getSeverite()) ||
"ERROR".equals(log.getSeverite()))
.count();
}
// Getters et Setters
public Date getDateDebut() { return dateDebut; }
public void setDateDebut(Date dateDebut) {
this.dateDebut = dateDebut;
appliquerFiltres();
}
public Date getDateFin() { return dateFin; }
public void setDateFin(Date dateFin) {
this.dateFin = dateFin;
appliquerFiltres();
}
public String getTypeAction() { return typeAction; }
public void setTypeAction(String typeAction) {
this.typeAction = typeAction;
appliquerFiltres();
}
public String getSeverite() { return severite; }
public void setSeverite(String severite) {
this.severite = severite;
appliquerFiltres();
}
public String getUtilisateur() { return utilisateur; }
public void setUtilisateur(String utilisateur) {
this.utilisateur = utilisateur;
appliquerFiltres();
}
public String getModule() { return module; }
public void setModule(String module) {
this.module = module;
appliquerFiltres();
}
public String getIpAddress() { return ipAddress; }
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
appliquerFiltres();
}
public List<AuditLogResponse> getEvenementsFiltres() {
return logsFiltres != null ? logsFiltres : new ArrayList<>();
}
public AuditLogResponse getEvenementSelectionne() { return logSelectionne; }
public void setEvenementSelectionne(AuditLogResponse log) { this.logSelectionne = log; }
public String getFormatExport() { return formatExport; }
public void setFormatExport(String formatExport) { this.formatExport = formatExport; }
public boolean isInclureFiltresExport() { return inclureFiltresExport; }
public void setInclureFiltresExport(boolean inclureFiltresExport) {
this.inclureFiltresExport = inclureFiltresExport;
}
}