feat: maintenance mode

This commit is contained in:
2026-09-08 12:35:50 +02:00
parent f12561c62b
commit 45ca0d2b46
4 changed files with 125 additions and 0 deletions
@@ -0,0 +1,86 @@
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\IpUtils;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Twig\Environment;
#[AsEventListener(event: KernelEvents::REQUEST, method: 'onKernelRequest')]
class MaintenanceModeListener
{
/**
* @var array<string, mixed>
*/
private array $config;
/**
* @param array<string, mixed> $options
*/
public function __construct(private readonly Environment $twig, array $options)
{
$this->config = $this->resolveConfig($options);
}
public function onKernelRequest(RequestEvent $event): void
{
if (false === $event->isMainRequest()) {
return;
}
if (false === $this->config['enabled']) {
return;
}
$request = $event->getRequest();
// Check requested path against whitelist
foreach ($this->config['whitelisted_paths'] as $whitelistedPath) {
$prefix = rtrim((string) $whitelistedPath, '/');
if ($request->getPathInfo() === $prefix || str_starts_with($request->getPathInfo(), $prefix.'/')) {
return;
}
}
// Check user's IP against whitelist
if (true === IpUtils::checkIp($request->getClientIp(), $this->config['whitelisted_ips'])) {
$request->attributes->set('_maintenance_mode_allowed', true);
return;
}
// Check requested route against whitelist
if (true === in_array($request->attributes->get('_route'), $this->config['whitelisted_routes'])) {
return;
}
$content = $this->twig->render('maintenance/index.html.twig');
$event->setResponse(new Response($content, Response::HTTP_SERVICE_UNAVAILABLE));
}
/**
* @param array<string, mixed> $options
*
* @return array<string, mixed>
*/
private function resolveConfig(array $options): array
{
$optionsResolver = new OptionsResolver();
$optionsResolver
->setDefaults([
'enabled' => false,
'whitelisted_ips' => [],
'whitelisted_routes' => [],
'whitelisted_paths' => [],
])
;
return $optionsResolver->resolve($options);
}
}