561 lines
21 KiB
Java
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;
|
|
}
|
|
}
|