feat(Security/IntranetLocked): Ajoute le contrôle de l'état des services et le cache.
```
This commit is contained in:
Serreau Jovann
2026-01-31 14:05:37 +01:00
parent 486e3116c9
commit 970a47bcc4

View File

@@ -7,6 +7,8 @@ use App\Service\Signature\Client;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Twig\Environment;
#[AsEventListener(RequestEvent::class, method: 'onLocked', priority: 10)]
@@ -24,17 +26,17 @@ class IntranetLocked
private readonly Client $signatureClient,
private readonly \App\Service\Search\Client $searchClient,
private readonly \App\Service\Stripe\Client $stripeClient,
private readonly Mailer $mailer
private readonly Mailer $mailer,
private readonly CacheInterface $cache // Injection du cache
) {}
public function onLocked(RequestEvent $requestEvent): void
{
// Si l'IP est autorisée ou si c'est une route de debug, on ne bloque pas
if ($this->isWhitelisted($requestEvent) || $this->isDebugRoute($requestEvent)) {
return;
}
if ($_ENV['INTRANET_LOCK'] == 'true') {
if (($_ENV['INTRANET_LOCK'] ?? 'false') === 'true') {
$response = new Response($this->environment->render('security/locked.twig'));
$response->setStatusCode(Response::HTTP_FORBIDDEN);
$requestEvent->setResponse($response);
@@ -43,49 +45,55 @@ class IntranetLocked
public function onControl(RequestEvent $requestEvent): void
{
// On ignore également le contrôle des services pour l'IP whitelisted
if ($this->isWhitelisted($requestEvent) || $this->isDebugRoute($requestEvent)) {
return;
}
$isValid = true;
$message = [];
// On récupère le statut depuis le cache (Clé : intranet_status)
$status = $this->cache->get('intranet_services_status', function (ItemInterface $item) {
$item->expiresAfter(86400); // Durée de 1 jour (24h * 3600s)
// Check Signature
if (!$this->signatureClient->status()) {
$isValid = false;
$message = ['service' => 'Signature', 'status' => 'Hors Service'];
$this->advertTech($message);
}
$check = ['isValid' => true, 'message' => []];
// Check Recherche (seulement si le précédent est encore valide ou pour accumuler les erreurs)
if ($isValid && !$this->searchClient->status()) {
$isValid = false;
$message = ['service' => 'Recherche', 'status' => 'Hors Service'];
$this->advertTech($message);
}
// Check Signature
if (!$this->signatureClient->status()) {
$check = [
'isValid' => false,
'message' => ['service' => 'Signature', 'status' => 'Hors Service']
];
}
// Check Recherche
elseif (!$this->searchClient->status()) {
$check = [
'isValid' => false,
'message' => ['service' => 'Recherche', 'status' => 'Hors Service']
];
}
// Check Stripe
elseif (!$this->stripeClient->status()) {
$check = [
'isValid' => false,
'message' => ['service' => 'Stripe', 'status' => 'Hors Service']
];
}
// Check Stripe
if ($isValid && !$this->stripeClient->status()) {
$isValid = false;
$message = ['service' => 'Stripe', 'status' => 'Hors Service'];
$this->advertTech($message);
}
// Si un service est HS, on envoie le mail une seule fois (lors de la mise en cache)
if (!$check['isValid']) {
$this->advertTech($check['message']);
}
if (!$isValid) {
return $check;
});
if (!$status['isValid']) {
$response = new Response($this->environment->render('security/error.twig', [
'message' => $message,
'message' => $status['message'],
]));
$response->setStatusCode(Response::HTTP_FORBIDDEN);
$requestEvent->setResponse($response);
}
}
/**
* Vérifie si l'IP du client est l'IP de maintenance
*/
private function isWhitelisted(RequestEvent $event): bool
{
$request = $event->getRequest();