Task 1.2 - Entités JPA fondamentales
- Création de BaseEntity avec audit trail et soft delete - Création de l'entité User avec Quarkus Security JPA - Création de l'entité Client avec informations d'entreprise - Création de l'entité Coach avec informations professionnelles - Relations JPA one-to-one entre User-Client et User-Coach - Migrations Flyway V1, V2, V3 pour les tables - Données de test dans import.sql - Compilation réussie du module d'implémentation
This commit is contained in:
432
src/main/java/com/gbcm/server/impl/entity/User.java
Normal file
432
src/main/java/com/gbcm/server/impl/entity/User.java
Normal file
@@ -0,0 +1,432 @@
|
||||
package com.gbcm.server.impl.entity;
|
||||
|
||||
import com.gbcm.server.api.enums.UserRole;
|
||||
import io.quarkus.security.jpa.Password;
|
||||
import io.quarkus.security.jpa.Roles;
|
||||
import io.quarkus.security.jpa.UserDefinition;
|
||||
import io.quarkus.security.jpa.Username;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Entité représentant un utilisateur de la plateforme GBCM.
|
||||
* Utilisée pour l'authentification et l'autorisation avec Quarkus Security.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "users", indexes = {
|
||||
@Index(name = "idx_users_email", columnList = "email", unique = true),
|
||||
@Index(name = "idx_users_role", columnList = "role"),
|
||||
@Index(name = "idx_users_active", columnList = "active"),
|
||||
@Index(name = "idx_users_deleted", columnList = "deleted")
|
||||
})
|
||||
@UserDefinition
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "User.findByEmail",
|
||||
query = "SELECT u FROM User u WHERE u.email = :email AND u.deleted = false"),
|
||||
@NamedQuery(name = "User.findActiveUsers",
|
||||
query = "SELECT u FROM User u WHERE u.active = true AND u.deleted = false"),
|
||||
@NamedQuery(name = "User.findByRole",
|
||||
query = "SELECT u FROM User u WHERE u.role = :role AND u.deleted = false"),
|
||||
@NamedQuery(name = "User.searchByNameOrEmail",
|
||||
query = "SELECT u FROM User u WHERE (LOWER(u.firstName) LIKE LOWER(:search) OR LOWER(u.lastName) LIKE LOWER(:search) OR LOWER(u.email) LIKE LOWER(:search)) AND u.deleted = false")
|
||||
})
|
||||
public class User extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Identifiant unique de l'utilisateur.
|
||||
*/
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Prénom de l'utilisateur.
|
||||
*/
|
||||
@Column(name = "first_name", nullable = false, length = 50)
|
||||
@NotBlank(message = "Le prénom est obligatoire")
|
||||
@Size(max = 50, message = "Le prénom ne peut pas dépasser 50 caractères")
|
||||
private String firstName;
|
||||
|
||||
/**
|
||||
* Nom de famille de l'utilisateur.
|
||||
*/
|
||||
@Column(name = "last_name", nullable = false, length = 50)
|
||||
@NotBlank(message = "Le nom est obligatoire")
|
||||
@Size(max = 50, message = "Le nom ne peut pas dépasser 50 caractères")
|
||||
private String lastName;
|
||||
|
||||
/**
|
||||
* Adresse email unique de l'utilisateur.
|
||||
* Utilisée comme nom d'utilisateur pour l'authentification.
|
||||
*/
|
||||
@Column(name = "email", nullable = false, unique = true, length = 255)
|
||||
@NotBlank(message = "L'email est obligatoire")
|
||||
@Email(message = "Format d'email invalide")
|
||||
@Size(max = 255, message = "L'email ne peut pas dépasser 255 caractères")
|
||||
@Username
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Mot de passe haché de l'utilisateur.
|
||||
* Utilisé pour l'authentification avec Quarkus Security.
|
||||
*/
|
||||
@Column(name = "password_hash", nullable = false, length = 255)
|
||||
@NotBlank(message = "Le mot de passe est obligatoire")
|
||||
@Size(max = 255, message = "Le hash du mot de passe ne peut pas dépasser 255 caractères")
|
||||
@Password
|
||||
private String passwordHash;
|
||||
|
||||
/**
|
||||
* Numéro de téléphone de l'utilisateur.
|
||||
*/
|
||||
@Column(name = "phone", length = 20)
|
||||
@Size(max = 20, message = "Le téléphone ne peut pas dépasser 20 caractères")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* Rôle de l'utilisateur dans le système.
|
||||
* Détermine les permissions et l'accès aux fonctionnalités.
|
||||
*/
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "role", nullable = false, length = 20)
|
||||
@NotNull(message = "Le rôle est obligatoire")
|
||||
@Roles
|
||||
private UserRole role;
|
||||
|
||||
/**
|
||||
* Statut d'activation du compte utilisateur.
|
||||
* true = compte actif, false = compte désactivé.
|
||||
*/
|
||||
@Column(name = "active", nullable = false)
|
||||
private boolean active = true;
|
||||
|
||||
/**
|
||||
* Date de dernière connexion de l'utilisateur.
|
||||
*/
|
||||
@Column(name = "last_login_at")
|
||||
private LocalDateTime lastLoginAt;
|
||||
|
||||
/**
|
||||
* Adresse IP de la dernière connexion.
|
||||
*/
|
||||
@Column(name = "last_login_ip", length = 45)
|
||||
@Size(max = 45, message = "L'adresse IP ne peut pas dépasser 45 caractères")
|
||||
private String lastLoginIp;
|
||||
|
||||
/**
|
||||
* Nombre de tentatives de connexion échouées consécutives.
|
||||
*/
|
||||
@Column(name = "failed_login_attempts", nullable = false)
|
||||
private int failedLoginAttempts = 0;
|
||||
|
||||
/**
|
||||
* Date de verrouillage du compte (après trop de tentatives échouées).
|
||||
*/
|
||||
@Column(name = "locked_until")
|
||||
private LocalDateTime lockedUntil;
|
||||
|
||||
/**
|
||||
* Token de réinitialisation de mot de passe.
|
||||
*/
|
||||
@Column(name = "password_reset_token", length = 255)
|
||||
@Size(max = 255, message = "Le token de réinitialisation ne peut pas dépasser 255 caractères")
|
||||
private String passwordResetToken;
|
||||
|
||||
/**
|
||||
* Date d'expiration du token de réinitialisation.
|
||||
*/
|
||||
@Column(name = "password_reset_expires_at")
|
||||
private LocalDateTime passwordResetExpiresAt;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public User() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec les champs obligatoires.
|
||||
*
|
||||
* @param firstName le prénom
|
||||
* @param lastName le nom de famille
|
||||
* @param email l'adresse email
|
||||
* @param passwordHash le mot de passe haché
|
||||
* @param role le rôle de l'utilisateur
|
||||
*/
|
||||
public User(String firstName, String lastName, String email, String passwordHash, UserRole role) {
|
||||
this();
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.email = email;
|
||||
this.passwordHash = passwordHash;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom complet de l'utilisateur.
|
||||
*
|
||||
* @return le nom complet (prénom + nom)
|
||||
*/
|
||||
public String getFullName() {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le compte est verrouillé.
|
||||
*
|
||||
* @return true si le compte est verrouillé, false sinon
|
||||
*/
|
||||
public boolean isLocked() {
|
||||
return lockedUntil != null && LocalDateTime.now().isBefore(lockedUntil);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verrouille le compte pour une durée spécifiée.
|
||||
*
|
||||
* @param lockDurationMinutes durée de verrouillage en minutes
|
||||
*/
|
||||
public void lockAccount(int lockDurationMinutes) {
|
||||
this.lockedUntil = LocalDateTime.now().plusMinutes(lockDurationMinutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Déverrouille le compte et remet à zéro les tentatives échouées.
|
||||
*/
|
||||
public void unlockAccount() {
|
||||
this.lockedUntil = null;
|
||||
this.failedLoginAttempts = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrémente le nombre de tentatives de connexion échouées.
|
||||
*/
|
||||
public void incrementFailedLoginAttempts() {
|
||||
this.failedLoginAttempts++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remet à zéro les tentatives de connexion échouées.
|
||||
*/
|
||||
public void resetFailedLoginAttempts() {
|
||||
this.failedLoginAttempts = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour les informations de dernière connexion.
|
||||
*
|
||||
* @param ipAddress l'adresse IP de connexion
|
||||
*/
|
||||
public void updateLastLogin(String ipAddress) {
|
||||
this.lastLoginAt = LocalDateTime.now();
|
||||
this.lastLoginIp = ipAddress;
|
||||
resetFailedLoginAttempts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un token de réinitialisation de mot de passe.
|
||||
*
|
||||
* @param token le token généré
|
||||
* @param expirationHours durée de validité en heures
|
||||
*/
|
||||
public void setPasswordResetToken(String token, int expirationHours) {
|
||||
this.passwordResetToken = token;
|
||||
this.passwordResetExpiresAt = LocalDateTime.now().plusHours(expirationHours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Efface le token de réinitialisation de mot de passe.
|
||||
*/
|
||||
public void clearPasswordResetToken() {
|
||||
this.passwordResetToken = null;
|
||||
this.passwordResetExpiresAt = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le token de réinitialisation est valide.
|
||||
*
|
||||
* @param token le token à vérifier
|
||||
* @return true si le token est valide, false sinon
|
||||
*/
|
||||
public boolean isPasswordResetTokenValid(String token) {
|
||||
return passwordResetToken != null &&
|
||||
passwordResetToken.equals(token) &&
|
||||
passwordResetExpiresAt != null &&
|
||||
LocalDateTime.now().isBefore(passwordResetExpiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche par email.
|
||||
*
|
||||
* @param email l'adresse email à rechercher
|
||||
* @return l'utilisateur trouvé ou null
|
||||
*/
|
||||
public static User findByEmail(String email) {
|
||||
return find("#User.findByEmail", email).firstResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche des utilisateurs actifs.
|
||||
*
|
||||
* @return la liste des utilisateurs actifs
|
||||
*/
|
||||
public static List<User> findActiveUsers() {
|
||||
return find("#User.findActiveUsers").list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche par rôle.
|
||||
*
|
||||
* @param role le rôle à rechercher
|
||||
* @return la liste des utilisateurs avec ce rôle
|
||||
*/
|
||||
public static List<User> findByRole(UserRole role) {
|
||||
return find("#User.findByRole", role).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche par nom ou email.
|
||||
*
|
||||
* @param search le terme de recherche
|
||||
* @return la liste des utilisateurs correspondants
|
||||
*/
|
||||
public static List<User> searchByNameOrEmail(String search) {
|
||||
String searchPattern = "%" + search + "%";
|
||||
return find("#User.searchByNameOrEmail", searchPattern).list();
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPasswordHash() {
|
||||
return passwordHash;
|
||||
}
|
||||
|
||||
public void setPasswordHash(String passwordHash) {
|
||||
this.passwordHash = passwordHash;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(UserRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public LocalDateTime getLastLoginAt() {
|
||||
return lastLoginAt;
|
||||
}
|
||||
|
||||
public void setLastLoginAt(LocalDateTime lastLoginAt) {
|
||||
this.lastLoginAt = lastLoginAt;
|
||||
}
|
||||
|
||||
public String getLastLoginIp() {
|
||||
return lastLoginIp;
|
||||
}
|
||||
|
||||
public void setLastLoginIp(String lastLoginIp) {
|
||||
this.lastLoginIp = lastLoginIp;
|
||||
}
|
||||
|
||||
public int getFailedLoginAttempts() {
|
||||
return failedLoginAttempts;
|
||||
}
|
||||
|
||||
public void setFailedLoginAttempts(int failedLoginAttempts) {
|
||||
this.failedLoginAttempts = failedLoginAttempts;
|
||||
}
|
||||
|
||||
public LocalDateTime getLockedUntil() {
|
||||
return lockedUntil;
|
||||
}
|
||||
|
||||
public void setLockedUntil(LocalDateTime lockedUntil) {
|
||||
this.lockedUntil = lockedUntil;
|
||||
}
|
||||
|
||||
public String getPasswordResetToken() {
|
||||
return passwordResetToken;
|
||||
}
|
||||
|
||||
public LocalDateTime getPasswordResetExpiresAt() {
|
||||
return passwordResetExpiresAt;
|
||||
}
|
||||
|
||||
public void setPasswordResetExpiresAt(LocalDateTime passwordResetExpiresAt) {
|
||||
this.passwordResetExpiresAt = passwordResetExpiresAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" +
|
||||
"id=" + id +
|
||||
", firstName='" + firstName + '\'' +
|
||||
", lastName='" + lastName + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", role=" + role +
|
||||
", active=" + active +
|
||||
", lastLoginAt=" + lastLoginAt +
|
||||
", failedLoginAttempts=" + failedLoginAttempts +
|
||||
", locked=" + isLocked() +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user