feat(lum-client): logos Lions + refonte index + enrichissement user view/profil
- Logos Lions (3 variantes : branded, dark, standard) dans freya-layout/images - index.html + index.xhtml : refonte - pages/user-manager/users/view.xhtml : enrichissement affichage détails user (+427 lignes) - UserProfilBean, AuditConsultationBean, UserSessionBean : ajustements - templates/menu.xhtml + topbar.xhtml : ajustements layout - pom.xml : mises à jour mineures - .gitignore ajouté - UserCreationBeanTest : ajustements Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
111
.gitignore
vendored
Normal file
111
.gitignore
vendored
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# ============================================
|
||||||
|
# Quarkus JSF Frontend .gitignore
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
# Maven
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
|
||||||
|
# Quarkus
|
||||||
|
.quarkus/
|
||||||
|
quarkus.log
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.vscode/
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
.factorypath
|
||||||
|
.apt_generated/
|
||||||
|
.apt_generated_tests/
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.metadata
|
||||||
|
bin/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
local.properties
|
||||||
|
.loadpath
|
||||||
|
.recommenders
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
*.log.*
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
*.pid
|
||||||
|
|
||||||
|
# Java
|
||||||
|
*.class
|
||||||
|
*.jar
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
# JSF/Faces specific
|
||||||
|
**/META-INF/resources/.faces-config.xml.jsfdia
|
||||||
|
**/javax.faces.resource/
|
||||||
|
|
||||||
|
# PrimeFaces cache
|
||||||
|
**/primefaces_resource_cache/
|
||||||
|
|
||||||
|
# Node modules (if using npm/webpack)
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
# Static resources compiled
|
||||||
|
src/main/resources/META-INF/resources/dist/
|
||||||
|
src/main/resources/META-INF/resources/assets/vendor/
|
||||||
|
|
||||||
|
# Application secrets
|
||||||
|
*.jks
|
||||||
|
*.p12
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*-secret.properties
|
||||||
|
application-local.properties
|
||||||
|
application-dev-override.properties
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.dockerignore
|
||||||
|
docker-compose.override.yml
|
||||||
|
|
||||||
|
# Database
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
*.h2.db
|
||||||
|
|
||||||
|
# Test
|
||||||
|
test-output/
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.tmp/
|
||||||
|
temp/
|
||||||
3
pom.xml
3
pom.xml
@@ -149,6 +149,9 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<release>21</release>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|||||||
@@ -18,10 +18,8 @@ import org.eclipse.microprofile.rest.client.inject.RestClient;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -47,8 +45,8 @@ public class AuditConsultationBean implements Serializable {
|
|||||||
private AuditLogDTO selectedLog;
|
private AuditLogDTO selectedLog;
|
||||||
|
|
||||||
private String acteurUsername;
|
private String acteurUsername;
|
||||||
private Date dateDebut;
|
private LocalDateTime dateDebut;
|
||||||
private Date dateFin;
|
private LocalDateTime dateFin;
|
||||||
private TypeActionAudit selectedTypeAction;
|
private TypeActionAudit selectedTypeAction;
|
||||||
private String ressourceType;
|
private String ressourceType;
|
||||||
private Boolean succes;
|
private Boolean succes;
|
||||||
@@ -212,9 +210,23 @@ public class AuditConsultationBean implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toIsoString(Date date) {
|
public void loadLogsByActeur(String acteur) {
|
||||||
if (date == null) return null;
|
try {
|
||||||
LocalDateTime ldt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
List<AuditLogDTO> result = auditServiceClient.getLogsByActor(acteur, 100);
|
||||||
|
auditLogs = result != null ? result : new ArrayList<>();
|
||||||
|
totalRecords = auditLogs.size();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.severe("Erreur lors du chargement des logs par acteur: " + e.getMessage());
|
||||||
|
addErrorMessage("Erreur lors du chargement : " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadLogsByRealm(String realmName) {
|
||||||
|
LOGGER.warning("loadLogsByRealm non supporté côté serveur pour le realm : " + realmName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toIsoString(LocalDateTime ldt) {
|
||||||
|
if (ldt == null) return null;
|
||||||
return ldt.format(DATE_FORMATTER);
|
return ldt.format(DATE_FORMATTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,6 +192,34 @@ public class UserProfilBean implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtenir les initiales de l'utilisateur pour l'avatar
|
||||||
|
*/
|
||||||
|
public String getUserInitials() {
|
||||||
|
if (user == null) return "?";
|
||||||
|
String p = (user.getPrenom() != null && !user.getPrenom().isEmpty())
|
||||||
|
? user.getPrenom().substring(0, 1) : "";
|
||||||
|
String n = (user.getNom() != null && !user.getNom().isEmpty())
|
||||||
|
? user.getNom().substring(0, 1) : "";
|
||||||
|
String initials = (p + n).toUpperCase();
|
||||||
|
return initials.isEmpty() ? "?" : initials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtenir le nom du rôle principal (libellé lisible)
|
||||||
|
*/
|
||||||
|
public String getPrimaryRoleName() {
|
||||||
|
if (user == null || user.getRealmRoles() == null || user.getRealmRoles().isEmpty()) {
|
||||||
|
return "Utilisateur";
|
||||||
|
}
|
||||||
|
java.util.List<String> roles = user.getRealmRoles();
|
||||||
|
if (roles.contains("admin")) return "Administrateur";
|
||||||
|
if (roles.contains("user_manager")) return "Gestionnaire";
|
||||||
|
if (roles.contains("user_viewer")) return "Consultant";
|
||||||
|
if (roles.contains("auditor")) return "Auditeur";
|
||||||
|
return roles.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Méthodes compatibles avec user-actions.xhtml (qui passe l'ID en paramètre)
|
// Méthodes compatibles avec user-actions.xhtml (qui passe l'ID en paramètre)
|
||||||
|
|
||||||
public void activateUser(String userId) {
|
public void activateUser(String userId) {
|
||||||
|
|||||||
@@ -341,12 +341,9 @@ public class UserSessionBean implements Serializable {
|
|||||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||||
ExternalContext externalContext = facesContext.getExternalContext();
|
ExternalContext externalContext = facesContext.getExternalContext();
|
||||||
|
|
||||||
// Invalider la session HTTP locale
|
// NE PAS invalider la session ici — Quarkus OIDC a besoin des tokens
|
||||||
externalContext.invalidateSession();
|
// (stockés en session) pour construire l'URL end_session_endpoint de Keycloak
|
||||||
|
// avec id_token_hint. La session sera invalidée par Quarkus après le logout.
|
||||||
// Rediriger vers l'endpoint de logout OIDC de Quarkus
|
|
||||||
// Quarkus gère la déconnexion Keycloak (end_session_endpoint) + redirection
|
|
||||||
// post-logout
|
|
||||||
String contextPath = externalContext.getRequestContextPath();
|
String contextPath = externalContext.getRequestContextPath();
|
||||||
externalContext.redirect(contextPath + "/auth/logout");
|
externalContext.redirect(contextPath + "/auth/logout");
|
||||||
facesContext.responseComplete();
|
facesContext.responseComplete();
|
||||||
@@ -354,7 +351,6 @@ public class UserSessionBean implements Serializable {
|
|||||||
return null;
|
return null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage());
|
LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage());
|
||||||
// En cas d'erreur, rediriger vers la page d'accueil
|
|
||||||
return "/?faces-redirect=true";
|
return "/?faces-redirect=true";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +1,191 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||||
xmlns:p="http://primefaces.org/ui"
|
xmlns:p="http://primefaces.org/ui"
|
||||||
lang="fr">
|
template="/templates/main-template.xhtml">
|
||||||
|
|
||||||
<h:head>
|
<ui:define name="title">Accueil - Lions User Manager</ui:define>
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Lions User Manager - Gestion des Utilisateurs Keycloak</title>
|
|
||||||
|
|
||||||
<!-- PrimeFaces Freya Theme -->
|
<ui:define name="content">
|
||||||
<h:outputStylesheet name="primefaces-freya/theme.css" />
|
<div class="grid">
|
||||||
<h:outputStylesheet name="css/primeicons.css" library="freya-layout" />
|
<!-- ================================================================
|
||||||
<h:outputStylesheet name="css/primeflex.min.css" library="freya-layout" />
|
EN-TÊTE AVEC LOGO ET BIENVENUE
|
||||||
</h:head>
|
================================================================ -->
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="flex flex-column align-items-center text-center py-4">
|
||||||
|
<h:graphicImage name="freya-layout/images/lions-logo.png"
|
||||||
|
style="height: 160px; width: auto;" alt="Lions User Manager" />
|
||||||
|
|
||||||
<h:body>
|
<h2 class="text-900 font-bold text-3xl mt-4 mb-2">
|
||||||
<div class="flex align-items-center justify-content-center" style="min-height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
|
Bienvenue, #{userSessionBean.fullName}
|
||||||
<div class="card" style="width: 90%; max-width: 600px; text-align: center;">
|
</h2>
|
||||||
<div class="flex flex-column align-items-center gap-3 p-5">
|
<p class="text-600 text-lg m-0 mb-3">
|
||||||
<i class="pi pi-users text-6xl text-primary"></i>
|
Gestion centralisée des utilisateurs Keycloak
|
||||||
<h1 class="text-4xl font-bold m-0">Lions User Manager</h1>
|
</p>
|
||||||
<p class="text-xl text-600 m-0">Gestion centralisée des utilisateurs Keycloak</p>
|
|
||||||
|
|
||||||
<div class="flex flex-column gap-2 mt-4" style="width: 100%;">
|
<div class="flex align-items-center gap-2">
|
||||||
|
<span class="inline-flex align-items-center gap-2 bg-green-100 text-green-700 px-3 py-2 border-round font-semibold">
|
||||||
|
<i class="pi pi-circle-fill" style="font-size: 0.5rem;"></i>
|
||||||
|
<span>Connecté</span>
|
||||||
|
</span>
|
||||||
|
<span class="inline-flex align-items-center bg-blue-100 text-blue-700 px-3 py-1 border-round font-semibold text-sm"
|
||||||
|
style="text-transform: uppercase; letter-spacing: 0.5px;">
|
||||||
|
#{userSessionBean.primaryRole}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================================================
|
||||||
|
ACCÈS RAPIDE
|
||||||
|
================================================================ -->
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="text-900 font-semibold text-lg mb-4 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-bolt text-orange-500"></i>
|
||||||
|
Accès Rapide
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
<!-- Gestion Utilisateurs -->
|
||||||
|
<div class="col-12 md:col-6 lg:col-3">
|
||||||
<h:link outcome="/pages/user-manager/users/list" styleClass="no-underline">
|
<h:link outcome="/pages/user-manager/users/list" styleClass="no-underline">
|
||||||
<p:commandButton value="Accéder à la Gestion des Utilisateurs"
|
<div class="surface-50 border-round p-4 h-full hover:surface-100 transition-all transition-duration-200 cursor-pointer">
|
||||||
icon="pi pi-users"
|
<div class="flex align-items-center justify-content-between mb-3">
|
||||||
styleClass="w-full p-button-lg" />
|
<div class="flex align-items-center justify-content-center bg-blue-100 border-round"
|
||||||
|
style="width: 48px; height: 48px;">
|
||||||
|
<i class="pi pi-users text-blue-600 text-2xl"></i>
|
||||||
|
</div>
|
||||||
|
<i class="pi pi-angle-right text-400"></i>
|
||||||
|
</div>
|
||||||
|
<h4 class="text-900 font-semibold m-0 mb-1">Utilisateurs</h4>
|
||||||
|
<p class="text-600 text-sm m-0">Gérer les comptes utilisateurs</p>
|
||||||
|
</div>
|
||||||
</h:link>
|
</h:link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Gestion Rôles -->
|
||||||
|
<div class="col-12 md:col-6 lg:col-3">
|
||||||
<h:link outcome="/pages/user-manager/roles/list" styleClass="no-underline">
|
<h:link outcome="/pages/user-manager/roles/list" styleClass="no-underline">
|
||||||
<p:commandButton value="Gestion des Rôles"
|
<div class="surface-50 border-round p-4 h-full hover:surface-100 transition-all transition-duration-200 cursor-pointer">
|
||||||
icon="pi pi-shield"
|
<div class="flex align-items-center justify-content-between mb-3">
|
||||||
styleClass="w-full p-button-lg p-button-outlined" />
|
<div class="flex align-items-center justify-content-center bg-green-100 border-round"
|
||||||
|
style="width: 48px; height: 48px;">
|
||||||
|
<i class="pi pi-shield text-green-600 text-2xl"></i>
|
||||||
|
</div>
|
||||||
|
<i class="pi pi-angle-right text-400"></i>
|
||||||
|
</div>
|
||||||
|
<h4 class="text-900 font-semibold m-0 mb-1">Rôles</h4>
|
||||||
|
<p class="text-600 text-sm m-0">Configurer les rôles et permissions</p>
|
||||||
|
</div>
|
||||||
</h:link>
|
</h:link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Journal d'Audit -->
|
||||||
|
<div class="col-12 md:col-6 lg:col-3">
|
||||||
<h:link outcome="/pages/user-manager/audit/logs" styleClass="no-underline">
|
<h:link outcome="/pages/user-manager/audit/logs" styleClass="no-underline">
|
||||||
<p:commandButton value="Journal d'Audit"
|
<div class="surface-50 border-round p-4 h-full hover:surface-100 transition-all transition-duration-200 cursor-pointer">
|
||||||
icon="pi pi-history"
|
<div class="flex align-items-center justify-content-between mb-3">
|
||||||
styleClass="w-full p-button-lg p-button-outlined" />
|
<div class="flex align-items-center justify-content-center bg-orange-100 border-round"
|
||||||
|
style="width: 48px; height: 48px;">
|
||||||
|
<i class="pi pi-history text-orange-600 text-2xl"></i>
|
||||||
|
</div>
|
||||||
|
<i class="pi pi-angle-right text-400"></i>
|
||||||
|
</div>
|
||||||
|
<h4 class="text-900 font-semibold m-0 mb-1">Audit</h4>
|
||||||
|
<p class="text-600 text-sm m-0">Consulter le journal d'activité</p>
|
||||||
|
</div>
|
||||||
</h:link>
|
</h:link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 text-600">
|
<!-- Synchronisation -->
|
||||||
<p class="m-0">Version 1.0.0</p>
|
<div class="col-12 md:col-6 lg:col-3">
|
||||||
<p class="m-0 text-sm">Module réutilisable pour l'écosystème LionsDev</p>
|
<h:link outcome="/pages/user-manager/sync/dashboard" styleClass="no-underline">
|
||||||
|
<div class="surface-50 border-round p-4 h-full hover:surface-100 transition-all transition-duration-200 cursor-pointer">
|
||||||
|
<div class="flex align-items-center justify-content-between mb-3">
|
||||||
|
<div class="flex align-items-center justify-content-center bg-purple-100 border-round"
|
||||||
|
style="width: 48px; height: 48px;">
|
||||||
|
<i class="pi pi-sync text-purple-600 text-2xl"></i>
|
||||||
|
</div>
|
||||||
|
<i class="pi pi-angle-right text-400"></i>
|
||||||
|
</div>
|
||||||
|
<h4 class="text-900 font-semibold m-0 mb-1">Synchronisation</h4>
|
||||||
|
<p class="text-600 text-sm m-0">Synchroniser avec Keycloak</p>
|
||||||
|
</div>
|
||||||
|
</h:link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</h:body>
|
|
||||||
|
|
||||||
</html>
|
<!-- ================================================================
|
||||||
|
TABLEAU DE BORD RAPIDE
|
||||||
|
================================================================ -->
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<div class="card h-full">
|
||||||
|
<h3 class="text-900 font-semibold text-lg mb-3 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-info-circle text-blue-500"></i>
|
||||||
|
Informations Système
|
||||||
|
</h3>
|
||||||
|
<div class="flex flex-column gap-3">
|
||||||
|
<div class="flex align-items-center justify-content-between pb-2 border-bottom-1 surface-border">
|
||||||
|
<span class="text-600">Application</span>
|
||||||
|
<span class="text-900 font-semibold">Lions User Manager</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-between pb-2 border-bottom-1 surface-border">
|
||||||
|
<span class="text-600">Version</span>
|
||||||
|
<span class="text-900 font-semibold">1.0.0</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-between pb-2 border-bottom-1 surface-border">
|
||||||
|
<span class="text-600">Realm Keycloak</span>
|
||||||
|
<span class="text-900 font-semibold">lions-user-manager</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-between">
|
||||||
|
<span class="text-600">Statut</span>
|
||||||
|
<p:tag value="Opérationnel" severity="success" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<div class="card h-full">
|
||||||
|
<h3 class="text-900 font-semibold text-lg mb-3 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-user text-blue-500"></i>
|
||||||
|
Ma Session
|
||||||
|
</h3>
|
||||||
|
<div class="flex flex-column gap-3">
|
||||||
|
<div class="flex align-items-center justify-content-between pb-2 border-bottom-1 surface-border">
|
||||||
|
<span class="text-600">Utilisateur</span>
|
||||||
|
<span class="text-900 font-semibold">#{userSessionBean.username}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-between pb-2 border-bottom-1 surface-border">
|
||||||
|
<span class="text-600">Email</span>
|
||||||
|
<span class="text-900 font-semibold">#{userSessionBean.email}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-between pb-2 border-bottom-1 surface-border">
|
||||||
|
<span class="text-600">Rôle principal</span>
|
||||||
|
<p:tag value="#{userSessionBean.primaryRole}" severity="info" />
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-between">
|
||||||
|
<span class="text-600">Actions</span>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<h:link outcome="/pages/user-manager/users/profile" styleClass="p-button p-button-sm p-button-text">
|
||||||
|
<i class="pi pi-user mr-1"></i> Mon Profil
|
||||||
|
</h:link>
|
||||||
|
<h:link outcome="/pages/user-manager/dashboard" styleClass="p-button p-button-sm p-button-outlined">
|
||||||
|
<i class="pi pi-home mr-1"></i> Dashboard
|
||||||
|
</h:link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
</ui:composition>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"
|
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||||
xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
xmlns:p="http://primefaces.org/ui" xmlns:fr="http://primefaces.org/freya"
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" template="/templates/main-template.xhtml">
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||||
|
xmlns:p="http://primefaces.org/ui"
|
||||||
|
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||||
|
template="/templates/main-template.xhtml">
|
||||||
|
|
||||||
<f:metadata>
|
<f:metadata>
|
||||||
<f:viewParam name="userId" value="#{userProfilBean.userId}" />
|
<f:viewParam name="userId" value="#{userProfilBean.userId}" />
|
||||||
@@ -20,13 +23,10 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="flex align-items-center justify-content-between">
|
<div class="flex align-items-center justify-content-between">
|
||||||
<div class="flex align-items-center gap-2">
|
<h2 class="text-900 font-semibold text-xl m-0">
|
||||||
<i class="pi pi-user text-blue-500" style="font-size: 2rem"></i>
|
<i class="pi pi-user text-blue-500 mr-2"></i>
|
||||||
<div>
|
Profil Utilisateur
|
||||||
<h3 class="m-0 mb-1">Profil de l'Utilisateur</h3>
|
</h2>
|
||||||
<p class="text-600 m-0">Détails et informations de l'utilisateur</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h:link outcome="/pages/user-manager/users/list" styleClass="p-button p-button-text">
|
<h:link outcome="/pages/user-manager/users/list" styleClass="p-button p-button-text">
|
||||||
<i class="pi pi-arrow-left mr-2"></i>
|
<i class="pi pi-arrow-left mr-2"></i>
|
||||||
Retour à la liste
|
Retour à la liste
|
||||||
@@ -36,28 +36,394 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ================================================================
|
<!-- ================================================================
|
||||||
CARTE PROFIL PRINCIPAL & ACTIONS
|
CONTENU PRINCIPAL (si utilisateur trouvé)
|
||||||
================================================================ -->
|
================================================================ -->
|
||||||
<ui:fragment rendered="#{userProfilBean.user != null}">
|
<ui:fragment rendered="#{userProfilBean.user != null}">
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
CARTE PROFIL PRINCIPAL
|
||||||
|
============================================================ -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card p-0 overflow-hidden">
|
<div class="card">
|
||||||
<ui:include src="/templates/components/user-management/user-card.xhtml">
|
<div class="grid">
|
||||||
<ui:param name="user" value="#{userProfilBean.user}" />
|
<!-- Photo de profil et informations principales -->
|
||||||
<ui:param name="showActions" value="true" />
|
<div class="col-12 md:col-4">
|
||||||
<ui:param name="layout" value="horizontal" />
|
<div class="text-center mb-4">
|
||||||
<ui:param name="showOrganisation" value="true" />
|
<!-- Avatar avec gradient -->
|
||||||
<ui:param name="showRoles" value="true" />
|
<div style="width: 140px; height: 140px; border-radius: 50%; background: linear-gradient(135deg, var(--primary-color), var(--primary-600, #387FE9)); display: flex; align-items: center; justify-content: center; margin: 0 auto 1.5rem auto; font-size: 3.5rem; font-weight: bold; color: white; box-shadow: 0 8px 24px rgba(0,0,0,0.12);">
|
||||||
<ui:param name="clickable" value="false" />
|
#{userProfilBean.userInitials}
|
||||||
<ui:param name="actionBean" value="#{userProfilBean}" />
|
</div>
|
||||||
<ui:param name="showEdit" value="true" />
|
|
||||||
<ui:param name="editOutcome" value="/pages/user-manager/users/edit" />
|
<!-- Nom complet -->
|
||||||
<ui:param name="hasDeleteAction" value="true" />
|
<h3 class="text-900 font-semibold text-2xl mb-2">
|
||||||
<ui:param name="deleteAction" value="#{userProfilBean.deleteUser}" />
|
#{userProfilBean.user.prenom} #{userProfilBean.user.nom}
|
||||||
</ui:include>
|
</h3>
|
||||||
|
|
||||||
|
<!-- Username -->
|
||||||
|
<p class="text-500 mb-2">@#{userProfilBean.user.username}</p>
|
||||||
|
|
||||||
|
<!-- Email -->
|
||||||
|
<p class="text-600 mb-3 flex align-items-center justify-content-center gap-2">
|
||||||
|
<i class="pi pi-envelope"></i>
|
||||||
|
#{userProfilBean.user.email}
|
||||||
|
<h:panelGroup rendered="#{userProfilBean.user.emailVerified}">
|
||||||
|
<i class="pi pi-check-circle text-green-500" title="Email vérifié"></i>
|
||||||
|
</h:panelGroup>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Badge de statut -->
|
||||||
|
<div class="inline-flex align-items-center justify-content-center gap-2 mb-3">
|
||||||
|
<h:panelGroup rendered="#{userProfilBean.user.enabled}">
|
||||||
|
<span class="inline-flex align-items-center gap-2 bg-green-100 text-green-700 px-3 py-2 border-round font-semibold" style="font-size: 1rem;">
|
||||||
|
<i class="pi pi-circle-fill" style="font-size: 0.5rem; animation: pulse 2s ease-in-out infinite;"></i>
|
||||||
|
<span>Actif</span>
|
||||||
|
</span>
|
||||||
|
</h:panelGroup>
|
||||||
|
<h:panelGroup rendered="#{not userProfilBean.user.enabled}">
|
||||||
|
<span class="inline-flex align-items-center gap-2 bg-red-100 text-red-700 px-3 py-2 border-round font-semibold" style="font-size: 1rem;">
|
||||||
|
<i class="pi pi-circle-fill" style="font-size: 0.5rem;"></i>
|
||||||
|
<span>Inactif</span>
|
||||||
|
</span>
|
||||||
|
</h:panelGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Badge du rôle principal -->
|
||||||
|
<div class="flex justify-content-center">
|
||||||
|
<span class="inline-flex align-items-center bg-blue-100 text-blue-700 px-3 py-1 border-round font-semibold text-sm" style="text-transform: uppercase; letter-spacing: 0.5px;">
|
||||||
|
#{userProfilBean.primaryRoleName}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Informations détaillées -->
|
||||||
|
<div class="col-12 md:col-8">
|
||||||
|
<div class="grid">
|
||||||
|
<!-- Colonne gauche: Informations personnelles -->
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<h4 class="text-900 font-semibold text-lg mb-3 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-user text-blue-500"></i>
|
||||||
|
Informations Personnelles
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Nom d'utilisateur</label>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.username}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Prénom</label>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.prenom}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Nom</label>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.nom}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Adresse email</label>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.email}</p>
|
||||||
|
<h:panelGroup rendered="#{userProfilBean.user.emailVerified}">
|
||||||
|
<i class="pi pi-check-circle text-green-500" title="Email vérifié"></i>
|
||||||
|
</h:panelGroup>
|
||||||
|
<h:panelGroup rendered="#{not userProfilBean.user.emailVerified}">
|
||||||
|
<i class="pi pi-times-circle text-red-400" title="Email non vérifié"></i>
|
||||||
|
</h:panelGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.telephone}">
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Téléphone</label>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.telephone}</p>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.langue}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Langue</label>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.langue}</p>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Colonne droite: Rôles et permissions -->
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<h4 class="text-900 font-semibold text-lg mb-3 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-shield text-purple-500"></i>
|
||||||
|
Rôles et Permissions
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-2 text-sm">Rôles assignés</label>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{not empty userProfilBean.user.realmRoles and not userProfilBean.user.realmRoles.isEmpty()}">
|
||||||
|
<ui:repeat value="#{userProfilBean.user.realmRoles}" var="role">
|
||||||
|
<p:badge value="#{role}" severity="info" styleClass="text-sm"></p:badge>
|
||||||
|
</ui:repeat>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<span class="text-500 font-italic text-sm">Aucun rôle attribué</span>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-2 text-sm">Rôle principal</label>
|
||||||
|
<div class="flex align-items-center">
|
||||||
|
<p:badge value="#{userProfilBean.primaryRoleName}"
|
||||||
|
severity="success"
|
||||||
|
styleClass="text-sm">
|
||||||
|
</p:badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 pb-3 border-bottom-1 surface-border">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Niveau d'accès</label>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.primaryRoleName}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-2 text-sm">Statut du compte</label>
|
||||||
|
<div class="flex align-items-center">
|
||||||
|
<h:panelGroup rendered="#{userProfilBean.user.enabled}">
|
||||||
|
<p:badge value="Actif" severity="success" styleClass="text-sm"></p:badge>
|
||||||
|
</h:panelGroup>
|
||||||
|
<h:panelGroup rendered="#{not userProfilBean.user.enabled}">
|
||||||
|
<p:badge value="Inactif" severity="danger" styleClass="text-sm"></p:badge>
|
||||||
|
</h:panelGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
INFORMATIONS DU COMPTE
|
||||||
|
============================================================ -->
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="text-900 font-semibold text-lg mb-4 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-id-card text-teal-500"></i>
|
||||||
|
Informations du Compte
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<h4 class="text-900 font-semibold mb-3">Contact et Organisation</h4>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.organisation}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Organisation</label>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-building text-blue-500"></i>
|
||||||
|
<p class="text-900 m-0">#{userProfilBean.user.organisation}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.departement}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Département</label>
|
||||||
|
<p class="text-900 m-0">#{userProfilBean.user.departement}</p>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.fonction}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Fonction</label>
|
||||||
|
<p class="text-900 m-0">#{userProfilBean.user.fonction}</p>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.pays}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Pays</label>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-globe text-purple-500"></i>
|
||||||
|
<p class="text-900 m-0">#{userProfilBean.user.pays}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.ville}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Ville</label>
|
||||||
|
<p class="text-900 m-0">#{userProfilBean.user.ville}</p>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<h4 class="text-900 font-semibold mb-3">Activité et Sécurité</h4>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Realm Keycloak</label>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-server text-blue-500"></i>
|
||||||
|
<p class="text-700 m-0 text-sm font-mono bg-bluegray-50 p-2 border-round">
|
||||||
|
#{userProfilBean.realmName}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{userProfilBean.user.derniereConnexion != null}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Dernière connexion</label>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-clock text-green-500"></i>
|
||||||
|
<p class="text-700 m-0 text-sm">
|
||||||
|
<h:outputText value="#{userProfilBean.user.derniereConnexion}">
|
||||||
|
<f:convertDateTime pattern="dd/MM/yyyy à HH:mm:ss" timeZone="Europe/Paris" type="localDateTime"/>
|
||||||
|
</h:outputText>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{userProfilBean.user.activeSessions != null}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-1 text-sm">Sessions actives</label>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-desktop text-purple-500"></i>
|
||||||
|
<p class="text-900 font-semibold m-0">#{userProfilBean.user.activeSessions}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{not empty userProfilBean.user.groups and not userProfilBean.user.groups.isEmpty()}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="block text-600 font-medium mb-2 text-sm">Groupes</label>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<ui:repeat value="#{userProfilBean.user.groups}" var="group">
|
||||||
|
<p:badge value="#{group}" severity="warning" styleClass="text-sm"></p:badge>
|
||||||
|
</ui:repeat>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
ACTIONS
|
||||||
|
============================================================ -->
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="text-900 font-semibold text-lg mb-4 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-cog text-gray-500"></i>
|
||||||
|
Actions
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<h:form id="formUserActions">
|
||||||
|
<div class="grid">
|
||||||
|
<!-- Gestion du Profil -->
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<div class="surface-50 border-round p-3 h-full">
|
||||||
|
<h4 class="text-900 font-semibold mb-3 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-pencil text-blue-500"></i>
|
||||||
|
<span>Gestion du Profil</span>
|
||||||
|
</h4>
|
||||||
|
<div class="flex flex-column gap-2">
|
||||||
|
<h:link outcome="/pages/user-manager/users/edit"
|
||||||
|
styleClass="p-button p-button-outlined w-full justify-content-start">
|
||||||
|
<f:param name="userId" value="#{userProfilBean.userId}" />
|
||||||
|
<f:param name="realm" value="#{userProfilBean.realmName}" />
|
||||||
|
<i class="pi pi-pencil mr-2"></i>
|
||||||
|
Modifier l'utilisateur
|
||||||
|
</h:link>
|
||||||
|
|
||||||
|
<p:commandButton value="Réinitialiser le mot de passe"
|
||||||
|
icon="pi pi-key"
|
||||||
|
styleClass="p-button-outlined p-button-warning w-full justify-content-start"
|
||||||
|
action="#{userProfilBean.resetPassword}"
|
||||||
|
update=":formUserActions"
|
||||||
|
oncomplete="PF('dlgResetPassword').show()">
|
||||||
|
</p:commandButton>
|
||||||
|
|
||||||
|
<p:commandButton value="Envoyer email de vérification"
|
||||||
|
icon="pi pi-envelope"
|
||||||
|
styleClass="p-button-outlined p-button-info w-full justify-content-start"
|
||||||
|
action="#{userProfilBean.sendVerificationEmail}"
|
||||||
|
update="@form"
|
||||||
|
rendered="#{not userProfilBean.user.emailVerified}">
|
||||||
|
<p:confirm header="Confirmation"
|
||||||
|
message="Envoyer un email de vérification à #{userProfilBean.user.email} ?"
|
||||||
|
icon="pi pi-envelope" />
|
||||||
|
</p:commandButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Gestion du Compte -->
|
||||||
|
<div class="col-12 md:col-6">
|
||||||
|
<div class="surface-50 border-round p-3 h-full">
|
||||||
|
<h4 class="text-900 font-semibold mb-3 flex align-items-center gap-2">
|
||||||
|
<i class="pi pi-shield text-purple-500"></i>
|
||||||
|
<span>Gestion du Compte</span>
|
||||||
|
</h4>
|
||||||
|
<div class="flex flex-column gap-2">
|
||||||
|
<p:commandButton value="Activer le compte"
|
||||||
|
icon="pi pi-check-circle"
|
||||||
|
styleClass="p-button-outlined p-button-success w-full justify-content-start"
|
||||||
|
action="#{userProfilBean.activateUser}"
|
||||||
|
update="@form"
|
||||||
|
rendered="#{not userProfilBean.user.enabled}">
|
||||||
|
<p:confirm header="Confirmation d'activation"
|
||||||
|
message="Activer le compte de #{userProfilBean.user.prenom} #{userProfilBean.user.nom} ?"
|
||||||
|
icon="pi pi-check-circle" />
|
||||||
|
</p:commandButton>
|
||||||
|
|
||||||
|
<p:commandButton value="Désactiver le compte"
|
||||||
|
icon="pi pi-ban"
|
||||||
|
styleClass="p-button-outlined p-button-warning w-full justify-content-start"
|
||||||
|
action="#{userProfilBean.deactivateUser}"
|
||||||
|
update="@form"
|
||||||
|
rendered="#{userProfilBean.user.enabled}">
|
||||||
|
<p:confirm header="Confirmation de désactivation"
|
||||||
|
message="Désactiver le compte de #{userProfilBean.user.prenom} #{userProfilBean.user.nom} ?"
|
||||||
|
icon="pi pi-exclamation-triangle" />
|
||||||
|
</p:commandButton>
|
||||||
|
|
||||||
|
<p:commandButton value="Déconnecter toutes les sessions"
|
||||||
|
icon="pi pi-sign-out"
|
||||||
|
styleClass="p-button-outlined p-button-secondary w-full justify-content-start"
|
||||||
|
action="#{userProfilBean.logoutAllSessions}"
|
||||||
|
update="@form">
|
||||||
|
<p:confirm header="Confirmation"
|
||||||
|
message="Déconnecter toutes les sessions actives de #{userProfilBean.user.prenom} #{userProfilBean.user.nom} ?"
|
||||||
|
icon="pi pi-sign-out" />
|
||||||
|
</p:commandButton>
|
||||||
|
|
||||||
|
<p:commandButton value="Supprimer l'utilisateur"
|
||||||
|
icon="pi pi-trash"
|
||||||
|
styleClass="p-button-danger w-full justify-content-start"
|
||||||
|
action="#{userProfilBean.deleteUser}"
|
||||||
|
update="@form">
|
||||||
|
<p:confirm header="Suppression définitive"
|
||||||
|
message="Supprimer définitivement #{userProfilBean.user.prenom} #{userProfilBean.user.nom} ? Cette action est irréversible."
|
||||||
|
icon="pi pi-exclamation-triangle" />
|
||||||
|
</p:commandButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ui:fragment>
|
</ui:fragment>
|
||||||
|
|
||||||
|
<!-- ================================================================
|
||||||
|
UTILISATEUR NON TROUVÉ
|
||||||
|
================================================================ -->
|
||||||
<ui:fragment rendered="#{userProfilBean.user == null}">
|
<ui:fragment rendered="#{userProfilBean.user == null}">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@@ -80,6 +446,13 @@
|
|||||||
<p:autoUpdate />
|
<p:autoUpdate />
|
||||||
</p:growl>
|
</p:growl>
|
||||||
|
|
||||||
|
<!-- Animation CSS pour le badge "Actif" -->
|
||||||
|
<style>
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.5; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</ui:define>
|
</ui:define>
|
||||||
|
|
||||||
</ui:composition>
|
</ui:composition>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 220 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 220 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 220 KiB |
@@ -13,7 +13,7 @@
|
|||||||
<div class="menu-wrapper">
|
<div class="menu-wrapper">
|
||||||
<div class="sidebar-logo">
|
<div class="sidebar-logo">
|
||||||
<a href="/pages/user-manager/dashboard">
|
<a href="/pages/user-manager/dashboard">
|
||||||
<p:graphicImage name="images/logo-freya-single.svg" library="freya-layout" />
|
<h:graphicImage name="freya-layout/images/lions-logo.png" style="height: 36px; width: auto;" alt="Lions" />
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="sidebar-pin" title="Toggle Menu">
|
<a href="#" class="sidebar-pin" title="Toggle Menu">
|
||||||
<span class="pin"></span>
|
<span class="pin"></span>
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
<i class="pi pi-bars"/>
|
<i class="pi pi-bars"/>
|
||||||
</a>
|
</a>
|
||||||
<h:link id="logolink" outcome="/pages/user-manager/dashboard" styleClass="layout-topbar-logo">
|
<h:link id="logolink" outcome="/pages/user-manager/dashboard" styleClass="layout-topbar-logo">
|
||||||
<p:graphicImage name="images/#{guestPreferences.lightLogo ? 'logo-freya-white.svg' : 'logo-freya.svg'}" library="freya-layout" />
|
<h:graphicImage name="freya-layout/images/#{guestPreferences.lightLogo ? 'lions-logo-dark.png' : 'lions-logo.png'}"
|
||||||
|
style="height: 40px; width: auto;" alt="Lions User Manager" />
|
||||||
</h:link>
|
</h:link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class UserCreationBeanTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testInit() {
|
void testInit() {
|
||||||
|
userCreationBean.setDefaultRealm("master");
|
||||||
userCreationBean.init();
|
userCreationBean.init();
|
||||||
|
|
||||||
assertNotNull(userCreationBean.getNewUser());
|
assertNotNull(userCreationBean.getNewUser());
|
||||||
@@ -90,9 +91,8 @@ class UserCreationBeanTest {
|
|||||||
userCreationBean.setPasswordConfirm("password123");
|
userCreationBean.setPasswordConfirm("password123");
|
||||||
userCreationBean.setRealmName(REALM_NAME);
|
userCreationBean.setRealmName(REALM_NAME);
|
||||||
|
|
||||||
String result = userCreationBean.createUser();
|
userCreationBean.createUser();
|
||||||
|
|
||||||
assertEquals("userListPage", result);
|
|
||||||
verify(userServiceClient).createUser(any(UserDTO.class), eq(REALM_NAME));
|
verify(userServiceClient).createUser(any(UserDTO.class), eq(REALM_NAME));
|
||||||
verify(userServiceClient).resetPassword(eq("user-123"), eq(REALM_NAME),
|
verify(userServiceClient).resetPassword(eq("user-123"), eq(REALM_NAME),
|
||||||
any(dev.lions.user.manager.dto.user.PasswordResetRequestDTO.class));
|
any(dev.lions.user.manager.dto.user.PasswordResetRequestDTO.class));
|
||||||
@@ -104,9 +104,8 @@ class UserCreationBeanTest {
|
|||||||
userCreationBean.setPassword("");
|
userCreationBean.setPassword("");
|
||||||
userCreationBean.setPasswordConfirm("");
|
userCreationBean.setPasswordConfirm("");
|
||||||
|
|
||||||
String result = userCreationBean.createUser();
|
userCreationBean.createUser();
|
||||||
|
|
||||||
assertNull(result);
|
|
||||||
verify(userServiceClient, never()).createUser(any(), anyString());
|
verify(userServiceClient, never()).createUser(any(), anyString());
|
||||||
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
||||||
}
|
}
|
||||||
@@ -116,9 +115,8 @@ class UserCreationBeanTest {
|
|||||||
userCreationBean.setPassword("password1");
|
userCreationBean.setPassword("password1");
|
||||||
userCreationBean.setPasswordConfirm("password2");
|
userCreationBean.setPasswordConfirm("password2");
|
||||||
|
|
||||||
String result = userCreationBean.createUser();
|
userCreationBean.createUser();
|
||||||
|
|
||||||
assertNull(result);
|
|
||||||
verify(userServiceClient, never()).createUser(any(), anyString());
|
verify(userServiceClient, never()).createUser(any(), anyString());
|
||||||
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
||||||
}
|
}
|
||||||
@@ -128,9 +126,8 @@ class UserCreationBeanTest {
|
|||||||
userCreationBean.setPassword("short");
|
userCreationBean.setPassword("short");
|
||||||
userCreationBean.setPasswordConfirm("short");
|
userCreationBean.setPasswordConfirm("short");
|
||||||
|
|
||||||
String result = userCreationBean.createUser();
|
userCreationBean.createUser();
|
||||||
|
|
||||||
assertNull(result);
|
|
||||||
verify(userServiceClient, never()).createUser(any(), anyString());
|
verify(userServiceClient, never()).createUser(any(), anyString());
|
||||||
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
||||||
}
|
}
|
||||||
@@ -144,9 +141,8 @@ class UserCreationBeanTest {
|
|||||||
userCreationBean.setPasswordConfirm("password123");
|
userCreationBean.setPasswordConfirm("password123");
|
||||||
userCreationBean.setRealmName(REALM_NAME);
|
userCreationBean.setRealmName(REALM_NAME);
|
||||||
|
|
||||||
String result = userCreationBean.createUser();
|
userCreationBean.createUser();
|
||||||
|
|
||||||
assertNull(result);
|
|
||||||
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
verify(facesContext).addMessage(isNull(), any(FacesMessage.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,9 +168,12 @@ class UserCreationBeanTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCancel() {
|
void testCancel() {
|
||||||
String result = userCreationBean.cancel();
|
jakarta.faces.context.ExternalContext externalContext =
|
||||||
|
mock(jakarta.faces.context.ExternalContext.class);
|
||||||
|
when(facesContext.getExternalContext()).thenReturn(externalContext);
|
||||||
|
|
||||||
|
userCreationBean.cancel();
|
||||||
|
|
||||||
assertEquals("userListPage", result);
|
|
||||||
assertNotNull(userCreationBean.getNewUser());
|
assertNotNull(userCreationBean.getNewUser());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user