handles session timeouts in modals (#1092)

This commit is contained in:
Kevin Papst
2019-09-10 17:07:34 +02:00
committed by GitHub
parent a651e55dc9
commit cdcf9eaf67
12 changed files with 86 additions and 14 deletions

View File

@@ -57,12 +57,9 @@ export default class KimaiAjaxModalForm extends KimaiClickHandlerReducedInTableR
if (errorHandler === undefined) { if (errorHandler === undefined) {
errorHandler = function(xhr, err) { errorHandler = function(xhr, err) {
if (xhr.status !== undefined && xhr.status === 403) { if (xhr.status === undefined || xhr.status !== 403) {
const alert = self.getContainer().getPlugin('alert'); window.location = url;
alert.error(xhr.statusText);
return;
} }
window.location = url;
}; };
} }

View File

@@ -15,8 +15,8 @@ import KimaiPlugin from '../KimaiPlugin';
export default class KimaiThemeInitializer extends KimaiPlugin { export default class KimaiThemeInitializer extends KimaiPlugin {
init() { init() {
this.registerGlobalAjaxErrorHandler();
this.registerAutomaticAlertRemove('div.alert-success', 5000); this.registerAutomaticAlertRemove('div.alert-success', 5000);
// activate the dropdown functionality // activate the dropdown functionality
jQuery('.dropdown-toggle').dropdown(); jQuery('.dropdown-toggle').dropdown();
// activate the tooltip functionality // activate the tooltip functionality
@@ -25,6 +25,27 @@ export default class KimaiThemeInitializer extends KimaiPlugin {
this.getContainer().getPlugin('form').activateForm('.content-wrapper form', 'body'); this.getContainer().getPlugin('form').activateForm('.content-wrapper form', 'body');
} }
/**
* redirect access denied / session timeouts to login page
*/
registerGlobalAjaxErrorHandler() {
const loginUrl = this.getContainer().getConfiguration().get('login');
const alert = this.getContainer().getPlugin('alert');
const translation = this.getContainer().getTranslation().get('login.required');
jQuery(document).ajaxError(function(event, jqxhr, settings, thrownError) {
if (jqxhr.status !== undefined && jqxhr.status === 403) {
const loginRequired = jqxhr.getResponseHeader('login-required');
if (loginRequired !== null) {
alert.question(translation, function (result) {
if (result === true) {
window.location.replace(loginUrl);
}
});
}
}
});
}
/** /**
* auto hide success messages, as they are just meant as user feedback and not as a permanent information * auto hide success messages, as they are just meant as user feedback and not as a permanent information
* *

View File

@@ -37,7 +37,7 @@ nelmio_api_doc:
info: info:
title: Kimai 2 - API Docs title: Kimai 2 - API Docs
description: | description: |
REST API for the Kimai 2 time-tracking software. Read more about its usage in the [API documentation](https://www.kimai.org/documentation/rest-api.html) and then download a [Swagger file](doc.json) for import e.g. in Postman. JSON API for the Kimai 2 time-tracking software. Read more about its usage in the [API documentation](https://www.kimai.org/documentation/rest-api.html) and then download a [Swagger file](doc.json) for import e.g. in Postman.
Be aware: it is not yet considered stable and BC breaks might happen, but we try to avoid them. Be aware: it is not yet considered stable and BC breaks might happen, but we try to avoid them.
version: 0.3 version: 0.3
securityDefinitions: securityDefinitions:

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
"build/runtime.f02eb7c9.js", "build/runtime.f02eb7c9.js",
"build/0.2372f97a.js", "build/0.2372f97a.js",
"build/1.eec3372c.js", "build/1.eec3372c.js",
"build/app.608dd464.js" "build/app.21c06505.js"
], ],
"css": [ "css": [
"build/app.af6cd671.css" "build/app.af6cd671.css"
@@ -35,7 +35,7 @@
"build/runtime.f02eb7c9.js": "sha384-xNNrNinl64G3nCUrIskgSjU0mUXXCB9lj6XCSInBTwxSKXk8uTMafnLHtdWdIGtd", "build/runtime.f02eb7c9.js": "sha384-xNNrNinl64G3nCUrIskgSjU0mUXXCB9lj6XCSInBTwxSKXk8uTMafnLHtdWdIGtd",
"build/0.2372f97a.js": "sha384-+My37x5S4cen1I4LYgCVg4Qaa+y8vmPzhpDNLPEoEuH5uBtdwYx6ACOxm23nW0UP", "build/0.2372f97a.js": "sha384-+My37x5S4cen1I4LYgCVg4Qaa+y8vmPzhpDNLPEoEuH5uBtdwYx6ACOxm23nW0UP",
"build/1.eec3372c.js": "sha384-7UVWcP6Hefp2k/CrtGSITKXx4dSZqtvpAiU8WX7dClETkzMewrUjoCRtVXQ5j3KI", "build/1.eec3372c.js": "sha384-7UVWcP6Hefp2k/CrtGSITKXx4dSZqtvpAiU8WX7dClETkzMewrUjoCRtVXQ5j3KI",
"build/app.608dd464.js": "sha384-dnyOfN3SyZEO87bNKmrrsicXn1usVTQcqmw1pe7cLtr+zO50b09tsIPsUkfAqJJv", "build/app.21c06505.js": "sha384-e7hmqWhNBpDXkCu8f0ASmtcnqxenbVJ+XqAYlh0+m8MZGM8FHUwHYmbWep38WKrf",
"build/app.af6cd671.css": "sha384-N8TrohuaS6twRAMAhyy+5o3qV69cT6KGgsvKiLmHMCmRIV3zssFoM14+pO92w+JL", "build/app.af6cd671.css": "sha384-N8TrohuaS6twRAMAhyy+5o3qV69cT6KGgsvKiLmHMCmRIV3zssFoM14+pO92w+JL",
"build/2.ad3e2792.js": "sha384-1aYWOOt09EZyaAlTHQzsuBKU1b+iDuMEen4m8lrRIm7awHvYkP82CWAowcKZ+XuW", "build/2.ad3e2792.js": "sha384-1aYWOOt09EZyaAlTHQzsuBKU1b+iDuMEen4m8lrRIm7awHvYkP82CWAowcKZ+XuW",
"build/chart.a0ca6955.js": "sha384-I57c9DtU3AOG2kzKqIZkIu0hi1aGYHRZ5QG4LKC9+9slzJnAMttPGXoL2cQG3m6y", "build/chart.a0ca6955.js": "sha384-I57c9DtU3AOG2kzKqIZkIu0hi1aGYHRZ5QG4LKC9+9slzJnAMttPGXoL2cQG3m6y",

View File

@@ -3,7 +3,7 @@
"build/1.eec3372c.js": "build/1.eec3372c.js", "build/1.eec3372c.js": "build/1.eec3372c.js",
"build/2.ad3e2792.js": "build/2.ad3e2792.js", "build/2.ad3e2792.js": "build/2.ad3e2792.js",
"build/app.css": "build/app.af6cd671.css", "build/app.css": "build/app.af6cd671.css",
"build/app.js": "build/app.608dd464.js", "build/app.js": "build/app.21c06505.js",
"build/calendar.css": "build/calendar.8bb56227.css", "build/calendar.css": "build/calendar.8bb56227.css",
"build/calendar.js": "build/calendar.340fd7f1.js", "build/calendar.js": "build/calendar.340fd7f1.js",
"build/chart.js": "build/chart.a0ca6955.js", "build/chart.js": "build/chart.a0ca6955.js",

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException;
class AjaxAuthenticationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
KernelEvents::EXCEPTION => ['onCoreException', 1]
];
}
public function onCoreException(ExceptionEvent $event)
{
$request = $event->getRequest();
if ($request->isXmlHttpRequest()) {
$exception = $event->getException();
if ($exception instanceof AuthenticationExpiredException) {
$event->setResponse(new Response('Session expired', 403, ['Login-Required' => true]));
} elseif ($exception instanceof AuthenticationException) {
$event->setResponse(new Response('Authentication problem', 403, ['Login-Required' => true]));
} elseif ($exception instanceof AccessDeniedException) {
$event->setResponse(new Response('Access denied', 403, ['Login-Required' => true]));
}
}
}
}

View File

@@ -25,7 +25,7 @@ class TimesheetToolbarForm extends AbstractToolbarForm
{ {
$this->addSearchTermInputField($builder); $this->addSearchTermInputField($builder);
if ($options['include_user']) { if ($options['include_user']) {
$this->addUserChoice($builder); $this->addUsersChoice($builder);
} }
$this->addDateRangeChoice($builder); $this->addDateRangeChoice($builder);
$this->addCustomerChoice($builder); $this->addCustomerChoice($builder);

View File

@@ -201,6 +201,7 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
var loader = new KimaiWebLoader( var loader = new KimaiWebLoader(
{ {
login: '{{ path('fos_user_security_login') }}',
locale: '{{ app.request.locale }}', locale: '{{ app.request.locale }}',
twentyFourHours: {{ 'true'|hour24('false') }}, twentyFourHours: {{ 'true'|hour24('false') }},
autoReloadDatatable: {% if theme_config('auto_reload_datatable') %}true{% else %}false{% endif %}, autoReloadDatatable: {% if theme_config('auto_reload_datatable') %}true{% else %}false{% endif %},
@@ -228,7 +229,8 @@
'action.delete.success': '{{ 'action.delete.success'|trans({}, 'flashmessages') }}', 'action.delete.success': '{{ 'action.delete.success'|trans({}, 'flashmessages') }}',
'action.delete.error': '{{ 'action.delete.error'|trans({}, 'flashmessages') }}', 'action.delete.error': '{{ 'action.delete.error'|trans({}, 'flashmessages') }}',
'confirm.delete': '{{ 'confirm.delete' |trans }}', 'confirm.delete': '{{ 'confirm.delete' |trans }}',
'delete': '{{ 'action.delete' |trans }}' 'delete': '{{ 'action.delete' |trans }}',
'login.required': '{{ 'login_required'|trans }}'
} }
); );
window.kimai = loader.getKimai(); window.kimai = loader.getKimai();

View File

@@ -67,7 +67,7 @@ class TimesheetTeamControllerTest extends ControllerBaseTest
$form = $client->getCrawler()->filter('form.header-search')->form(); $form = $client->getCrawler()->filter('form.header-search')->form();
$client->submit($form, [ $client->submit($form, [
'state' => 1, 'state' => 1,
'user' => $user->getId(), 'users' => [$user->getId()],
'pageSize' => 25, 'pageSize' => 25,
'daterange' => $dateRange, 'daterange' => $dateRange,
'customer' => null, 'customer' => null,

View File

@@ -84,6 +84,10 @@
<source>label.api_token_repeat</source> <source>label.api_token_repeat</source>
<target>API Passwort wiederholen</target> <target>API Passwort wiederholen</target>
</trans-unit> </trans-unit>
<trans-unit id="login_required">
<source>login_required</source>
<target>Fehlende Berechtigung. Zur Anmeldung wechseln?</target>
</trans-unit>
<!-- <!--
Menu / Navbar items Menu / Navbar items

View File

@@ -84,6 +84,10 @@
<source>label.api_token_repeat</source> <source>label.api_token_repeat</source>
<target>Repeat API password</target> <target>Repeat API password</target>
</trans-unit> </trans-unit>
<trans-unit id="login_required">
<source>login_required</source>
<target>Missing permission. Redirect to login?</target>
</trans-unit>
<!-- <!--
Menu / Navbar items Menu / Navbar items