handles session timeouts in modals (#1092)
This commit is contained in:
@@ -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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
44
src/EventSubscriber/AjaxAuthenticationSubscriber.php
Normal file
44
src/EventSubscriber/AjaxAuthenticationSubscriber.php
Normal 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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user