Squelette Symfony, entités Server et Action
This commit is contained in:
commit
52ecb4204c
46 changed files with 4308 additions and 0 deletions
0
src/Entity/.gitignore
vendored
Normal file
0
src/Entity/.gitignore
vendored
Normal file
131
src/Entity/ActionLog.php
Normal file
131
src/Entity/ActionLog.php
Normal 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
230
src/Entity/Server.php
Normal 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; }
|
||||
}
|
||||
98
src/Entity/ServerAccess.php
Normal file
98
src/Entity/ServerAccess.php
Normal 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
93
src/Entity/Service.php
Normal 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
226
src/Entity/User.php
Normal 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()); }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue