Skip to content

fix(AuthoringToolComponent): Session expires silently because the timer is never started - #2369

Open
Isaries wants to merge 1 commit into
WISE-Community:developfrom
Isaries:fix/authoring-session-timer
Open

Isaries wants to merge 1 commit into
WISE-Community:developfrom
Isaries:fix/authoring-session-timer

Conversation

@Isaries

@Isaries Isaries commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

The authoring tool never starts the session timer, so an author's session can expire while the page gives no sign of it. Every save after that is rejected, and the page keeps accepting edits.

SessionService.initializeSession() starts a one-minute timer that renews the session while the user is active, shows the "Session Timeout" warning before the timeout, and logs out after it. AuthoringToolComponent is wired for all of this: it records mouse, keyboard and touch activity with userIsActive(), subscribes to showSessionWarning$ and logOut$, and the author config it loads carries sessionTimeout and renewSessionURL. But nothing in the authoring tool calls initializeSession(). The AngularJS route states called it after loading /api/author/config/<id>, and the call was not carried over when those states were replaced in #1390, so today only the student VLE starts the timer. The activity the authoring tool records is never read.

In the authoring tool the session is therefore kept alive only by real requests. An author who reads, thinks, or edits a translation field for longer than the session timeout without saving loses the session silently. From then on every save returns 403. The page shows "Error Saving Unit. Please refresh the page.", and refreshing discards whatever was typed since. This was observed in production: after a 35-minute pause, an author working on English translations had five consecutive translation saves on five different steps rejected over eight minutes, and the server log shows no renew request during the whole visit.

Changes

  • AuthoringToolComponent calls initializeSession() in ngOnInit and the new stopCheckMouseEvent() in ngOnDestroy, so the timer lives exactly as long as the component that handles its events.
  • initializeSession() stops any earlier timer before starting a new one, so entering the authoring tool again does not stack timers. It also clears a warning flag left over from an earlier visit, which would otherwise suppress the warning for the rest of the session, and it does not start the timer when sessionTimeout is not positive (a session that never expires).
  • renewSession() and checkForLogout() log out only when the renew endpoint answers false. LoginController.renewSession sends an empty body when the portal row cannot be read, which HttpClient parses as null; that previously counted as logged out, and with the timer running in authoring it would now be checked every minute.
  • The warning dialog logs out only when the author chooses No. Closing it with Escape, a backdrop click or a navigation used to log out as well, which this change would otherwise make reachable in authoring for the first time.

Two existing behaviours are unchanged and worth knowing. The forced-logout check calls the renew endpoint, which itself refreshes the server session, so a tab left idle keeps its session alive while showing the warning rather than being logged out. And the Classroom Monitor has the same missing initializeSession() call; it is left out of this PR because starting the timer there changes what teachers see during a class (the warning dialog after an idle period) and deserves its own decision.

Test

  • sessionService.spec.ts gains six cases: no timer when the session never expires, a single timer after repeated initialization, a stale warning cleared on initialization, stopCheckMouseEvent() stopping the timer, and no logout on an empty renew answer in both renewSession() and checkForLogout(). They do not compile against the current develop because stopCheckMouseEvent() is new; with only an empty stopCheckMouseEvent() added to develop, all six fail. The existing cases pass, with one renamed because the preview stub it set up was never read.
  • Full suite: 2,506 pass. The one failure is millisecondsToDateTime() in datetime.spec.ts, which expects US Pacific output and fails on a workstation in UTC+8 with a zh-TW locale; this branch does not touch it.

…er is never started

The authoring tool records activity and subscribes to the session
warning and forced logout, but since the AngularJS routes were removed
in WISE-Community#1390 nothing calls SessionService.initializeSession() there, so the
timer that renews the session, warns and logs out never runs. An author
who makes no request for the session timeout loses the session without
notice, and every later save is rejected while the page keeps
accepting edits.

AuthoringToolComponent now starts the timer on init and stops it on
destroy. initializeSession() replaces any earlier timer, clears a stale
warning flag, and does nothing when the session never expires. Only an
explicit false from the renew endpoint logs out; the empty body it
sends when the portal row cannot be read no longer ends the session.
Dismissing the warning dialog without choosing No keeps the author
logged in.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant