From 68f9abb6f58419676527c58983d31f6a4dcdb9b7 Mon Sep 17 00:00:00 2001 From: Roger Steve Ruiz Date: Mon, 18 Jun 2018 13:06:51 -0400 Subject: [PATCH] Add Auto Logout functionality (#815) * Add Auto Logout functionality * Update middleware to the latest & greatest * Upgrade settings for MIDDLEWARE * Update order of imports * Fix test check for tock session activity data * Move the fmt up --- tock/tock/middleware.py | 36 ++++++++++++++++++++++++++++++ tock/tock/settings/base.py | 5 ++++- tock/tock/settings/dev.py | 6 ++--- tock/tock/settings/test.py | 4 ++-- tock/tock/tests/test_middleware.py | 28 +++++++++++++++++++++++ 5 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 tock/tock/middleware.py create mode 100644 tock/tock/tests/test_middleware.py diff --git a/tock/tock/middleware.py b/tock/tock/middleware.py new file mode 100644 index 000000000..c34159f4e --- /dev/null +++ b/tock/tock/middleware.py @@ -0,0 +1,36 @@ +from datetime import datetime, timedelta +from django.conf import settings +from django.contrib import auth + + +class AutoLogout(object): + + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + fmt = '%Y%m%d%H%M%S' + + # Check if user exists and is logged in + if request.user and request.user.is_authenticated(): + + logout_time_in_seconds = settings.AUTO_LOGOUT_DELAY_MINUTES * 60 + + # Compare the time of the last activity with the logout delay + try: + session_time = datetime.strptime( + request.session['tock_last_activity'], + fmt + ) + if datetime.now() - session_time > \ + timedelta(seconds=logout_time_in_seconds): + auth.logout(request) + del request.session['tock_last_activity'] + return self.get_response(request) + except KeyError: + pass + + request.session['tock_last_activity'] = \ + datetime.now().strftime(fmt) + + return self.get_response(request) diff --git a/tock/tock/settings/base.py b/tock/tock/settings/base.py index ba144d7d6..ea48b5c95 100644 --- a/tock/tock/settings/base.py +++ b/tock/tock/settings/base.py @@ -69,7 +69,7 @@ ] -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -78,6 +78,7 @@ 'uaa_client.middleware.UaaRefreshMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'tock.middleware.AutoLogout', ) AUTHENTICATION_BACKENDS = ( @@ -123,4 +124,6 @@ UAA_TOKEN_URL = 'https://uaa.fr.cloud.gov/oauth/token' UAA_LOGOUT_URL = 'https://login.fr.cloud.gov/logout.do' +AUTO_LOGOUT_DELAY_MINUTES = 60 + TOCK_CHANGE_REQUEST_FORM = 'https://docs.google.com/a/gsa.gov/forms/d/1EpVTxXgRNgYfoSA2J8Oi-csjhFKqFm5DT542vIlahpU/viewform?edit_requested=true' diff --git a/tock/tock/settings/dev.py b/tock/tock/settings/dev.py index 3f3b8062b..f1a16e8e2 100644 --- a/tock/tock/settings/dev.py +++ b/tock/tock/settings/dev.py @@ -4,7 +4,7 @@ from .base import * # noqa # spell out explicit variable dependencies -from .base import (DATABASES, INSTALLED_APPS, MIDDLEWARE_CLASSES, TEMPLATES) +from .base import (DATABASES, INSTALLED_APPS, MIDDLEWARE, TEMPLATES) DEBUG = True @@ -26,7 +26,7 @@ ) INSTALLED_APPS += ('nplusone.ext.django', ) -MIDDLEWARE_CLASSES += ('nplusone.ext.django.NPlusOneMiddleware', ) +MIDDLEWARE += ('nplusone.ext.django.NPlusOneMiddleware', ) # Change this setting to True in order to discover potentially inefficient # queries while doing active development using nplusone. @@ -37,7 +37,7 @@ if not IS_RUNNING_TEST_SUITE: INSTALLED_APPS += ('debug_toolbar', ) - MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware', ) + MIDDLEWARE += ('debug_toolbar.middleware.DebugToolbarMiddleware', ) else: NPLUSONE_RAISE = True diff --git a/tock/tock/settings/test.py b/tock/tock/settings/test.py index dfd42b419..3ccb4fc7a 100644 --- a/tock/tock/settings/test.py +++ b/tock/tock/settings/test.py @@ -2,7 +2,7 @@ from .base import * # noqa # spell out explicit variable dependencies -from .base import (INSTALLED_APPS, MIDDLEWARE_CLASSES) +from .base import (INSTALLED_APPS, MIDDLEWARE) SECRET_KEY = get_random_string(50) @@ -18,7 +18,7 @@ } INSTALLED_APPS += ('nplusone.ext.django', ) -MIDDLEWARE_CLASSES += ('nplusone.ext.django.NPlusOneMiddleware', ) +MIDDLEWARE += ('nplusone.ext.django.NPlusOneMiddleware', ) NPLUSONE_RAISE = True MEDIA_ROOT = './media/' diff --git a/tock/tock/tests/test_middleware.py b/tock/tock/tests/test_middleware.py new file mode 100644 index 000000000..d3180dc33 --- /dev/null +++ b/tock/tock/tests/test_middleware.py @@ -0,0 +1,28 @@ +import time +from django.test import TestCase, override_settings +from django.core.urlresolvers import reverse + +from test_common import ProtectedViewTestCase + + +@override_settings(AUTO_LOGOUT_DELAY_MINUTES=0.05) +class MiddlewareAutoLogoutTests(ProtectedViewTestCase, TestCase): + + def test_user_auto_logged_out(self): + self.login(username='regular.user') + + response_initial = self.client.get(reverse('ListReportingPeriods')) + self.assertEqual(response_initial.status_code, 200) + self.assertIn('tock_last_activity', response_initial.client.session) + + # Sleep for an arbirary five seconds + time.sleep(5) + + response_after_expiry = self.client.get( + reverse('ListReportingPeriods') + ) + self.assertEqual(response_after_expiry.status_code, 302) + self.assertIn( + 'tock_last_activity', + response_after_expiry.client.session + )