Internal: Add session expiry redirect and custom exception handling

pull/5258/head
christianbeeznst 2 years ago
parent 9ca9904c3e
commit cc86c0061f
  1. 19
      assets/vue/components/Login.vue
  2. 5
      assets/vue/components/layout/TopbarNotLoggedIn.vue
  3. 3
      public/main/inc/lib/api.lib.php
  4. 17
      src/CoreBundle/Component/Utils/ChamiloApi.php
  5. 37
      src/CoreBundle/EventListener/ExceptionListener.php
  6. 16
      src/CoreBundle/Exception/NotAllowedException.php
  7. 12
      src/CoreBundle/Resources/views/Exception/error.html.twig

@ -115,7 +115,12 @@ async function performLogin() {
if (!store.getters["security/hasError"]) {
securityStore.user = store.state["security/user"]
if (typeof redirect !== "undefined") {
// Check if 'redirect' is an absolute URL
if (typeof redirect !== "undefined" && isValidHttpUrl(redirect.toString())) {
// If it's an absolute URL, redirect directly
window.location.href = redirect.toString()
} else if (typeof redirect !== "undefined") {
// If 'redirect' is a relative path, use 'router.push' to navigate
await router.push({ path: redirect.toString() })
} else {
if (responseData.load_terms) {
@ -126,4 +131,16 @@ async function performLogin() {
}
}
}
function isValidHttpUrl(string) {
let url
try {
url = new URL(string)
} catch (_) {
return false
}
return url.protocol === "http:" || url.protocol === "https:"
}
</script>

@ -37,13 +37,14 @@ function setLanguage(event) {
window.location.href = newUrl.fullPath
}
const languageItems = window.languages.map((language) => ({
const languages = window.languages || [{ originalName: "English", isocode: "en" }]
const languageItems = languages.map((language) => ({
label: language.originalName,
isoCode: language.isocode,
command: setLanguage,
}))
const currentLanguage = window.languages.find((language) => document.querySelector("html").lang === language.isocode)
const currentLanguage = languages.find((language) => document.querySelector("html").lang === language.isocode)
const menuItems = computed(() => [
{

@ -9,6 +9,7 @@ use Chamilo\CoreBundle\Entity\Session as SessionEntity;
use Chamilo\CoreBundle\Entity\SettingsCurrent;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Entity\UserCourseCategory;
use Chamilo\CoreBundle\Exception\NotAllowedException;
use Chamilo\CoreBundle\Framework\Container;
use Chamilo\CourseBundle\Entity\CGroup;
use Chamilo\CourseBundle\Entity\CLp;
@ -3516,7 +3517,7 @@ function api_not_allowed(
$message = null,
$responseCode = 0
): never {
throw new Exception('You are not allowed');
throw new NotAllowedException($message ?: 'You are not allowed', $responseCode);
}
/**

@ -428,4 +428,21 @@ class ChamiloApi
instance.buildmarkersrolls(instance, instance.controls, instance.layers, instance.media);
";
}
/**
* Performs a redirection to the specified URL.
*
* This method sends a direct HTTP Location header to the client,
* causing the browser to navigate to the specified URL. It should be
* used with caution and only in scenarios where Symfony's standard
* response handling is not applicable. The method terminates script
* execution after sending the header.
*/
public static function redirectTo(string $url): void
{
if (!empty($url)) {
header("Location: $url");
exit;
}
}
}

@ -6,34 +6,53 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\EventListener;
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use Chamilo\CoreBundle\Exception\NotAllowedException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Twig\Environment;
class ExceptionListener
{
protected Environment $twig;
protected TokenStorageInterface $tokenStorage;
protected UrlGeneratorInterface $router;
public function __construct(Environment $twig)
public function __construct(Environment $twig, TokenStorageInterface $tokenStorage, UrlGeneratorInterface $router)
{
$this->twig = $twig;
$this->tokenStorage = $tokenStorage;
$this->router = $router;
}
public function onKernelException(ExceptionEvent $event): void
{
// You get the exception object from the received event
$exception = $event->getThrowable();
$request = $event->getRequest();
if ($exception instanceof AccessDeniedException || $exception instanceof NotAllowedException) {
if (null === $this->tokenStorage->getToken()) {
$currentUrl = $request->getUri();
$parsedUrl = parse_url($currentUrl);
$baseUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'];
$path = rtrim($parsedUrl['path'], '/') ?: '';
$query = $parsedUrl['query'] ?? '';
$redirectUrl = $baseUrl . $path . ($query ? '?' . $query : '');
$loginUrl = $this->router->generate('login', ['redirect' => $redirectUrl], UrlGeneratorInterface::ABSOLUTE_URL);
ChamiloApi::redirectTo($loginUrl);
}
}
if (isset($_SERVER['APP_ENV']) && \in_array($_SERVER['APP_ENV'], ['dev', 'test'], true)) {
return;
}
// You get the exception object from the received event
$exception = $event->getThrowable();
/*$message = sprintf(
'My Error says: %s with code: %s',
$exception->getMessage(),
$exception->getCode()
);*/
$message = $this->twig->render(
'@ChamiloCore/Exception/error.html.twig',
[

@ -0,0 +1,16 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Exception;
use Exception;
class NotAllowedException extends Exception
{
public function __construct($message = 'Not allowed', $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

@ -1,15 +1,17 @@
{% extends '@ChamiloCore/Layout/base-layout.html.twig' %}
{% block page_content %}
<div
id="app"
>
</div>
<section id="sectionMainContent" class="section-content">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4">Error</h1>
<p class="lead"> {{ exception.message }}</p>
</div>
<div class="alert alert-danger" style="width: 60%; padding: 20px; margin: 10% auto; text-align: center;">
<h4 class="alert-heading">{{ 'Oops! Something went wrong.'|trans }}</h4>
<hr />
<p>{{ exception.message }}</p>
<hr>
<p class="mb-0">{{ 'If the problem persists, please contact support.'|trans }}</p>
</div>
</section>
{% endblock %}

Loading…
Cancel
Save