Authentication: User session: Add expiration notification system - refs #4776

pull/5867/head
juancp-contidosdixitais 2 years ago committed by Yannick Warnier
parent 0f96eac0a4
commit 14e699f23c
  1. 75
      main/inc/ajax/session_clock.ajax.php
  2. 3
      main/install/configuration.dist.php
  3. 4
      main/lang/english/trad4all.inc.php
  4. 4
      main/lang/french/trad4all.inc.php
  5. 4
      main/lang/spanish/trad4all.inc.php
  6. 197
      main/template/default/layout/main.js.tpl

@ -0,0 +1,75 @@
<?php
require_once __DIR__.'/../../../vendor/autoload.php';
require_once __DIR__.'/../../../app/AppKernel.php';
$kernel = new AppKernel('', '');
// Check for 'action' parameter in the GET request
if (isset($_GET['action'])) {
$action = $_GET['action'];
if ($action == 'time') {
// Load the Chamilo configuration
$alreadyInstalled = false;
if (file_exists($kernel->getConfigurationFile())) {
require_once $kernel->getConfigurationFile();
$alreadyInstalled = true;
}
// Load the API library BEFORE loading the Chamilo configuration
require_once $_configuration['root_sys'].'main/inc/lib/api.lib.php';
if (api_get_configuration_value('session_lifetime_controller')) {
// Get the session
session_name('ch_sid');
session_start();
$session = new ChamiloSession();
$endTime = 0;
$isExpired = false;
$timeLeft = -1;
$currentTime = time();
// Existing code for time action
if ($alreadyInstalled && api_get_user_id()) {
$endTime = $session->end_time();
$isExpired = $session->is_expired();
} else {
// Chamilo not installed or user not logged in
$endTime = $currentTime + 315360000; // This sets a default end time far in the future
$isExpired = false;
}
$timeLeft = $endTime - $currentTime;
}
else {
$endTime = 999999;
$isExpired = false;
$timeLeft = 999999;
}
if ($endTime > 0) {
echo json_encode(['sessionEndDate' => $endTime, 'sessionTimeLeft' => $timeLeft, 'sessionExpired' => $isExpired]);
} else {
http_response_code(500);
echo json_encode(['error' => 'Error retrieving data from the current session']);
}
} elseif ($action == 'logout') {
require_once __DIR__.'/../../../main/inc/global-min.inc.php';
$userId = api_get_user_id();
online_logout($userId, false);
echo json_encode(['message' => 'Logged out successfully']);
} else {
// Handle unexpected action value
http_response_code(400);
echo json_encode(['error' => 'Invalid action parameter']);
}
} else {
// No action provided
http_response_code(400);
echo json_encode(['error' => 'No action parameter provided']);
}

@ -2580,3 +2580,6 @@ INSERT INTO extra_field_options (field_id, option_value, display_text, priority,
// is '$1EdTech-CC-FILEBASE$' (the latest), but previous versions of the standard
// recommended '$IMS-CC-FILEBASE$', so you might want to use that for greater compatibility.
//$_configuration['commoncartridge_path_token'] = '$IMS-CC-FILEBASE$';
// Set the following parameter to true to enable a session lifetime controller that notifies users that their session is about to expire
//$_configuration['session_lifetime_controller'] = false;

@ -9073,4 +9073,8 @@ $MoodleVersion = "Moodle version";
$CreateExport = "Create export file";
$MoodleExportAdminIDComment = "Moodle requires a user identification to be stored inside some XML files of the .mbz format. Please provide an internal (integer) ID of the user exporting this course or Moodle's internal user ID of the user that will be the owner of the imported resources. If you're in doubt, just write '1' and some fake data ton continue.";
$DropboxVulnerabilityWarning = "Remember to only download files sent by people you trust. If in doubt, please use a anti-virus tool on your computer to mitigate the risk of harm to your data.";
$SessionExpiredAt = "Session expired at";
$DueToInactivityTheSessionIsGoingToClose = "Due to your inactivity, this session is going to close in";
$KeepGoing = "Keep going";
$SessionIsClosing = "Your session is closing";
?>

@ -9008,4 +9008,8 @@ $CreateExport = "Créer un export";
$MoodleExportAdminIDComment = "Moodle requiert une identification de l'utilisateur pour la stocker au sein de fichiers XML qui font partie du format .mbz.
Merci de bien vouloir fournir un numéro interne (nombre entier) de l'utilisateur qui exporte le cours, ou d'un utilisateur de notre système, qui sera désigné (s'il y a correspondance) comme le propriétaire des ressources importées sur l'autre système. Si vous avez encore des doutes, indiquez simplement '1' et donnez des données fictives.";
$DropboxVulnerabilityWarning = "Ne téléchargez que des fichiers envoyés par des personnes en qui vous avez confiance. Dans le doute, merci d'utiliser un programme anti-virus sur votre ordinateur pour réduire les risques pour vos données.";
$SessionExpiredAt = "Session expirée à";
$DueToInactivityTheSessionIsGoingToClose = "Dû à votre inactivité, la session se fermera dans";
$KeepGoing = "Rester connecté";
$SessionIsClosing = "Votre session est en cours de fermeture";
?>

@ -9098,4 +9098,8 @@ $MoodleVersion = "Versión de Moodle";
$CreateExport = "Crear archivo de exporte";
$MoodleExportAdminIDComment = "Moodle requiere la indentificación de algún usuario para almacenarla dentro de los archivos XML del formato .mbz. Por favor indique un número de ID interno (entero) del usuario quien está exportando este curso, o el ID interno del usuario en Moodle para el usuario quien será propietario de los recursos importados. Si tiene duda, puede simplemente marcar '1' y algunos datos falsos para seguir.";
$DropboxVulnerabilityWarning = "Recuerde únicamente descargar archivos enviados por personas conocidas. Si tiene dudas, use un anti-virus en su computadora para reducir el riesgo de daños a sus datos.";
$SessionExpiredAt = "Sesión expirada el";
$DueToInactivityTheSessionIsGoingToClose = "Debido a su inactividad, esta sesión se cerrará en";
$KeepGoing = "Seguir conectado";
$SessionIsClosing = "Su sesión se está cerrando";
?>

@ -5,6 +5,9 @@ var offline_button = '<img src="' + _p.web_img + 'statusoffline.png">';
var connect_lang = '{{ "ChatConnected"|get_lang | escape('js')}}';
var disconnect_lang = '{{ "ChatDisconnected"|get_lang | escape('js')}}';
var chatLang = '{{ "GlobalChat"|get_lang | escape('js')}}';
var sessionRemainingSeconds = 0;
var sessionCounterInterval;
var sessionClosing = false;
{% if 'hide_chat_video'|api_get_configuration_value %}
var hide_chat_video = true;
@ -443,6 +446,10 @@ $(function() {
});
});
{% endif %}
if (window.self === window.top) {
checkSessionTime();
}
});
$(window).resize(function() {
@ -731,3 +738,193 @@ function copyTextToClipBoard(elementId)
/* Copy the text inside the text field */
document.execCommand("copy");
}
function checkSessionTime()
{
fetch('/main/inc/ajax/session_clock.ajax.php?action=time')
.then(response => {
if (!response.ok) {
throw new Error('Server error: ' + response.statusText);
}
return response.json();
})
.then(data => {
if (data.sessionTimeLeft <= 0) {
if (!document.getElementById('session-checker-overlay')) {
clearInterval(sessionCounterInterval);
var counterOverlay = document.getElementById('session-count-overlay');
if (counterOverlay) {
counterOverlay.remove();
}
var now = new Date();
var day = String(now.getDate()).padStart(2, '0');
var month = String(now.getMonth() + 1).padStart(2, '0');
var year = now.getFullYear();
var hour = String(now.getHours()).padStart(2, '0');
var minutes = String(now.getMinutes()).padStart(2, '0');
var dateTimeSessionExpired = day + '/' + month + '/' + year + ' ' + hour + ':' + minutes;
document.body.insertAdjacentHTML('afterbegin', '<div id="session-checker-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,1);display:flex;justify-content:center;align-items:center;z-index:1000;"><div id="session-checker-modal" style="background:white;padding:20px;border-radius:5px;box-shadow:0010pxrgba(0,0,0,0.5);width:35%;text-align:center;"><p style="margin-bottom:20px;">{{ 'SessionExpiredAt' | get_lang | escape('js')}} ' + dateTimeSessionExpired + '.</p><button class="btn btn-primary" onclick="window.location.pathname = \'/\';">OK</button></div></div>');
}
} else if (data.sessionTimeLeft <= 110) {
sessionRemainingSeconds = data.sessionTimeLeft - 5;
if (sessionRemainingSeconds < 0) {
sessionRemainingSeconds = 0;
}
if (!document.getElementById('session-count-overlay')) {
document.body.insertAdjacentHTML('afterbegin', '<div id="session-count-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:flex;justify-content:center;align-items:center;z-index:1000;"><div id="session-checker-modal" style="background:white;padding:20px;border-radius:5px;box-shadow:0010pxrgba(0,0,0,0.5);width:35%;text-align:center;"><p id="session-counter" style="margin-bottom:20px;">{{ 'DueToInactivityTheSessionIsGoingToClose' | get_lang | escape('js')}} ' + sessionRemainingSeconds + ' {{ 'Seconds' | get_lang | escape('js')}}</p><button class="btn btn-primary" id="btn-session-extend" onclick="extendSession();">{{ 'KeepGoing' | get_lang | escape('js')}}</button></div></div>');
sessionCounterInterval = setInterval(updateSessionTimeCounter, 1000);
}
setTimeout(checkSessionTime, 60000);
} else {
clearInterval(sessionCounterInterval);
var counterOverlay = document.getElementById('session-count-overlay');
if (counterOverlay) {
counterOverlay.remove();
}
setTimeout(checkSessionTime, 60000);
}
})
.catch(error => console.error('Error:', error));
}
function extendSession() {
fetch('/main/inc/ajax/online.ajax.php')
.then(response => {
if (!response.ok) {
throw new Error('Server error: ' + response.statusText);
}
return response;
})
.then(data => {
console.log('Session extended');
clearInterval(sessionCounterInterval);
var counterOverlay = document.getElementById('session-count-overlay');
if (counterOverlay) {
counterOverlay.remove();
}
})
.catch(error => console.error('Error:', error));
}
function updateSessionTimeCounter() {
var sessionCounter = document.getElementById('session-counter');
if (sessionRemainingSeconds > 3) {
sessionCounter.innerHTML = '{{ 'DueToInactivityTheSessionIsGoingToClose' | get_lang | escape('js')}} ' + sessionRemainingSeconds + ' {{ 'Seconds' | get_lang | escape('js')}}';
sessionRemainingSeconds--;
} else if (sessionRemainingSeconds <= 3 && sessionRemainingSeconds > 1) {
var currentUrl = window.location.href;
if (currentUrl.includes('lp_controller.php') && currentUrl.includes('lp_id=') && currentUrl.includes('action=view')) {
if (!sessionClosing) {
var btnSessionExtend = document.getElementById('btn-session-extend');
if (btnSessionExtend) {
btnSessionExtend.remove();
}
document.getElementById('session-counter').innerHTML = '{{ 'SessionIsClosing' | get_lang | escape('js')}}';
setTimeout(function() {
fetch('/main/inc/ajax/session_clock.ajax.php?action=logout')
.then(response => response.json())
.then(data => {
if (!document.getElementById('session-checker-overlay')) {
clearInterval(sessionCounterInterval);
var counterOverlay = document.getElementById('session-count-overlay');
if (counterOverlay) {
counterOverlay.remove();
}
var now = new Date();
var day = String(now.getDate()).padStart(2, '0');
var month = String(now.getMonth() + 1).padStart(2, '0');
var year = now.getFullYear();
var hour = String(now.getHours()).padStart(2, '0');
var minutes = String(now.getMinutes()).padStart(2, '0');
var dateTimeSessionExpired = day + '/' + month + '/' + year + ' ' + hour + ':' + minutes;
document.body.insertAdjacentHTML('afterbegin', '<div id="session-checker-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,1);display:flex;justify-content:center;align-items:center;z-index:1000;"><div id="session-checker-modal" style="background:white;padding:20px;border-radius:5px;box-shadow:0010pxrgba(0,0,0,0.5);width:35%;text-align:center;"><p style="margin-bottom:20px;">{{ 'SessionExpiredAt' | get_lang | escape('js')}} ' + dateTimeSessionExpired + '.</p><button class="btn btn-primary" onclick="window.location.pathname = \'/\';">OK</button></div></div>');
}
})
.catch((error) => {
console.error('Error:', error);
});
}, 1000);
lastCall();
}
sessionClosing = true;
}
else {
if (!sessionClosing) {
var btnSessionExtend = document.getElementById('btn-session-extend');
if (btnSessionExtend) {
btnSessionExtend.remove();
}
document.getElementById('session-counter').innerHTML = '{{ 'SessionIsClosing' | get_lang | escape('js')}}';
setTimeout(function() {
fetch('/main/inc/ajax/session_clock.ajax.php?action=logout')
.then(response => response.json())
.then(data => {
if (!document.getElementById('session-checker-overlay')) {
clearInterval(sessionCounterInterval);
var counterOverlay = document.getElementById('session-count-overlay');
if (counterOverlay) {
counterOverlay.remove();
}
var now = new Date();
var day = String(now.getDate()).padStart(2, '0');
var month = String(now.getMonth() + 1).padStart(2, '0');
var year = now.getFullYear();
var hour = String(now.getHours()).padStart(2, '0');
var minutes = String(now.getMinutes()).padStart(2, '0');
var dateTimeSessionExpired = day + '/' + month + '/' + year + ' ' + hour + ':' + minutes;
document.body.insertAdjacentHTML('afterbegin', '<div id="session-checker-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,1);display:flex;justify-content:center;align-items:center;z-index:1000;"><div id="session-checker-modal" style="background:white;padding:20px;border-radius:5px;box-shadow:0010pxrgba(0,0,0,0.5);width:35%;text-align:center;"><p style="margin-bottom:20px;">{{ 'SessionExpiredAt' | get_lang | escape('js')}} ' + dateTimeSessionExpired + '.</p><button class="btn btn-primary" onclick="window.location.pathname = \'/\';">OK</button></div></div>');
}
})
.catch((error) => {
console.error('Error:', error);
});
}, 1000);
}
sessionClosing = true;
}
}
else {
clearInterval(sessionCounterInterval);
var counterOverlay = document.getElementById('session-count-overlay');
if (counterOverlay) {
counterOverlay.remove();
}
var now = new Date();
var day = String(now.getDate()).padStart(2, '0');
var month = String(now.getMonth() + 1).padStart(2, '0');
var year = now.getFullYear();
var hour = String(now.getHours()).padStart(2, '0');
var minutes = String(now.getMinutes()).padStart(2, '0');
var dateTimeSessionExpired = day + '/' + month + '/' + year + ' ' + hour + ':' + minutes;
document.body.insertAdjacentHTML('afterbegin', '<div id="session-checker-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,1);display:flex;justify-content:center;align-items:center;z-index:1000;"><div id="session-checker-modal" style="background:white;padding:20px;border-radius:5px;box-shadow:0010pxrgba(0,0,0,0.5);width:35%;text-align:center;"><p style="margin-bottom:20px;">{{ 'SessionExpiredAt' | get_lang | escape('js')}} ' + dateTimeSessionExpired + '.</p><button class="btn btn-primary" onclick="window.location.pathname = \'/\';">OK</button></div></div>');
}
}

Loading…
Cancel
Save