Repository: learningequality/kolibri

Issue:
Up the login session idle time to 10 minutes
## Summary

Currently at 5 minutes, I find it to be very low. But I'm not a learner, I'm a person who has a lot of tabs opened while testing :)

This is targeted already at 0.4 as a quick fix kind of thing.

Suggesting to up it to 10 minutes. Would like to hear what you think about this @harishbalachandran ?


Discussion:
@harishbalachandran if you find any issues with the timeout, please report here!
Some additional context from a slack conversation:

![image](https://user-images.githubusercontent.com/2367265/31357352-39cf4a48-acf6-11e7-9a43-dbed85b4e72d.png)

However it sounds like @benjaoming timed out even though he had the page open, so the heartbeat wasn't working?


Yeah, I think I misdescribed the precise heartbeat behaviour there, and was focusing more on the 'passive use' case.

Heartbeat only beats if the user has interacted with the UI at all.
Hm okay then I'd definitely be worried about people being logged out too soon - it's much more aggressive than 'end session when the browser is closed'.

What about implementing a light-weight session keep-alive heartbeat? No DB interaction - just to make this feature work as originally intended.

Yeah, could make an endpoint with the active flag that would only update the UserSessionLog if true.
@indirectlylit yup it's the *session ***idle*** time* - I don't know how to phrase it any better. But you have to leave the tab or window with no interaction. I think this is likely to occur when learners are listening to instructions from the teacher.. 5 minutes aren't long. Of course we want to log users out so learners cannot (intentionally/mistakenly) take over each other's profiles.

An example:

\- Teacher: Ahrem, everyone put down your tablets for a moment, I wanna tell you about how life was like before computers
\- Teacher: *(talks about forests and animals)*
\- Teacher: Alright, now back to the assignments
\- \**(everybody's logged out)*\*
@benjaoming @rtibbles @indirectlylit, the main reason for a session log out was that, when a student does not log out on a particular tablet and the next learner gets the same tablet in the next session then he/she is logged in to the previous leaners account. 

But like @benjaoming pointed out, there are use cases when a teacher would request the learners to pause and explain a concept or a child might pause from his current work, help his/her friends to clear some doubts.

Since the logout uses case cannot be implemented when a learner closes the browser or when a tablet is turned off, it might be worth while to keep 10 minutes as a logout time rather than 5 minutes. 
Reason being:
* Even if the leaners are sharing the same tablets for the next session, it takes more than 10 minutes before they use the same tablets again in a different tablet class in an another division or grade. 
* 10 minutes seams to be a good time before the learner gets back to his or her screen and continue where they paused. If the idle time is more than 10 mins its okey for the leaner to be logged out, but there has to be an automatic redirection where in the leaner is logged out and is given the home page clearly indicating that he needs to log out. In todays testing, the 5 minute session time out implemented on 0.4.6 does not happen smoothly and the leaner is shown an error page. @swapnil106111 will be logging a separate issues to highlight error sate while the tablet is kept idle for 5 minutes.
Thanks @harishbalachandran for the thorough feedback! If you have any extra detailed adjustments - like say 7 or 8 minutes, that's also interesting! 5 and 10 are nice because they are easy to remember and communicate.

>  In todays testing, the 5 minutes session time out implemented on 0.4.6 does not happen smoothly and the leaner is shown an error page, rather than logging out and shown the homepage that would indicate that the session has times out. @swapnil106111 will be logging a separate issues to highlight error sate while the tablet is kept idle for 5 minutes.

This should be  #2390!

to be concrete, my suggestion above was:

* keep the server-side session timeout at 5 minutes
* implement an ajax 'ping' on a javascript timer, maybe every minute
* when a browser window is open - even in the background - this should prevent the session from timing out, ever
* when the browser window is closed for more than 5 minutes, the session times out

@benjaoming @rtibbles @indirectlylit 

Here are the 4 scenarios that we tested today, and hope it gives enough information to solve this issue.

**Case 1:** 
Captured: 
On a teacher server
Scenario: 
Logged in and left the system idle for more than 10 minutes.
Logged in at 2:23PM:
![import1](https://user-images.githubusercontent.com/13453618/31882074-3e69e60e-b803-11e7-895c-88d70f34fa24.png)
Automatically logged out at 2:31PM:
![import2](https://user-images.githubusercontent.com/13453618/31882095-5312aa50-b803-11e7-8017-294ca01c9fc3.png)
Observation:
The logout happened around  8 to 9 mins. Still seams to be a valid use case, for idle time scenario. 

**Case 2:** 
Captured: 
On a teacher server
Scenario: 
Logged in and kept the browser active by navigating through the pages.
Logged in around 2:49PM:
![import_seesion](https://user-images.githubusercontent.com/13453618/31882486-92c04dc8-b804-11e7-84eb-6b0899582b7a.png)
Kept the session active by navigating at 2:53PM:
![import_seeiosn2](https://user-images.githubusercontent.com/13453618/31882517-b4176d4e-b804-11e7-9e46-152b81d4c6dc.png)
Still got logged off at 2:56PM:
![import_session3](https://user-images.githubusercontent.com/13453618/31882581-df27d99c-b804-11e7-8f0b-ac20f6c78d8a.png)
Observation:
The logout happened after 7mins irrespective of keeping the session active by navigating through various page.

**Case 3:** 
Captured: 
On a learners tablet
Scenario: 
Logged in and left the tablet idle for more than 10 minutes.
Logged in at 2:46PM:
![screenshot_2017-10-23-14-46-44](https://user-images.githubusercontent.com/13453618/31884128-cb55710e-b809-11e7-81cc-a8faa50766a3.png) 

Logged out at 2:57PM:
Had to refresh the page to see that the page was signed out, 
Below screenshot is before refresh.
![screenshot_2017-10-23-14-57-17](https://user-images.githubusercontent.com/13453618/31884293-3e7f7e36-b80a-11e7-9f72-1710474d75d2.png)
After refresh:
![screenshot_2017-10-23-14-57-31](https://user-images.githubusercontent.com/13453618/31884365-712957e4-b80a-11e7-9909-67e7c02fcc10.png)
Observation:
The logout happened after a fixed time. Still seams to be a valid use case, for idle time scenario. 
But the learner is not even aware that he/she has been logged out, since the logged out page doesn't not explicitly say so, or the learner is not shown the sign in page that would indicate he/she is logged out and they need to sign in again.

**Case 4:**
Captured: 
On a teacher server
Scenario: 
Logged in and kept the browser active by solving exercises continuously.
Logged in at 3:21PM:
![screenshot_2017-10-23-15-21-20](https://user-images.githubusercontent.com/13453618/31884562-22cbcd92-b80b-11e7-8ed7-eb0f8bac1b21.png)
Kept the session active by solving few exercise:
![screenshot_2017-10-23-15-27-45](https://user-images.githubusercontent.com/13453618/31884581-3809c98e-b80b-11e7-8ac4-d2e823434c84.png)
Still got logged off at 3:31PM:
![import_session3](https://user-images.githubusercontent.com/13453618/31882581-df27d99c-b804-11e7-8f0b-ac20f6c78d8a.png)
Observation:
The logged out after 10mins irrespective of keeping the session active solving the exercises continuously.
Reopening to track fixing of activity session extension.
Replicated behaviour above locally.

Resolving patch:
diff --git a/kolibri/auth/api.py b/kolibri/auth/api.py
--- a/kolibri/auth/api.py
+++ b/kolibri/auth/api.py
@@ -1,5 +1,7 @@
 from __future__ import absolute_import, print_function, unicode_literals
 
+import time
+
 from django.contrib.auth import authenticate, get_user, login, logout
 from django.contrib.auth.models import AnonymousUser
 from django.db.models.query import F
@@ -225,6 +227,8 @@ def retrieve(self, request, pk=None):
         return Response(self.get_session(request))
 
     def get_session(self, request):
+        # Set last activity on session to the current time to prevent session timeout
+        request.session['last_session_request'] = int(time.time())
         # Default to active, only assume not active when explicitly set.
         active = True if request.GET.get('active', 'true') == 'true' else False
         user = get_user(request)


Test patch:
diff --git a/kolibri/auth/test/test_api.py b/kolibri/auth/test/test_api.py
--- a/kolibri/auth/test/test_api.py
+++ b/kolibri/auth/test/test_api.py
@@ -341,6 +341,13 @@ def test_session_return_anon_kind(self):
         response = self.client.get(reverse('session-detail', kwargs={'pk': 'current'}))
         self.assertTrue(response.data['kind'][0], 'anonymous')
 
+    def test_session_update_last_active(self):
+        self.client.post(reverse('session-list'), data={"username": self.user.username, "password": DUMMY_PASSWORD, "facility": self.facility.id})
+        expire_date = Session.objects.get().expire_date
+        self.client.get(reverse('session-detail', kwargs={'pk': 'current'}))
+        new_expire_date = Session.objects.get().expire_date
+        self.assertTrue(expire_date < new_expire_date)
+
 
 class AnonSignUpTestCase(APITestCase):