Files
KantSites/src/EventSubscriber/MaintenanceSubscriber.php
T
kantarciandClaude Opus 5 3b1dfc0948 Set the site address in the administration, checked against the installation itself
- System > This installation > Address has a field and a link to the other
  spelling (with or without www), like the WordPress address. It writes
  SITE_ORIGIN to .env through Environment::write and takes effect on the
  next request. With SITE_ORIGIN from the server environment there is no
  field, and a POST is refused.
- Before saving, OriginCheck requests /.well-known/kantsites-origin under the
  new address; it has to return an HMAC of APP_SECRET that only this
  installation knows. Switching to www without DNS or certificate would
  otherwise send every page, the administration included, nowhere. "Save
  anyway" appears only after a refusal. The probe also answers during
  maintenance.
- The message says when the administration changes host and needs a new
  sign-in, since the session cookie belongs to one spelling.

Tests: 584 PHPUnit on PHP 8.2 and 8.4, 35 node, test:editor and
test:browser green (test:browser reports only the known editor colour
contrast on /grundlagen).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 08:36:38 +02:00

55 lines
2.1 KiB
PHP

<?php
namespace App\EventSubscriber;
use App\Ops\Updater;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;
/**
* While an update runs, the website answers with 503 and the administration stays open.
*
* 503 and not 200 with a notice: a search engine reads 503 with Retry-After as "come back later"
* and keeps the page in its index, while a 200 would teach it that the page now contains an
* excuse. The administration has to stay reachable, because otherwise nobody could finish or
* undo the update.
*/
final class MaintenanceSubscriber implements EventSubscriberInterface
{
public function __construct(private Environment $twig, private string $projectDir, private string $adminPath)
{
}
public static function getSubscribedEvents(): array
{
// Before the router: during maintenance no controller should run at all.
return [KernelEvents::REQUEST => ['onRequest', 40]];
}
public function onRequest(RequestEvent $event): void
{
if (!$event->isMainRequest() || !is_file($this->projectDir.'/'.Updater::MAINTENANCE_FILE)) {
return;
}
$path = $event->getRequest()->getPathInfo();
if (preg_match('#^/('.preg_quote($this->adminPath, '#').'|assets/|media/|favicon|\.well-known/kantsites-origin)#', $path)) {
return;
}
$since = @file_get_contents($this->projectDir.'/'.Updater::MAINTENANCE_FILE);
$response = new Response(
$this->twig->render('maintenance.html.twig', ['since' => trim((string) $since)]),
Response::HTTP_SERVICE_UNAVAILABLE,
[
'Retry-After' => '600',
'Cache-Control' => 'no-store',
'Content-Type' => 'text/html; charset=UTF-8',
'Content-Security-Policy' => "default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'",
],
);
$event->setResponse($response);
}
}