chamilo / chamilo-lms

Chamilo is a learning management system focused on ease of use and accessibility
https://chamilo.org
GNU General Public License v3.0
784 stars 478 forks source link

Agregar aviso de expiración de sesión #4776

Open contidos opened 1 year ago

contidos commented 1 year ago

Algunos profesores utilizan lecciones con un tiempo mínimo de duración que obliga a los alumnos a estar un cierto tiempo conectados para poder avanzar y pasar a la siguiente lección.

El problema viene cuando un alumno, deja la lección sin actividad y regresa a ella pasado x tiempo. Generalmente mucho tiempo. Al hacerlo su contador sigue mostrando el tiempo de avance pero en realidad, si la sesión tiene, por ejemplo, dos horas de duración y han pasado 8 horas, el alumno no se entera porque no le sale un aviso de que su sesión ha expirado.

Me gustaría proponer que cuando una sesión expire, la pantalla de Chamilo cambie para dar ese aviso al alumno.

contidos commented 1 year ago

A modo de actualización hay que diseñar un sistema de expiración de la sesión que al llegar a cierto tiempo muestre una pantalla de que la sesión ha expirado, o incluso, en el mejor de los casos, que pudiese avisar con una cuenta regresiva x tiempo antes, esto último lo dejamos en standby

En principio esto obligaría a tener un subproceso que está comprobando cada X segundos el tiempo restante de sesión, este subproceso se tendría que analizar si su ejecución provocaría la extensión de la sesión, lo que sería un efecto indeseado.

Además de este subproceso deberemos incluir un javascript para que cuando la sesión expire lo ejecute, meta una capa difuminada y sobre ella un modal indicando que la sesión ha caducado

ywarnier commented 9 months ago

La propuesta está bien. Lo del no extender la sesión creo que se podría hacer en puro JS verificando el cookie de sesión. Quizás el cookie de sesión mismo tenga que tener un nuevo valor a cada vez que se refresca, que diga en cuanto tiempo se vence (ojo : no usar fecha+hora porque puede variar de una computadora a la otra y cortar sesión antes de la hora) y tener una cuenta regresiva JS. No estoy seguro de como hacerla para que no tome demasiado recursos. Supongo que un timer que solo hace un "tick" cada 60 segundos debería ser relativamente ligero. Siempre habrá formas en que esto falle (por ejemplo si tengo varias pestañas abiertas, habría que evitar que el JS de ambas entre en conflicto) pero creo que debería poderse lograr un resultado aceptable en un 99% de casos.

juancp-contidosdixitais commented 8 months ago

Finalmente creo que lo tengo: https://github.com/contidos-dixitais/chamilo-lms/commit/7bce9799094ff16c922b3805351a2f486605bb4a

Por un lado la sesión se estaba extendiendo debido a que cada vez que incluía una llamada a global.inc.php o recurso donde se cargara la sesión se extendía. Tomando lo anterior en cuenta se hizo lo siguiente:

1. Crear main/inc/ajax/session_clock.ajax.php -> https://github.com/contidos-dixitais/chamilo-lms/commit/7bce9799094ff16c922b3805351a2f486605bb4a#diff-42d443253f7a36d9340581ab7bc0e6864ad7e65a1dddb5b63d27498734862604

Cargamos los recursos necesarios, que en cualquier otro caso no tendríamos que hacer al encargase de ello global.inc.php,

image

https://github.com/contidos-dixitais/chamilo-lms/blob/7bce9799094ff16c922b3805351a2f486605bb4a/main/inc/ajax/session_clock.ajax.php#L3-L17

Una vez los tenemos ya podemos consultar el estado de la sesión:

image

https://github.com/contidos-dixitais/chamilo-lms/blob/7bce9799094ff16c922b3805351a2f486605bb4a/main/inc/ajax/session_clock.ajax.php#L19-L35

Se tiene en cuenta si Chamilo aún no se ha instalado (no existe archivo de configuración) o si no está logueado, en esos casos se envía el dato falso de que la sesión caduca a 10 años vista:

image

https://github.com/contidos-dixitais/chamilo-lms/blob/7bce9799094ff16c922b3805351a2f486605bb4a/main/inc/ajax/session_clock.ajax.php#L30-L32

Finalmente se devuelve los datos:

image

https://github.com/contidos-dixitais/chamilo-lms/blob/7bce9799094ff16c922b3805351a2f486605bb4a/main/inc/ajax/session_clock.ajax.php#L37-L42

2. ¿Quién consume main/inc/ajax/session_clock.ajax.php?

En mi solución modifico main/template/default/layout/main.js.tpl -> https://github.com/contidos-dixitais/chamilo-lms/commit/7bce9799094ff16c922b3805351a2f486605bb4a#diff-27e33c2b97fd480e867fe26d393e1d332ffc9ddcf73fa3d83e70739b70d41ce1

Agrego tres nuevos métodos, checkSessionTime(), extendSession() y updateSessionTimeCounter().

checkSessionTime() -> Realiza un fetch a main/inc/ajax/session_clock.ajax.php cada minuto, comprueba el tiempo restante, si es menor de 100 segundos inyecta en el DOM un modal que muestra una cuenta regresiva (updateSessionTimeCounter()) del tiempo queda para que cierre la sesión, este modal tiene un botón que extiende la sesión y cierra el modal. Si tengo varias ventanas / pestañas abiertas, se mostrará en todas el modal, y, al extender la sesión en una de ellas la sesión el modal desaparecerá del resto en el próximo ciclo del timer.

Finalmente si detecta que la sesión ha finalizado se elimina el modal anterior y se inyecta uno nuevo al DOM con la fecha y hora de cuando ocurrió y un botón para ir a la home. ¿Por qué un botón para ir a la home y no recargar la página?, estuve realizando varias pruebas y dentro de una lección, al recargarse la pagina con una sesión de usuario ya finalizada, solicita el login (como es normal) pero luego nos redirige a una pagina en blanco, no la url de la lección ... se puede comprobar dejando finalizar una sesión de usuario dentro de una lección y recargando con F5 o con el botón del navegador. Por tanto, como no encontré una solución mejor, el botón nos envía a la home.

¿Como se extiende la sesión?, el botón del modal de la cuenta regresiva llama a la nueva función extendSession(), esta hace un fetch de /main/inc/ajax/online.ajax.php, este es utilizado en Chamilo para obtener los usuarios que hay en línea (get_users_online y load_online_user), si no se pasa ningún parámetro GET no hace nada, pero al inicio de todo, como se invoca a global.inc.php serviría para este propósito, (además el nombre, online.ajax.php, nos viene como anillo al dedo ;) ) evitando crear algo a mayores para extender la sesión. Aún así no estoy muy convencido ya que aunque el resultado es el idóneo no lo estaría para lo que sería su fin original

Usuario cuya sesión se va cerrar en 45 segundos, todas las ventanas / pestañas muestran el modal:

captura

Usuario con sesión finalizada:

captura_2

Si se da el visto bueno a esta solución quedaría agregar los texto localizados