fix(client): Corrections beans JSF et pages XHTML

- UserListBean: correction getTotalCount(), searchTerm(), méthodes statistiques
- RoleGestionBean: correction assignRoleToUser/revokeRoleFromUser, getUserRolesDTOs
- Pages: correction paramètres hasSubmitAction, useParentForm, update IDs
- assign.xhtml: simplification expression EL avec méthode dédiée
This commit is contained in:
lionsdev
2025-12-05 16:23:42 +00:00
parent 137db9c2bb
commit af4c332df8
6 changed files with 199 additions and 60 deletions

View File

@@ -3,6 +3,7 @@ package dev.lions.user.manager.client.view;
import dev.lions.user.manager.client.service.RoleServiceClient; import dev.lions.user.manager.client.service.RoleServiceClient;
import dev.lions.user.manager.dto.role.RoleAssignmentDTO; import dev.lions.user.manager.dto.role.RoleAssignmentDTO;
import dev.lions.user.manager.dto.role.RoleDTO; import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.enums.role.TypeRole; import dev.lions.user.manager.enums.role.TypeRole;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage; import jakarta.faces.application.FacesMessage;
@@ -67,13 +68,27 @@ public class RoleGestionBean implements Serializable {
* Charger les rôles Realm * Charger les rôles Realm
*/ */
public void loadRealmRoles() { public void loadRealmRoles() {
if (realmName == null || realmName.isEmpty()) {
LOGGER.warning("Realm non sélectionné, impossible de charger les rôles");
addErrorMessage("Veuillez sélectionner un realm");
return;
}
try { try {
LOGGER.info("Chargement des rôles Realm pour le realm: " + realmName);
realmRoles = roleServiceClient.getAllRealmRoles(realmName); realmRoles = roleServiceClient.getAllRealmRoles(realmName);
updateAllRoles(); updateAllRoles();
LOGGER.info("Chargement de " + realmRoles.size() + " rôles Realm"); LOGGER.info("Chargement réussi: " + realmRoles.size() + " rôles Realm trouvés");
if (realmRoles.isEmpty()) {
addErrorMessage("Aucun rôle Realm trouvé dans le realm: " + realmName);
}
} catch (Exception e) { } catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des rôles Realm: " + e.getMessage()); String errorMsg = "Erreur lors du chargement des rôles Realm pour le realm '" + realmName + "': " + e.getMessage();
addErrorMessage("Erreur lors du chargement des rôles Realm"); LOGGER.severe(errorMsg);
LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e);
addErrorMessage(errorMsg);
realmRoles = new ArrayList<>(); // Réinitialiser en cas d'erreur
updateAllRoles();
} }
} }
@@ -212,6 +227,53 @@ public class RoleGestionBean implements Serializable {
} }
} }
/**
* Attribuer un rôle à un utilisateur (depuis les paramètres de requête)
*/
public void assignRoleFromParams() {
FacesContext context = FacesContext.getCurrentInstance();
String userId = context.getExternalContext().getRequestParameterMap().get("userId");
String roleName = context.getExternalContext().getRequestParameterMap().get("roleName");
if (userId != null && roleName != null) {
assignRoleToUser(userId, roleName);
} else {
addErrorMessage("Paramètres manquants: userId ou roleName");
}
}
/**
* Révoquer un rôle d'un utilisateur (depuis les paramètres de requête)
*/
public void revokeRoleFromParams() {
FacesContext context = FacesContext.getCurrentInstance();
String userId = context.getExternalContext().getRequestParameterMap().get("userId");
String roleName = context.getExternalContext().getRequestParameterMap().get("roleName");
if (userId != null && roleName != null) {
revokeRoleFromUser(userId, roleName);
} else {
addErrorMessage("Paramètres manquants: userId ou roleName");
}
}
/**
* Obtenir les rôles RoleDTO correspondant aux noms de rôles de l'utilisateur
*/
public List<RoleDTO> getUserRolesDTOs(UserDTO user) {
if (user == null || user.getRealmRoles() == null || user.getRealmRoles().isEmpty()) {
return new ArrayList<>();
}
if (allRoles == null || allRoles.isEmpty()) {
return new ArrayList<>();
}
return allRoles.stream()
.filter(role -> user.getRealmRoles().contains(role.getName()))
.collect(java.util.stream.Collectors.toList());
}
/** /**
* Réinitialiser le formulaire * Réinitialiser le formulaire
*/ */
@@ -224,8 +286,16 @@ public class RoleGestionBean implements Serializable {
* Charger les realms disponibles * Charger les realms disponibles
*/ */
private void loadRealms() { private void loadRealms() {
// TODO: Implémenter la récupération des realms depuis Keycloak try {
availableRealms = List.of("master", "btpxpress", "unionflow"); // Pour l'instant, utiliser les realms de la configuration
// TODO: Implémenter la récupération des realms depuis Keycloak via un endpoint API
availableRealms = List.of("master", "lions-user-manager", "btpxpress", "test-realm");
LOGGER.info("Realms disponibles chargés: " + availableRealms.size());
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage());
// Fallback sur une liste par défaut
availableRealms = List.of("master");
}
} }
// Méthodes utilitaires // Méthodes utilitaires

View File

@@ -185,6 +185,50 @@ public class UserListBean implements Serializable {
} }
} }
/**
* Obtenir le nombre d'utilisateurs actifs
*/
public long getActiveUsersCount() {
if (users == null || users.isEmpty()) {
return 0;
}
return users.stream()
.filter(user -> user.getEnabled() != null && user.getEnabled())
.count();
}
/**
* Obtenir le nombre d'utilisateurs désactivés
*/
public long getDisabledUsersCount() {
if (users == null || users.isEmpty()) {
return 0;
}
return users.stream()
.filter(user -> user.getEnabled() != null && !user.getEnabled())
.count();
}
/**
* Obtenir le pourcentage d'utilisateurs actifs
*/
public int getActiveUsersPercentage() {
if (totalRecords == 0) {
return 0;
}
return (int) Math.round((double) getActiveUsersCount() / totalRecords * 100);
}
/**
* Obtenir le pourcentage d'utilisateurs désactivés
*/
public int getDisabledUsersPercentage() {
if (totalRecords == 0) {
return 0;
}
return (int) Math.round((double) getDisabledUsersCount() / totalRecords * 100);
}
/** /**
* Charger les realms disponibles * Charger les realms disponibles
*/ */

View File

@@ -22,9 +22,7 @@
<ui:include src="/templates/components/role-management/role-assignment.xhtml"> <ui:include src="/templates/components/role-management/role-assignment.xhtml">
<ui:param name="user" value="#{userProfilBean.user}" /> <ui:param name="user" value="#{userProfilBean.user}" />
<ui:param name="availableRoles" value="#{roleGestionBean.allRoles}" /> <ui:param name="availableRoles" value="#{roleGestionBean.allRoles}" />
<ui:param name="userRoles" value="#{userProfilBean.user.realmRoles != null ? roleGestionBean.allRoles.stream().filter(r -> userProfilBean.user.realmRoles.contains(r.name)).collect(java.util.stream.Collectors.toList()) : new java.util.ArrayList()}" /> <ui:param name="userRoles" value="#{roleGestionBean.getUserRolesDTOs(userProfilBean.user)}" />
<ui:param name="assignAction" value="#{roleGestionBean.assignRoleToUser(userProfilBean.user.id, role.id)}" />
<ui:param name="revokeAction" value="#{roleGestionBean.revokeRoleFromUser(userProfilBean.user.id, role.id)}" />
<ui:param name="update" value="roleAssignmentPanel" /> <ui:param name="update" value="roleAssignmentPanel" />
</ui:include> </ui:include>
</div> </div>

View File

@@ -48,7 +48,7 @@
<f:selectItems value="#{roleGestionBean.availableRealms}" /> <f:selectItems value="#{roleGestionBean.availableRealms}" />
<p:ajax event="change" <p:ajax event="change"
listener="#{roleGestionBean.loadRealmRoles}" listener="#{roleGestionBean.loadRealmRoles}"
update="realmRolesPanel clientRolesPanel" /> update=":formRealmRoles:realmRolesPanel :formClientRoles:clientRolesPanel" />
</p:selectOneMenu> </p:selectOneMenu>
<p:outputLabel for="clientFilter" value="Client" /> <p:outputLabel for="clientFilter" value="Client" />
@@ -59,7 +59,7 @@
<f:selectItems value="#{roleGestionBean.availableClients}" /> <f:selectItems value="#{roleGestionBean.availableClients}" />
<p:ajax event="change" <p:ajax event="change"
listener="#{roleGestionBean.loadClientRoles}" listener="#{roleGestionBean.loadClientRoles}"
update="clientRolesPanel" /> update=":formClientRoles:clientRolesPanel" />
</p:selectOneMenu> </p:selectOneMenu>
<p:outputLabel for="typeFilter" value="Type" /> <p:outputLabel for="typeFilter" value="Type" />
@@ -131,7 +131,9 @@
<ui:param name="mode" value="create" /> <ui:param name="mode" value="create" />
<ui:param name="showClientSelector" value="false" /> <ui:param name="showClientSelector" value="false" />
<ui:param name="submitAction" value="#{roleGestionBean.createRealmRole}" /> <ui:param name="submitAction" value="#{roleGestionBean.createRealmRole}" />
<ui:param name="update" value="realmRolesPanel" /> <ui:param name="hasSubmitAction" value="true" />
<ui:param name="update" value=":formRealmRoles:realmRolesPanel" />
<ui:param name="useParentForm" value="true" />
</ui:include> </ui:include>
</h:form> </h:form>
</p:dialog> </p:dialog>
@@ -148,7 +150,9 @@
<ui:param name="mode" value="create" /> <ui:param name="mode" value="create" />
<ui:param name="showClientSelector" value="true" /> <ui:param name="showClientSelector" value="true" />
<ui:param name="submitAction" value="#{roleGestionBean.createClientRole}" /> <ui:param name="submitAction" value="#{roleGestionBean.createClientRole}" />
<ui:param name="update" value="clientRolesPanel" /> <ui:param name="hasSubmitAction" value="true" />
<ui:param name="update" value=":formClientRoles:clientRolesPanel" />
<ui:param name="useParentForm" value="true" />
</ui:include> </ui:include>
</h:form> </h:form>
</p:dialog> </p:dialog>

View File

@@ -25,6 +25,7 @@
<ui:param name="showRealmSelector" value="true" /> <ui:param name="showRealmSelector" value="true" />
<ui:param name="showPasswordFields" value="true" /> <ui:param name="showPasswordFields" value="true" />
<ui:param name="submitAction" value="#{userCreationBean.createUser}" /> <ui:param name="submitAction" value="#{userCreationBean.createUser}" />
<ui:param name="hasSubmitAction" value="true" />
<ui:param name="cancelOutcome" value="/pages/user-manager/users/list" /> <ui:param name="cancelOutcome" value="/pages/user-manager/users/list" />
</ui:include> </ui:include>
</div> </div>

View File

@@ -29,55 +29,78 @@
</ui:define> </ui:define>
</ui:include> </ui:include>
<!-- Statistiques --> <!-- Statistiques KPI -->
<div class="grid mb-4"> <div class="grid mb-4">
<div class="col-12 md:col-3"> <!-- Total Utilisateurs -->
<ui:include src="/templates/components/shared/cards/user-stat-card.xhtml"> <ui:include src="/templates/components/shared/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Utilisateurs" /> <ui:param name="title" value="Total Utilisateurs" />
<ui:param name="value" value="#{userListBean.totalRecords}" /> <ui:param name="value" value="#{userListBean.totalRecords}" />
<ui:param name="icon" value="pi-users" /> <ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="blue-600" /> <ui:param name="iconColor" value="blue-600" />
</ui:include> <ui:param name="subtitle" value="Utilisateurs dans le realm" />
</div> <ui:param name="clickable" value="true" />
<div class="col-12 md:col-3"> <ui:param name="clickOutcome" value="/pages/user-manager/users/list" />
<ui:include src="/templates/components/shared/cards/user-stat-card.xhtml"> </ui:include>
<ui:param name="title" value="Utilisateurs Actifs" />
<ui:param name="value" value="#{userListBean.users.stream().filter(u -> u.enabled).count()}" />
<ui:param name="icon" value="pi-user-check" />
<ui:param name="iconColor" value="green-600" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/shared/cards/user-stat-card.xhtml">
<ui:param name="title" value="Utilisateurs Désactivés" />
<ui:param name="value" value="#{userListBean.users.stream().filter(u -> !u.enabled).count()}" />
<ui:param name="icon" value="pi-user-times" />
<ui:param name="iconColor" value="red-600" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/shared/cards/user-stat-card.xhtml">
<ui:param name="title" value="Realm" />
<ui:param name="value" value="#{userListBean.realmName}" />
<ui:param name="icon" value="pi pi-globe" />
<ui:param name="iconColor" value="purple-600" />
</ui:include>
</div>
</div>
<!-- Barre de recherche --> <!-- Utilisateurs Actifs -->
<div class="card mb-3"> <ui:include src="/templates/components/shared/cards/kpi-card.xhtml">
<ui:include src="/templates/components/user-management/user-search-bar.xhtml"> <ui:param name="title" value="Utilisateurs Actifs" />
<ui:param name="searchCriteria" value="#{userListBean.searchCriteria}" /> <ui:param name="value" value="#{userListBean.activeUsersCount}" />
<ui:param name="searchAction" value="#{userListBean.search}" /> <ui:param name="icon" value="pi-user-check" />
<ui:param name="update" value="userTable" /> <ui:param name="iconColor" value="green-600" />
<ui:param name="showAdvanced" value="true" /> <ui:param name="subtitle" value="#{userListBean.activeUsersPercentage}% du total" />
<ui:param name="progressValue" value="#{userListBean.activeUsersPercentage}" />
<ui:param name="statusIcon" value="pi-check-circle" />
<ui:param name="statusLabel" value="Actifs" />
<ui:param name="statusValue" value="#{userListBean.activeUsersCount} utilisateurs" />
<ui:param name="clickable" value="true" />
<ui:param name="clickOutcome" value="/pages/user-manager/users/list" />
</ui:include>
<!-- Utilisateurs Désactivés -->
<ui:include src="/templates/components/shared/cards/kpi-card.xhtml">
<ui:param name="title" value="Utilisateurs Désactivés" />
<ui:param name="value" value="#{userListBean.disabledUsersCount}" />
<ui:param name="icon" value="pi-user-times" />
<ui:param name="iconColor" value="red-600" />
<ui:param name="subtitle" value="#{userListBean.disabledUsersPercentage}% du total" />
<ui:param name="progressValue" value="#{userListBean.disabledUsersPercentage}" />
<ui:param name="statusIcon" value="pi-times-circle" />
<ui:param name="statusLabel" value="Désactivés" />
<ui:param name="statusValue" value="#{userListBean.disabledUsersCount} utilisateurs" />
<ui:param name="clickable" value="true" />
<ui:param name="clickOutcome" value="/pages/user-manager/users/list" />
</ui:include>
<!-- Realm Actuel -->
<ui:include src="/templates/components/shared/cards/kpi-card.xhtml">
<ui:param name="title" value="Realm Actuel" />
<ui:param name="value" value="#{empty userListBean.realmName ? 'master' : userListBean.realmName}" />
<ui:param name="icon" value="pi-globe" />
<ui:param name="iconColor" value="purple-600" />
<ui:param name="subtitle" value="Realm Keycloak" />
<ui:param name="statusIcon" value="pi-info-circle" />
<ui:param name="statusLabel" value="Realm" />
<ui:param name="statusValue" value="#{empty userListBean.realmName ? 'master' : userListBean.realmName}" />
<ui:param name="showProgress" value="false" />
</ui:include> </ui:include>
</div> </div>
<!-- Tableau des utilisateurs --> <!-- Barre de recherche et Tableau des utilisateurs dans le même formulaire -->
<div class="card"> <h:form id="formUsers">
<h:form id="formUsers"> <!-- Barre de recherche -->
<div class="card mb-3">
<ui:include src="/templates/components/user-management/user-search-bar.xhtml">
<ui:param name="searchCriteria" value="#{userListBean.searchCriteria}" />
<ui:param name="searchAction" value="#{userListBean.search}" />
<ui:param name="update" value="userTable" />
<ui:param name="showAdvanced" value="true" />
<ui:param name="useParentForm" value="true" />
</ui:include>
</div>
<!-- Tableau des utilisateurs -->
<div class="card">
<ui:include src="/templates/components/shared/tables/user-data-table.xhtml"> <ui:include src="/templates/components/shared/tables/user-data-table.xhtml">
<ui:param name="users" value="#{userListBean.users}" /> <ui:param name="users" value="#{userListBean.users}" />
<ui:param name="var" value="user" /> <ui:param name="var" value="user" />
@@ -90,9 +113,8 @@
<ui:param name="showStatus" value="true" /> <ui:param name="showStatus" value="true" />
<ui:param name="update" value="userTable" /> <ui:param name="update" value="userTable" />
</ui:include> </ui:include>
</h:form> </div>
</div> </h:form>
</ui:define> </ui:define>
</ui:composition> </ui:composition>