Squelette Symfony, entités Server et Action

This commit is contained in:
Yasser Boulayoune 2026-04-07 10:12:00 +02:00
commit 52ecb4204c
46 changed files with 4308 additions and 0 deletions

0
src/Entity/.gitignore vendored Normal file
View file

131
src/Entity/ActionLog.php Normal file
View file

@ -0,0 +1,131 @@
<?php
/**
* @file ActionLog.php
* @brief Entité representant une entrée dans le journal d'audit
*
* Chaque action SSH effectuée (start, stop, restart, status d'un service
* ou commande terminal) est enregistrée ici pour assurer la tracabilité.
* Permet de savoir qui a fait quoi et quand sur quel serveur.
*
* @package App\Entity
* @author Yasser
*/
namespace App\Entity;
use App\Repository\ActionLogRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @class ActionLog
* @brief Journal des actions effectuées sur les serveurs via SSH
*
* Stocke chaque action avec son type (start/stop/restart/status),
* son resultat (success/failure/needs_sudo), la sortie de la commande
* et l'utilisateur qui a déclenché l'action.
* L'utilisateur peut etre null si l'action est fait par le systeme.
*/
#[ORM\Entity(repositoryClass: ActionLogRepository::class)]
#[ORM\Table(name: 'action_log')]
class ActionLog
{
/**
* @var int|null Identifiant unique du log
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'log_id')]
private ?int $id = null;
/**
* @var string|null Type d'action: 'start', 'stop', 'restart', 'status' ou 'command'
*/
#[ORM\Column(name: 'action_type', length: 20)]
private ?string $actionType = null;
/**
* @var string|null Statut de l'action: 'success', 'failure' ou 'needs_sudo'
*/
#[ORM\Column(name: 'status', length: 10)]
private ?string $status = null;
/**
* @var string|null Sortie brute de la commande SSH, peut etre null si needs_sudo
*/
#[ORM\Column(name: 'output', type: 'text', nullable: true)]
private ?string $output = null;
/**
* @var \DateTimeImmutable|null Date et heure d'execution de l'action
*/
#[ORM\Column(name: 'executed_at')]
private ?\DateTimeImmutable $executedAt = null;
/**
* @var User|null Utilisateur qui a effectué l'action (null = systeme)
*/
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'actionLogs')]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'user_id', nullable: true)]
private ?User $user = null;
/**
* @var Server|null Serveur sur lequel l'action a été effectuée
*/
#[ORM\ManyToOne(targetEntity: Server::class, inversedBy: 'actionLogs')]
#[ORM\JoinColumn(name: 'server_id', referencedColumnName: 'server_id', nullable: false)]
private ?Server $server = null;
/**
* @brief Constructeur - enregistre automatiquement l'heure d'execution
*/
public function __construct()
{
$this->executedAt = new \DateTimeImmutable();
}
/**
* @return int|null Identifiant du log
*/
public function getId(): ?int { return $this->id; }
/**
* @brief Retourne le type d'action effectué
* @return string|null 'start', 'stop', 'restart', 'status' ou 'command'
*/
public function getActionType(): ?string { return $this->actionType; }
/**
* @param string $actionType Le type d'action
* @return static
*/
public function setActionType(string $actionType): static { $this->actionType = $actionType; return $this; }
/**
* @brief Retourne le statut de l'action
* @return string|null 'success', 'failure' ou 'needs_sudo'
*/
public function getStatus(): ?string { return $this->status; }
/** @param string $status @return static */
public function setStatus(string $status): static { $this->status = $status; return $this; }
/** @return string|null La sortie de la commande SSH */
public function getOutput(): ?string { return $this->output; }
/** @param string|null $output @return static */
public function setOutput(?string $output): static { $this->output = $output; return $this; }
/**
* @brief Retourne la date d'execution du log
* @return \DateTimeImmutable|null
*/
public function getExecutedAt(): ?\DateTimeImmutable { return $this->executedAt; }
/** @return User|null L'utilisateur qui a effectué l'action */
public function getUser(): ?User { return $this->user; }
/** @param User|null $user @return static */
public function setUser(?User $user): static { $this->user = $user; return $this; }
/** @return Server|null Le serveur cible de l'action */
public function getServer(): ?Server { return $this->server; }
/** @param Server|null $server @return static */
public function setServer(?Server $server): static { $this->server = $server; return $this; }
}

230
src/Entity/Server.php Normal file
View file

@ -0,0 +1,230 @@
<?php
/**
* @file Server.php
* @brief Entité representant un serveur Linux distant geré par l'application
*
* Cette classe correspond a la table 'server' en base de donnée.
* Elle stock toutes les informations necessaires pour etablir une
* connexion SSH et gerer les services systemd du serveur.
*
* @package App\Entity
* @author Yasser
*/
namespace App\Entity;
use App\Repository\ServerRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @class Server
* @brief Entité Doctrine pour les serveurs distants
*
* Represente un serveur Linux administrable via SSH. Chaque serveur
* appartient a un proprietaire (User avec ROLE_ADMIN) et peut avoir
* plusieurs services systemd associées ainsi que des accés granulaires
* pour les opérateurs.
*/
#[ORM\Entity(repositoryClass: ServerRepository::class)]
#[ORM\Table(name: 'server')]
class Server
{
/**
* @var int|null Identifiant unique auto-incrementé du serveur
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'server_id')]
private ?int $id = null;
/**
* @var string|null Nom lisible du serveur (ex: "Prod Web Server")
*/
#[ORM\Column(name: 'name', length: 100)]
#[Assert\NotBlank(message: 'The server name is required')]
#[Assert\Length(max: 100)]
private ?string $name = null;
/**
* @var string|null Adresse IP du serveur, supporte IPv4 et IPv6
*/
#[ORM\Column(name: 'ip_address', length: 45)]
#[Assert\NotBlank(message: 'The IP address is required')]
#[Assert\Ip(version: 'all', message: 'Please provide a valid IP address')]
private ?string $ipAddress = null;
/**
* @var int Port SSH du serveur, par defaut 22
*/
#[ORM\Column(name: 'ssh_port', type: 'smallint')]
#[Assert\NotBlank]
#[Assert\Range(min: 1, max: 65535)]
private int $sshPort = 22;
/**
* @var string|null Nom d'utilisateur SSH pour la connexion
*/
#[ORM\Column(name: 'ssh_user', length: 50)]
#[Assert\NotBlank(message: 'The SSH user is required')]
private ?string $sshUser = null;
/**
* @var string|null Mot de passe SSH stocké en clair (TODO: chiffrer)
*/
#[ORM\Column(name: 'ssh_password', type: 'text')]
#[Assert\NotBlank(message: 'The SSH password is required')]
private ?string $sshPassword = null;
/**
* @var string|null Description optionel du serveur
*/
#[ORM\Column(name: 'description', type: 'text', nullable: true)]
private ?string $description = null;
/**
* @var string Dernier statut connu: 'online', 'offline' ou 'unknown'
*/
#[ORM\Column(name: 'last_status', length: 10)]
private string $lastStatus = 'unknown';
/**
* @var \DateTimeImmutable|null Date de creation de l'enregistrement
*/
#[ORM\Column(name: 'created_at')]
private ?\DateTimeImmutable $createdAt = null;
/**
* @var User|null Utilisateur propriétaire du serveur (doit etre ROLE_ADMIN)
*/
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'servers')]
#[ORM\JoinColumn(name: 'owner_id', referencedColumnName: 'user_id', nullable: false)]
private ?User $owner = null;
/**
* @var Collection Liste des services systemd surveillé sur ce serveur
*/
#[ORM\OneToMany(targetEntity: Service::class, mappedBy: 'server', cascade: ['remove'])]
private Collection $services;
/**
* @var Collection Historique des actions effectuées sur ce serveur
*/
#[ORM\OneToMany(targetEntity: ActionLog::class, mappedBy: 'server', cascade: ['remove'])]
private Collection $actionLogs;
/**
* @var Collection Liste des accès operateurs configurés pour ce serveur
*/
#[ORM\OneToMany(targetEntity: ServerAccess::class, mappedBy: 'server', cascade: ['remove'])]
private Collection $serverAccesses;
/**
* @brief Constructeur - initialise les collections et la date de creation
*
* Les collections Doctrine doivent etre initialisées ici sinon
* on a des erreur lors du premier acces avant que Doctrine les charge.
*/
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
$this->services = new ArrayCollection();
$this->actionLogs = new ArrayCollection();
$this->serverAccesses = new ArrayCollection();
}
/**
* @brief Retourne l'identifiant du serveur
* @return int|null L'id en base de donnée, null si pas encore persisté
*/
public function getId(): ?int { return $this->id; }
/**
* @brief Retourne le nom du serveur
* @return string|null Le nom du serveur
*/
public function getName(): ?string { return $this->name; }
/**
* @brief Definit le nom du serveur
* @param string $name Nouveau nom a assigner
* @return static Pour le chaining de méthodes
*/
public function setName(string $name): static { $this->name = $name; return $this; }
/** @return string|null Adresse IP du serveur */
public function getIpAddress(): ?string { return $this->ipAddress; }
/**
* @param string $ipAddress Adresse IP (IPv4 ou IPv6)
* @return static
*/
public function setIpAddress(string $ipAddress): static { $this->ipAddress = $ipAddress; return $this; }
/** @return int Numero de port SSH (defaut 22) */
public function getSshPort(): int { return $this->sshPort; }
/** @param int $sshPort Port entre 1 et 65535 @return static */
public function setSshPort(int $sshPort): static { $this->sshPort = $sshPort; return $this; }
/** @return string|null Nom d'utilisateur pour la connexion SSH */
public function getSshUser(): ?string { return $this->sshUser; }
/** @param string $sshUser @return static */
public function setSshUser(string $sshUser): static { $this->sshUser = $sshUser; return $this; }
/** @return string|null Mot de passe SSH (attention donnée sensible) */
public function getSshPassword(): ?string { return $this->sshPassword; }
/** @param string $sshPassword @return static */
public function setSshPassword(string $sshPassword): static { $this->sshPassword = $sshPassword; return $this; }
/** @return string|null Description optionel du serveur */
public function getDescription(): ?string { return $this->description; }
/** @param string|null $description Peut etre null @return static */
public function setDescription(?string $description): static { $this->description = $description; return $this; }
/**
* @brief Retourne le dernier statut connu du serveur
* @return string 'online', 'offline' ou 'unknown'
*/
public function getLastStatus(): string { return $this->lastStatus; }
/**
* @brief Met a jour le statut du serveur apres une vérification SSH
* @param string $lastStatus Le nouveau statut a stocker
* @return static
*/
public function setLastStatus(string $lastStatus): static { $this->lastStatus = $lastStatus; return $this; }
/** @return \DateTimeImmutable|null Date de creation de cet enregistrement */
public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; }
/** @return User|null Le proprietaire administrateur du serveur */
public function getOwner(): ?User { return $this->owner; }
/**
* @param User|null $owner L'utilisateur propriétaire, doit avoir ROLE_ADMIN
* @return static
*/
public function setOwner(?User $owner): static { $this->owner = $owner; return $this; }
/**
* @brief Retourne la collection de services systemd du serveur
* @return Collection Collection d'objets Service
*/
public function getServices(): Collection { return $this->services; }
/**
* @brief Retourne l'historique des actions sur ce serveur
* @return Collection Collection d'objets ActionLog
*/
public function getActionLogs(): Collection { return $this->actionLogs; }
/**
* @brief Retourne les accés configurés pour les opérateurs
* @return Collection Collection d'objets ServerAccess
*/
public function getServerAccesses(): Collection { return $this->serverAccesses; }
}

View file

@ -0,0 +1,98 @@
<?php
/**
* @file ServerAccess.php
* @brief Entité representant l'accès d'un opérateur a un serveur specifique
*
* Permet d'assigner un opérateur a un serveur avec des identifiants SSH
* dédié (different de ceux de l'admin). La contrainte d'unicité empeche
* de donner plusieurs fois acces au meme user sur le meme serveur.
*
* @package App\Entity
* @author Yasser
*/
namespace App\Entity;
use App\Repository\ServerAccessRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @class ServerAccess
* @brief Relation entre un opérateur et un serveur avec ses propres identifiants SSH
*
* Table de liaison enrichie entre User et Server. Chaque operateur
* peut avoir des credentials SSH different selon le serveur auquel
* il a acces. La contrainte uq_server_user evite les doublons.
*/
#[ORM\Entity(repositoryClass: ServerAccessRepository::class)]
#[ORM\Table(name: 'server_access')]
#[ORM\UniqueConstraint(name: 'uq_server_user', columns: ['server_id', 'user_id'])]
class ServerAccess
{
/**
* @var int|null Identifiant unique de cet accés
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'access_id')]
private ?int $id = null;
/**
* @var Server|null Le serveur auquel l'opérateur a accés
* Supprimé en cascade si le serveur est supprimé
*/
#[ORM\ManyToOne(targetEntity: Server::class, inversedBy: 'serverAccesses')]
#[ORM\JoinColumn(name: 'server_id', referencedColumnName: 'server_id', nullable: false, onDelete: 'CASCADE')]
private ?Server $server = null;
/**
* @var User|null L'opérateur qui a l'accés au serveur
* Supprimé en cascade si l'utilisateur est supprimé
*/
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'serverAccesses')]
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'user_id', nullable: false, onDelete: 'CASCADE')]
private ?User $user = null;
/**
* @var string|null Identifiant SSH propre a cet opérateur sur ce serveur
* Peut etre different de l'utilisateur SSH admin du serveur
*/
#[ORM\Column(name: 'ssh_user', length: 50)]
private ?string $sshUser = null;
/**
* @var string|null Mot de passe SSH propre a cet opérateur
*/
#[ORM\Column(name: 'ssh_password', type: 'text')]
private ?string $sshPassword = null;
/** @return int|null */
public function getId(): ?int { return $this->id; }
/**
* @brief Retourne le serveur cible de cet accés
* @return Server|null
*/
public function getServer(): ?Server { return $this->server; }
/** @param Server $server @return static */
public function setServer(Server $server): static { $this->server = $server; return $this; }
/**
* @brief Retourne l'opérateur qui possede cet accés
* @return User|null
*/
public function getUser(): ?User { return $this->user; }
/** @param User $user @return static */
public function setUser(User $user): static { $this->user = $user; return $this; }
/** @return string|null Identifiant SSH de l'opérateur */
public function getSshUser(): ?string { return $this->sshUser; }
/** @param string $sshUser @return static */
public function setSshUser(string $sshUser): static { $this->sshUser = $sshUser; return $this; }
/** @return string|null Mot de passe SSH de l'opérateur */
public function getSshPassword(): ?string { return $this->sshPassword; }
/** @param string $sshPassword @return static */
public function setSshPassword(string $sshPassword): static { $this->sshPassword = $sshPassword; return $this; }
}

93
src/Entity/Service.php Normal file
View file

@ -0,0 +1,93 @@
<?php
/**
* @file Service.php
* @brief Entité representant un service systemd surveillé sur un serveur
*
* Un service est associé a un Server et correspond a une unité systemd
* (ex: nginx, postgresql, php8.3-fpm). Il est detécté automatiquement
* lors de l'ajout du serveur ou ajouté manuellement par un admin.
*
* @package App\Entity
* @author Yasser
*/
namespace App\Entity;
use App\Repository\ServiceRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @class Service
* @brief Entité Doctrine pour un service systemd surveillé
*
* Represente une unité systemd (service) sur un serveur Linux.
* Le champ 'name' correspond au nom systemd (ex: 'nginx')
* et 'displayName' est le nom affiché dans l'interface.
*/
#[ORM\Entity(repositoryClass: ServiceRepository::class)]
#[ORM\Table(name: 'service')]
class Service
{
/**
* @var int|null Identifiant unique auto-incrementé du service
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'service_id')]
private ?int $id = null;
/**
* @var string|null Nom systemd du service (ex: 'nginx', 'postgresql')
* Ce nom est utilisé dans les commandes systemctl
*/
#[ORM\Column(name: 'name', length: 50)]
#[Assert\NotBlank]
private ?string $name = null;
/**
* @var string|null Nom affiché dans l'interface utilisateur
*/
#[ORM\Column(name: 'display_name', length: 100)]
#[Assert\NotBlank]
private ?string $displayName = null;
/**
* @var Server|null Le serveur auquel appartient ce service
*/
#[ORM\ManyToOne(targetEntity: Server::class, inversedBy: 'services')]
#[ORM\JoinColumn(name: 'server_id', referencedColumnName: 'server_id', nullable: false)]
private ?Server $server = null;
/**
* @brief Retourne l'id du service
* @return int|null
*/
public function getId(): ?int { return $this->id; }
/**
* @brief Retourne le nom systemd du service
* @return string|null Ex: 'nginx', 'php8.3-fpm'
*/
public function getName(): ?string { return $this->name; }
/**
* @param string $name Nom systemd du service
* @return static
*/
public function setName(string $name): static { $this->name = $name; return $this; }
/** @return string|null Nom d'affichage dans l'interface */
public function getDisplayName(): ?string { return $this->displayName; }
/** @param string $displayName @return static */
public function setDisplayName(string $displayName): static { $this->displayName = $displayName; return $this; }
/**
* @brief Retourne le serveur associé a ce service
* @return Server|null
*/
public function getServer(): ?Server { return $this->server; }
/** @param Server|null $server @return static */
public function setServer(?Server $server): static { $this->server = $server; return $this; }
}

226
src/Entity/User.php Normal file
View file

@ -0,0 +1,226 @@
<?php
/**
* @file User.php
* @brief Entité utilisateur pour le systeme d'authentification Symfony
*
* Represente un utilisateur de l'application ServerControl.
* Implémente UserInterface et PasswordAuthenticatedUserInterface
* pour s'intégrer avec le systeme de securité de Symfony.
*
* @package App\Entity
* @author Yasser
*/
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @class User
* @brief Entité Doctrine representant un utilisateur de l'application
*
* Gere les 3 niveaux de roles : ROLE_USER (compte en attente),
* ROLE_OPERATOR (acces aux serveurs assignés) et ROLE_ADMIN (acces total).
* Le champ email est unique et sert d'identifiant de connexion.
* Un utilisateur peut etre desactivé par un admin sans suppression.
*/
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: 'app_user')]
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
/**
* @var int|null Identifiant unique auto-incrementé de l'utilisateur
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'user_id')]
private ?int $id = null;
/**
* @var string|null Adresse email unique, utilisée comme identifiant de connexion
*/
#[ORM\Column(name: 'email', length: 180, unique: true)]
private ?string $email = null;
/**
* @var string|null Pseudo affiché dans l'interface (nom d'affichage)
*/
#[ORM\Column(name: 'pseudo', length: 50)]
private ?string $pseudo = null;
/**
* @var array Tableau des roles Symfony (ex: ['ROLE_ADMIN'])
* ROLE_USER est toujours ajouté automatiquement par getRoles()
*/
#[ORM\Column(name: 'roles', type: 'json')]
private array $roles = [];
/**
* @var string|null Mot de passe hashé par Symfony PasswordHasher
*/
#[ORM\Column(name: 'password', length: 255)]
private ?string $password = null;
/**
* @var bool Indique si le compte est actif, permet de bloquer un utilisateur
*/
#[ORM\Column(name: 'is_active')]
private bool $isActive = true;
/**
* @var \DateTimeImmutable|null Date d'inscription de l'utilisateur
*/
#[ORM\Column(name: 'created_at')]
private ?\DateTimeImmutable $createdAt = null;
/**
* @var string|null Token temporaire pour la reinitialisation de mot de passe
*/
#[ORM\Column(name: 'reset_token', length: 100, nullable: true)]
private ?string $resetToken = null;
/**
* @var \DateTimeImmutable|null Date d'expiration du token de reset, null si aucun token actif
*/
#[ORM\Column(name: 'reset_token_expires_at', nullable: true)]
private ?\DateTimeImmutable $resetTokenExpiresAt = null;
/**
* @var Collection Serveurs dont cet utilisateur est proprietaire
*/
#[ORM\OneToMany(targetEntity: Server::class, mappedBy: 'owner')]
private Collection $servers;
/**
* @var Collection Logs de toutes les actions effectué par cet utilisateur
*/
#[ORM\OneToMany(targetEntity: ActionLog::class, mappedBy: 'user')]
private Collection $actionLogs;
/**
* @var Collection Acces aux serveurs assignés a cet utilisateur par un admin
*/
#[ORM\OneToMany(targetEntity: ServerAccess::class, mappedBy: 'user', cascade: ['remove'])]
private Collection $serverAccesses;
/**
* @brief Constructeur - initialise les collections et la date de creation
*/
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
$this->servers = new ArrayCollection();
$this->actionLogs = new ArrayCollection();
$this->serverAccesses = new ArrayCollection();
}
/**
* @brief Retourne l'identifiant de l'utilisateur
* @return int|null L'id, null si pas encore persisté en base
*/
public function getId(): ?int { return $this->id; }
/** @return string|null Email de l'utilisateur */
public function getEmail(): ?string { return $this->email; }
/** @param string $email @return static */
public function setEmail(string $email): static { $this->email = $email; return $this; }
/** @return string|null Pseudo de l'utilisateur */
public function getPseudo(): ?string { return $this->pseudo; }
/** @param string $pseudo @return static */
public function setPseudo(string $pseudo): static { $this->pseudo = $pseudo; return $this; }
/**
* @brief Retourne l'identifiant de connexion (email) pour Symfony Security
* @return string L'email comme identifiant unique
*/
public function getUserIdentifier(): string { return (string) $this->email; }
/**
* @brief Retourne les roles de l'utilisateur
*
* ROLE_USER est toujours inclus automatiquement pour garantir
* que tout les utilisateurs aient au moin un role de base.
*
* @return array Tableau de roles uniques
*/
public function getRoles(): array
{
$roles = $this->roles;
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
/**
* @param array $roles Les roles a assigner (ex: ['ROLE_OPERATOR'])
* @return static
*/
public function setRoles(array $roles): static { $this->roles = $roles; return $this; }
/** @return string|null Mot de passe hashé */
public function getPassword(): ?string { return $this->password; }
/** @param string $password Le hash du mot de passe @return static */
public function setPassword(string $password): static { $this->password = $password; return $this; }
/**
* @brief Verifie si le compte est actif
* @return bool true si actif, false si désactivé par un admin
*/
public function isActive(): bool { return $this->isActive; }
/** @param bool $isActive @return static */
public function setIsActive(bool $isActive): static { $this->isActive = $isActive; return $this; }
/** @return \DateTimeImmutable|null Date d'inscription */
public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; }
/** @return string|null Token de reinitialisation de mot de passe */
public function getResetToken(): ?string { return $this->resetToken; }
/** @param string|null $resetToken null pour effacer le token @return static */
public function setResetToken(?string $resetToken): static { $this->resetToken = $resetToken; return $this; }
/** @return \DateTimeImmutable|null Date d'expiration du token */
public function getResetTokenExpiresAt(): ?\DateTimeImmutable { return $this->resetTokenExpiresAt; }
/**
* @param \DateTimeImmutable|null $resetTokenExpiresAt
* @return static
*/
public function setResetTokenExpiresAt(?\DateTimeImmutable $resetTokenExpiresAt): static
{
$this->resetTokenExpiresAt = $resetTokenExpiresAt;
return $this;
}
/**
* @brief Efface les données sensibles de l'utilisateur apres authentification
* Requis par l'interface UserInterface, on laisse vide car on utilise pas plainPassword
*/
public function eraseCredentials(): void {}
/** @return Collection Serveurs propriéte de cet utilisateur */
public function getServers(): Collection { return $this->servers; }
/** @return Collection Logs des actions de cet utilisateur */
public function getActionLogs(): Collection { return $this->actionLogs; }
/** @return Collection Accès aux serveurs assignés */
public function getServerAccesses(): Collection { return $this->serverAccesses; }
/**
* @brief Vérifie si l'utilisateur a le role admin
* @return bool true si ROLE_ADMIN est dans les roles
*/
public function isAdmin(): bool { return in_array('ROLE_ADMIN', $this->getRoles()); }
/**
* @brief Vérifie si l'utilisateur est au moins opérateur
* @return bool true si ROLE_OPERATOR ou ROLE_ADMIN
*/
public function isOperator(): bool { return $this->isAdmin() || in_array('ROLE_OPERATOR', $this->getRoles()); }
}