Initial commit: GBCM Client Quarkus implementation with PrimeFaces and Freya theme
This commit is contained in:
195
src/main/java/com/gbcm/client/beans/auth/AuthBean.java
Normal file
195
src/main/java/com/gbcm/client/beans/auth/AuthBean.java
Normal file
@@ -0,0 +1,195 @@
|
||||
package com.gbcm.client.beans.auth;
|
||||
|
||||
import com.gbcm.client.service.GBCMServerClient;
|
||||
import com.gbcm.server.api.dto.UserDTO;
|
||||
import com.gbcm.server.api.dto.LoginRequestDTO;
|
||||
import com.gbcm.server.api.dto.LoginResponseDTO;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Managed Bean pour la gestion de l'authentification
|
||||
*/
|
||||
@Named("authBean")
|
||||
@SessionScoped
|
||||
public class AuthBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
private GBCMServerClient serverClient;
|
||||
|
||||
// Propriétés de connexion
|
||||
private String email;
|
||||
private String password;
|
||||
private boolean rememberMe;
|
||||
|
||||
// Utilisateur connecté
|
||||
private UserDTO currentUser;
|
||||
private String authToken;
|
||||
private boolean authenticated = false;
|
||||
|
||||
/**
|
||||
* Tentative de connexion
|
||||
*/
|
||||
public String login() {
|
||||
try {
|
||||
LoginRequestDTO loginRequest = new LoginRequestDTO();
|
||||
loginRequest.setEmail(email);
|
||||
loginRequest.setPassword(password);
|
||||
loginRequest.setRememberMe(rememberMe);
|
||||
|
||||
LoginResponseDTO response = serverClient.login(loginRequest);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
this.currentUser = response.getUser();
|
||||
this.authToken = response.getToken();
|
||||
this.authenticated = true;
|
||||
|
||||
// Message de succès
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO,
|
||||
"Connexion réussie",
|
||||
"Bienvenue " + currentUser.getFirstName()));
|
||||
|
||||
// Redirection selon le rôle
|
||||
return redirectAfterLogin();
|
||||
} else {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
||||
"Erreur de connexion",
|
||||
response.getMessage()));
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
||||
"Erreur système",
|
||||
"Impossible de se connecter au serveur"));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Déconnexion
|
||||
*/
|
||||
public String logout() {
|
||||
try {
|
||||
if (authToken != null) {
|
||||
serverClient.logout(authToken);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Log l'erreur mais continue la déconnexion
|
||||
}
|
||||
|
||||
// Nettoyage de la session
|
||||
this.currentUser = null;
|
||||
this.authToken = null;
|
||||
this.authenticated = false;
|
||||
this.email = null;
|
||||
this.password = null;
|
||||
this.rememberMe = false;
|
||||
|
||||
// Invalidation de la session JSF
|
||||
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
|
||||
|
||||
return "/index?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirection après connexion selon le rôle
|
||||
*/
|
||||
private String redirectAfterLogin() {
|
||||
if (currentUser == null) {
|
||||
return "/index?faces-redirect=true";
|
||||
}
|
||||
|
||||
switch (currentUser.getRole()) {
|
||||
case "ADMIN":
|
||||
return "/pages/admin/dashboard?faces-redirect=true";
|
||||
case "COACH":
|
||||
return "/pages/coaching/dashboard?faces-redirect=true";
|
||||
case "CLIENT":
|
||||
return "/pages/dashboard/client?faces-redirect=true";
|
||||
default:
|
||||
return "/pages/dashboard/home?faces-redirect=true";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigation vers le profil
|
||||
*/
|
||||
public String goToProfile() {
|
||||
return "/pages/profile/edit?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigation vers les paramètres
|
||||
*/
|
||||
public String goToSettings() {
|
||||
return "/pages/settings/general?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérification des permissions
|
||||
*/
|
||||
public boolean hasRole(String role) {
|
||||
return authenticated && currentUser != null &&
|
||||
role.equals(currentUser.getRole());
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return hasRole("ADMIN");
|
||||
}
|
||||
|
||||
public boolean isCoach() {
|
||||
return hasRole("COACH");
|
||||
}
|
||||
|
||||
public boolean isClient() {
|
||||
return hasRole("CLIENT");
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public boolean isRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public void setRememberMe(boolean rememberMe) {
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
|
||||
public UserDTO getCurrentUser() {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
public String getAuthToken() {
|
||||
return authToken;
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
return authenticated;
|
||||
}
|
||||
}
|
||||
47
src/main/resources/application.properties
Normal file
47
src/main/resources/application.properties
Normal file
@@ -0,0 +1,47 @@
|
||||
# GBCM Client Configuration
|
||||
quarkus.application.name=gbcm-client
|
||||
quarkus.application.version=1.0.0-SNAPSHOT
|
||||
|
||||
# Server Configuration
|
||||
quarkus.http.port=8080
|
||||
quarkus.http.host=0.0.0.0
|
||||
|
||||
# JSF Configuration
|
||||
quarkus.servlet.context-path=/gbcm
|
||||
|
||||
# Security Configuration
|
||||
quarkus.security.auth.enabled=true
|
||||
|
||||
# REST Client Configuration - GBCM Server API
|
||||
gbcm.server.api.url=http://localhost:8081/api/v1
|
||||
quarkus.rest-client."com.gbcm.client.service.GBCMServerClient".url=${gbcm.server.api.url}
|
||||
|
||||
# Database Configuration (for session storage)
|
||||
quarkus.datasource.db-kind=postgresql
|
||||
quarkus.datasource.username=gbcm_user
|
||||
quarkus.datasource.password=gbcm_password
|
||||
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/gbcm_client
|
||||
|
||||
# Hibernate Configuration
|
||||
quarkus.hibernate-orm.database.generation=update
|
||||
quarkus.hibernate-orm.log.sql=false
|
||||
|
||||
# Logging Configuration
|
||||
quarkus.log.level=INFO
|
||||
quarkus.log.category."com.gbcm".level=DEBUG
|
||||
|
||||
# Development Configuration
|
||||
%dev.quarkus.log.level=DEBUG
|
||||
%dev.quarkus.hibernate-orm.log.sql=true
|
||||
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:gbcm_client_dev;DB_CLOSE_DELAY=-1
|
||||
%dev.quarkus.datasource.db-kind=h2
|
||||
|
||||
# Production Configuration
|
||||
%prod.quarkus.log.level=WARN
|
||||
%prod.quarkus.datasource.jdbc.url=${DATABASE_URL}
|
||||
|
||||
# PrimeFaces Configuration
|
||||
primefaces.theme=freya
|
||||
primefaces.font-awesome=true
|
||||
primefaces.client-side-validation=true
|
||||
primefaces.move-scripts-to-bottom=true
|
||||
87
src/main/webapp/WEB-INF/web.xml
Normal file
87
src/main/webapp/WEB-INF/web.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
|
||||
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
|
||||
version="5.0">
|
||||
|
||||
<display-name>GBCM Client Application</display-name>
|
||||
<description>Interface web GBCM pour la gestion des services de consulting</description>
|
||||
|
||||
<!-- JSF Configuration -->
|
||||
<context-param>
|
||||
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
|
||||
<param-value>Development</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>jakarta.faces.STATE_SAVING_METHOD</param-name>
|
||||
<param-value>server</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>jakarta.faces.FACELETS_SKIP_COMMENTS</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- PrimeFaces Configuration -->
|
||||
<context-param>
|
||||
<param-name>primefaces.THEME</param-name>
|
||||
<param-value>freya</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>primefaces.FONT_AWESOME</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>primefaces.CLIENT_SIDE_VALIDATION</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- JSF Servlet -->
|
||||
<servlet>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Faces Servlet</servlet-name>
|
||||
<url-pattern>*.xhtml</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Security Configuration -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Protected Pages</web-resource-name>
|
||||
<url-pattern>/pages/dashboard/*</url-pattern>
|
||||
<url-pattern>/pages/coaching/*</url-pattern>
|
||||
<url-pattern>/pages/workshops/*</url-pattern>
|
||||
<url-pattern>/pages/admin/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
<role-name>coach</role-name>
|
||||
<role-name>admin</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<!-- Welcome Files -->
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.xhtml</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<!-- Error Pages -->
|
||||
<error-page>
|
||||
<error-code>404</error-code>
|
||||
<location>/pages/error/404.xhtml</location>
|
||||
</error-page>
|
||||
|
||||
<error-page>
|
||||
<error-code>500</error-code>
|
||||
<location>/pages/error/500.xhtml</location>
|
||||
</error-page>
|
||||
|
||||
</web-app>
|
||||
135
src/main/webapp/templates/layout.xhtml
Normal file
135
src/main/webapp/templates/layout.xhtml
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui">
|
||||
|
||||
<h:head>
|
||||
<title>
|
||||
<ui:insert name="title">GBCM - Global Business Consulting and Management</ui:insert>
|
||||
</title>
|
||||
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<meta name="description" content="GBCM - Services de conseil en management et développement professionnel"/>
|
||||
<meta name="author" content="GBCM LLC"/>
|
||||
|
||||
<!-- Freya Theme CSS -->
|
||||
<h:outputStylesheet name="primefaces-freya/theme.css"/>
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<h:outputStylesheet name="css/gbcm-custom.css"/>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="#{request.contextPath}/resources/images/favicon.ico"/>
|
||||
</h:head>
|
||||
|
||||
<h:body>
|
||||
<div class="layout-wrapper">
|
||||
|
||||
<!-- Top Bar -->
|
||||
<div class="layout-topbar">
|
||||
<div class="layout-topbar-wrapper">
|
||||
<div class="layout-topbar-left">
|
||||
<h:link outcome="/index" styleClass="layout-topbar-logo">
|
||||
<h:graphicImage name="images/gbcm-logo.png" alt="GBCM Logo" height="40"/>
|
||||
<span class="layout-topbar-logo-text">GBCM</span>
|
||||
</h:link>
|
||||
</div>
|
||||
|
||||
<div class="layout-topbar-right">
|
||||
<ul class="layout-topbar-actions">
|
||||
<li>
|
||||
<p:commandButton icon="pi pi-user" styleClass="p-button-text p-button-plain"
|
||||
onclick="PF('userMenuDialog').show()"/>
|
||||
</li>
|
||||
<li>
|
||||
<p:commandButton icon="pi pi-bell" styleClass="p-button-text p-button-plain"
|
||||
onclick="PF('notificationDialog').show()"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Menu -->
|
||||
<div class="layout-sidebar">
|
||||
<div class="layout-menu">
|
||||
<p:menu model="#{menuBean.menuModel}" styleClass="layout-menu-items"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="layout-main">
|
||||
<div class="layout-main-content">
|
||||
|
||||
<!-- Breadcrumb -->
|
||||
<div class="content-section">
|
||||
<p:breadCrumb model="#{breadcrumbBean.breadcrumbModel}" styleClass="custom-breadcrumb"/>
|
||||
</div>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div class="content-section">
|
||||
<ui:insert name="content">
|
||||
<p:panel header="Contenu par défaut">
|
||||
<p>Aucun contenu spécifique défini pour cette page.</p>
|
||||
</p:panel>
|
||||
</ui:insert>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="layout-footer">
|
||||
<div class="layout-footer-wrapper">
|
||||
<span>© 2024 GBCM LLC - Global Business Consulting and Management</span>
|
||||
<div class="layout-footer-right">
|
||||
<span>Version 1.0.0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Menu Dialog -->
|
||||
<p:dialog header="Profil Utilisateur" widgetVar="userMenuDialog" modal="true"
|
||||
width="400" height="300" resizable="false">
|
||||
<div class="user-profile-content">
|
||||
<p:outputLabel value="#{authBean.currentUser.fullName}" styleClass="user-name"/>
|
||||
<p:outputLabel value="#{authBean.currentUser.email}" styleClass="user-email"/>
|
||||
|
||||
<div class="user-actions">
|
||||
<p:commandButton value="Mon Profil" icon="pi pi-user"
|
||||
action="#{authBean.goToProfile}" styleClass="p-button-outlined"/>
|
||||
<p:commandButton value="Paramètres" icon="pi pi-cog"
|
||||
action="#{authBean.goToSettings}" styleClass="p-button-outlined"/>
|
||||
<p:commandButton value="Déconnexion" icon="pi pi-sign-out"
|
||||
action="#{authBean.logout}" styleClass="p-button-danger"/>
|
||||
</div>
|
||||
</div>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Notification Dialog -->
|
||||
<p:dialog header="Notifications" widgetVar="notificationDialog" modal="true"
|
||||
width="500" height="400" resizable="false">
|
||||
<p:dataTable value="#{notificationBean.notifications}" var="notification"
|
||||
emptyMessage="Aucune notification">
|
||||
<p:column headerText="Message">
|
||||
<h:outputText value="#{notification.message}"/>
|
||||
</p:column>
|
||||
<p:column headerText="Date">
|
||||
<h:outputText value="#{notification.createdAt}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy HH:mm"/>
|
||||
</h:outputText>
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
</p:dialog>
|
||||
|
||||
<!-- Global Messages -->
|
||||
<p:growl id="globalMessages" showDetail="true" life="5000"/>
|
||||
|
||||
<!-- Custom JavaScript -->
|
||||
<h:outputScript name="js/gbcm-custom.js"/>
|
||||
|
||||
</h:body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user