diff --git a/assets/scss/modules/base/_status.scss b/assets/scss/modules/base/_status.scss index 21b95a1b9..55992ec12 100644 --- a/assets/scss/modules/base/_status.scss +++ b/assets/scss/modules/base/_status.scss @@ -46,6 +46,7 @@ .badge-homepage, .badge-404, +.badge-403, .badge-maintenance { font-weight: normal; vertical-align: middle; @@ -57,7 +58,8 @@ background: $secondary; } -.badge-404 { +.badge-404, +.badge-403 { background: $warning; } diff --git a/config/bolt/config.yaml b/config/bolt/config.yaml index 0823483d1..ab2639b0e 100644 --- a/config/bolt/config.yaml +++ b/config/bolt/config.yaml @@ -68,6 +68,10 @@ homepage_template: index.twig # identifiers for records, which will be tried until a match is found. notfound: [ blocks/404-not-found, 'helpers/page_404.html.twig' ] +# The default content for the 403 page. Can be an (array of) template names or +# identifiers for records, which will be tried until a match is found. +forbidden: [ blocks/403-forbidden, 'helpers/page_403.html.twig' ] + # The default template and amount of records to use for listing-pages on the # site. # diff --git a/src/Controller/ErrorController.php b/src/Controller/ErrorController.php index 0ea5702c2..d89ad9bc0 100644 --- a/src/Controller/ErrorController.php +++ b/src/Controller/ErrorController.php @@ -48,21 +48,20 @@ public function showAction(Environment $twig, \Throwable $exception): Response $code = Response::HTTP_INTERNAL_SERVER_ERROR; } - if ($code === Response::HTTP_NOT_FOUND) { + $twig->addGlobal('exception', $exception); + + if ($code === Response::HTTP_SERVICE_UNAVAILABLE || $this->isMaintenanceEnabled($code)) { $twig->addGlobal('exception', $exception); - // If Maintenance is on, show that, instead of the 404. - if ($this->isMaintenanceEnabled()) { - return $this->showMaintenance(); - } + return $this->showMaintenance(); + } + if ($code === Response::HTTP_NOT_FOUND) { return $this->showNotFound(); } - if ($code === Response::HTTP_SERVICE_UNAVAILABLE) { - $twig->addGlobal('exception', $exception); - - return $this->showMaintenance(); + if ($code === Response::HTTP_FORBIDDEN) { + return $this->showForbidden(); } // If not a 404, we'll let Symfony handle it as usual. @@ -82,9 +81,17 @@ private function showNotFound(): Response return new Response('404: Not found (and there was no proper page configured to display)'); } - private function isMaintenanceEnabled() + private function showForbidden(): Response { - return $this->config->get('general/maintenance_mode', false); + foreach ($this->config->get('general/forbidden') as $item) { + $output = $this->attemptToRender($item); + + if ($output instanceof Response) { + return $output; + } + } + + return new Response('403: Forbidden (and there was no proper page configured to display)'); } private function showMaintenance(): Response @@ -100,6 +107,16 @@ private function showMaintenance(): Response return new Response('503: Maintenance mode (and there was no proper page configured to display)'); } + private function isMaintenanceEnabled(int $code): bool + { + // Only applies to NOT_FOUND and FORBIDDEN in frontend + if (! in_array($code, [Response::HTTP_NOT_FOUND, Response::HTTP_FORBIDDEN], true)) { + return false; + } + + return $this->config->get('general/maintenance_mode', false); + } + private function attemptToRender(string $item): ?Response { // First, see if it's a contenttype/slug pair: diff --git a/src/DataFixtures/ContentFixtures.php b/src/DataFixtures/ContentFixtures.php index f3c1b7caf..7e2246588 100644 --- a/src/DataFixtures/ContentFixtures.php +++ b/src/DataFixtures/ContentFixtures.php @@ -338,6 +338,11 @@ private function getPresetRecords(): array 'slug' => '404-not-found', 'status' => Statuses::HELD, ]; + $records['blocks'][] = [ + 'title' => '403 Forbidden', + 'slug' => '403-forbidden', + 'status' => Statuses::HELD, + ]; $records['blocks'][] = [ 'title' => '503 Service Unavailable (Maintenance Mode)', 'slug' => '503-maintenance mode', diff --git a/src/Twig/ContentExtension.php b/src/Twig/ContentExtension.php index bd2d8b1b6..0d55b5642 100644 --- a/src/Twig/ContentExtension.php +++ b/src/Twig/ContentExtension.php @@ -681,6 +681,10 @@ public function getSpecialFeature(Content $record): string return '404'; } + if ($this->is403($record)) { + return '403'; + } + if ($this->isMaintenance($record)) { return 'maintenance'; } @@ -698,6 +702,11 @@ public function is404(Content $content): bool return $this->contentHelper->is404($content); } + public function is403(Content $content): bool + { + return $this->contentHelper->is403($content); + } + public function isMaintenance(Content $content): bool { return $this->contentHelper->isMaintenance($content); diff --git a/src/Utils/ContentHelper.php b/src/Utils/ContentHelper.php index f09695a3e..4cb639c49 100644 --- a/src/Utils/ContentHelper.php +++ b/src/Utils/ContentHelper.php @@ -96,6 +96,11 @@ public function is404(Content $content): bool return $this->isSpecialpage($content, 'notfound'); } + public function is403(Content $content): bool + { + return $this->isSpecialpage($content, 'forbidden'); + } + public function isMaintenance(Content $content): bool { return $this->isSpecialpage($content, 'maintenance');