diff --git a/src/CoreBundle/Controller/ExceptionController.php b/src/CoreBundle/Controller/ExceptionController.php index ffed9abf73a..a159084a5cf 100644 --- a/src/CoreBundle/Controller/ExceptionController.php +++ b/src/CoreBundle/Controller/ExceptionController.php @@ -6,6 +6,7 @@ namespace Chamilo\CoreBundle\Controller; +use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper; use Exception; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\ErrorHandler\Exception\FlattenException; @@ -13,6 +14,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class ExceptionController extends AbstractController { @@ -91,4 +93,33 @@ public function error(Request $request): Response 'exception' => $exception, ]); } + + #[Route(path: '/error/undefined-url', name: 'undefined_url_error')] + public function undefinedUrlError( + Request $request, + UrlGeneratorInterface $urlGenerator, + AccessUrlHelper $accessUrlHelper + ): Response { + $host = $request->getHost(); + + $accessUrl = $accessUrlHelper->getFirstAccessUrl(); + $themeHost = rtrim($accessUrl?->getUrl() ?? '', '/'); + $themeName = 'chamilo'; + + $cssUrl = $themeHost . $urlGenerator->generate('theme_asset', [ + 'name' => $themeName, + 'path' => 'colors.css', + ], UrlGeneratorInterface::ABSOLUTE_PATH); + + $logoUrl = $themeHost . $urlGenerator->generate('theme_asset', [ + 'name' => $themeName, + 'path' => 'images/header-logo.svg', + ], UrlGeneratorInterface::ABSOLUTE_PATH); + + return $this->render('@ChamiloCore/Exception/undefined_url.html.twig', [ + 'host' => $host, + 'cssUrl' => $cssUrl, + 'logoUrl' => $logoUrl, + ]); + } } diff --git a/src/CoreBundle/EventListener/AccessUrlValidationListener.php b/src/CoreBundle/EventListener/AccessUrlValidationListener.php new file mode 100644 index 00000000000..d46305ed134 --- /dev/null +++ b/src/CoreBundle/EventListener/AccessUrlValidationListener.php @@ -0,0 +1,78 @@ +isMainRequest()) { + return; + } + + $request = $event->getRequest(); + $path = $request->getPathInfo(); + + // Prevent infinite redirection loop to the same error page + if (str_starts_with($path, '/error/undefined-url')) { + return; + } + + // Skip validation for static assets and special files + $excludedPrefixes = [ + '/build/', // Webpack build assets + '/theme/', // Legacy theme assets + '/favicon.ico', // Favicon + '/robots.txt', // Robots file + '/apple-touch-icon.png', // Mobile shortcut icon + ]; + + foreach ($excludedPrefixes as $prefix) { + if (str_starts_with($path, $prefix)) { + return; + } + } + + // Skip validation if multi-URL is not enabled + if (!$this->accessUrlHelper->isMultiple()) { + return; + } + + try { + // Try to get the current AccessUrl from the request + $accessUrl = $this->accessUrlHelper->getCurrent(); + + // If it's null, throw an exception to trigger redirection + if (null === $accessUrl) { + throw new \RuntimeException('AccessUrl not defined'); + } + } catch (\Throwable $e) { + // Log host and URI for debugging + $host = $request->getHost(); + $uri = $request->getUri(); + + // Redirect to custom error page + $url = $this->router->generate('undefined_url_error'); + $event->setResponse(new RedirectResponse($url)); + } + } +} diff --git a/src/CoreBundle/Resources/config/services.yml b/src/CoreBundle/Resources/config/services.yml index f8ee9905511..d463435289c 100644 --- a/src/CoreBundle/Resources/config/services.yml +++ b/src/CoreBundle/Resources/config/services.yml @@ -138,3 +138,7 @@ services: $parameterBag: '@parameter_bag' $pluginRepo: '@Chamilo\CoreBundle\Repository\AccessUrlRelPluginRepository' $accessUrlHelper: '@Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper' + + Chamilo\CoreBundle\EventListener\AccessUrlValidationListener: + tags: + - { name: kernel.event_listener, event: kernel.request, priority: 255 } diff --git a/src/CoreBundle/Resources/views/Exception/undefined_url.html.twig b/src/CoreBundle/Resources/views/Exception/undefined_url.html.twig new file mode 100644 index 00000000000..7a8d91c35ea --- /dev/null +++ b/src/CoreBundle/Resources/views/Exception/undefined_url.html.twig @@ -0,0 +1,42 @@ +{% extends '@ChamiloCore/Layout/layout_one_col.html.twig' %} + +{% block chamilo_head %} + {{ parent() }} + +{% endblock %} + +{% block content %} +
+ {% if logoUrl %} + Chamilo Logo + {% endif %} + +
+

+ {{ 'Oops! URL not registered.'|trans }} +

+ +

+ {{ 'The address "%host%" is not configured in this Chamilo instance.'|trans({'%host%': host}) }} +

+ +

+ {{ 'If the problem persists, please contact support.'|trans }} +

+ + + {{ 'Go to home page'|trans }} + +
+
+{% endblock %} diff --git a/src/CoreBundle/ServiceHelper/AuthenticationConfigHelper.php b/src/CoreBundle/ServiceHelper/AuthenticationConfigHelper.php index a126499dcc5..137227d11e5 100644 --- a/src/CoreBundle/ServiceHelper/AuthenticationConfigHelper.php +++ b/src/CoreBundle/ServiceHelper/AuthenticationConfigHelper.php @@ -65,14 +65,14 @@ public function getEnabledOAuthProviders(?AccessUrl $url = null): array public function getAuthSources(?AccessUrl $url) { - $urlId = $url ?: $this->urlHelper->getCurrent(); + $accessUrl = $url ?: $this->urlHelper->getCurrent(); $authentication = $this->parameterBag->has('authentication') ? $this->parameterBag->get('authentication') : []; - if (isset($authentication[$urlId->getId()])) { - return $authentication[$urlId->getId()]; + if ($accessUrl instanceof AccessUrl && isset($authentication[$accessUrl->getId()])) { + return $authentication[$accessUrl->getId()]; } if (isset($authentication['default'])) { diff --git a/src/CoreBundle/ServiceHelper/ThemeHelper.php b/src/CoreBundle/ServiceHelper/ThemeHelper.php index dbb9f03f01e..6296b6b2f8b 100644 --- a/src/CoreBundle/ServiceHelper/ThemeHelper.php +++ b/src/CoreBundle/ServiceHelper/ThemeHelper.php @@ -6,6 +6,7 @@ namespace Chamilo\CoreBundle\ServiceHelper; +use Chamilo\CoreBundle\Entity\AccessUrl; use Chamilo\CoreBundle\Settings\SettingsManager; use Chamilo\CourseBundle\Settings\SettingsCourseManager; use League\Flysystem\FilesystemException; @@ -46,9 +47,12 @@ public function getVisualTheme(): string return $visualTheme; } + $visualTheme = null; $accessUrl = $this->accessUrlHelper->getCurrent(); - $visualTheme = $accessUrl->getActiveColorTheme()?->getColorTheme()->getSlug(); + if ($accessUrl instanceof AccessUrl) { + $visualTheme = $accessUrl->getActiveColorTheme()?->getColorTheme()->getSlug(); + } if ('true' == $this->settingsManager->getSetting('profile.user_selected_theme')) { $visualTheme = $this->userHelper->getCurrent()?->getTheme();