Skip to content

Commit

Permalink
Merge pull request #73 from sdelements/fix/6446_json_serializable_ses…
Browse files Browse the repository at this point in the history
…sion_dates

Serialize datetime in session
  • Loading branch information
emintham authored May 1, 2019
2 parents 2e2037f + cb9ad93 commit 40a3e8c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 19 deletions.
1 change: 1 addition & 0 deletions requirements
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
django>=1.8,<=1.11
ua_parser==0.7.1
python-dateutil==2.8.0
53 changes: 46 additions & 7 deletions security/middleware.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright (c) 2011, SD Elements. See LICENSE.txt for details.

import dateutil.parser
import importlib
import json
import logging
Expand Down Expand Up @@ -906,6 +907,44 @@ class SessionExpiryPolicyMiddleware(CustomLogoutMixin, BaseMiddleware):
START_TIME_KEY = 'starttime'
LAST_ACTIVITY_KEY = 'lastactivity'

@classmethod
def _get_datetime_in_session(cls, key, session):
return dateutil.parser.parse(session[key])

@classmethod
def _set_datetime_in_session(cls, key, value, session):
session[key] = str(value)

@classmethod
def get_start_time(cls, request):
return cls._get_datetime_in_session(
cls.START_TIME_KEY,
request.session
)

@classmethod
def set_start_time(cls, request, date):
cls._set_datetime_in_session(
cls.START_TIME_KEY,
date,
request.session
)

@classmethod
def get_last_activity(cls, request):
return cls._get_datetime_in_session(
cls.LAST_ACTIVITY_KEY,
request.session
)

@classmethod
def set_last_activity(cls, request, date):
cls._set_datetime_in_session(
cls.LAST_ACTIVITY_KEY,
date,
request.session
)

def load_setting(self, setting, value):
if setting == 'SESSION_COOKIE_AGE':
self.SESSION_COOKIE_AGE = value or self.SECONDS_PER_DAY
Expand Down Expand Up @@ -944,8 +983,8 @@ def process_request(self, request):
if (
self.START_TIME_KEY not in request.session or
self.LAST_ACTIVITY_KEY not in request.session or
timezone.is_naive(request.session[self.START_TIME_KEY]) or
timezone.is_naive(request.session[self.LAST_ACTIVITY_KEY])
timezone.is_naive(self.get_start_time(request)) or
timezone.is_naive(self.get_last_activity(request))
):
response = self.process_new_session(request)
else:
Expand All @@ -959,14 +998,14 @@ def process_new_session(self, request):
session = request.session

logger.debug("New session %s started: %s", session.session_key, now)
session[self.START_TIME_KEY] = now
session[self.LAST_ACTIVITY_KEY] = now
self.set_start_time(request, now)
self.set_last_activity(request, now)

def process_existing_session(self, request):
now = timezone.now()
session = request.session
start_time = session[self.START_TIME_KEY]
last_activity_time = session[self.LAST_ACTIVITY_KEY]
start_time = self.get_start_time(request)
last_activity_time = self.get_last_activity(request)

logger.debug("Session %s started: %s",
session.session_key,
Expand Down Expand Up @@ -997,7 +1036,7 @@ def process_existing_session(self, request):
return response

logger.debug("Session %s is still active.", session.session_key)
session[self.LAST_ACTIVITY_KEY] = now
self.set_last_activity(request, now)

def get_diff_in_seconds(self, now, time):
diff = now - time
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def run(self):
long_description=readme,
maintainer="SD Elements",
maintainer_email="[email protected]",
version="0.9.10",
version="0.10.0",
packages=["security", "security.south_migrations",
"security.migrations", "security.auth_throttling"],
url='https://github.com/sdelements/django-security',
Expand All @@ -52,5 +52,6 @@ def run(self):
install_requires=[
'django>=1.8',
'ua_parser>=0.7.1',
'python-dateutil==2.8.0',
],
cmdclass={'test': Test})
3 changes: 0 additions & 3 deletions testing/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,6 @@ def is_version(version):
P3P_POLICY_URL = '/w3c/p3p.xml'
P3P_COMPACT_POLICY = 'PRIVATE'

# Django 1.6 uses JSONSerializer which can't handle datetime
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
Expand Down
26 changes: 18 additions & 8 deletions testing/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,12 +337,14 @@ def test_session_variables_are_set(self):
self.client.get('/home/')
now = timezone.now()

start_time = self.client.session[
SessionExpiryPolicyMiddleware.START_TIME_KEY
]
last_activity = self.client.session[
SessionExpiryPolicyMiddleware.LAST_ACTIVITY_KEY
]
start_time = SessionExpiryPolicyMiddleware._get_datetime_in_session(
SessionExpiryPolicyMiddleware.START_TIME_KEY,
self.client.session
)
last_activity = SessionExpiryPolicyMiddleware._get_datetime_in_session(
SessionExpiryPolicyMiddleware.LAST_ACTIVITY_KEY,
self.client.session
)

self.assertTrue(now - start_time < datetime.timedelta(seconds=10))
self.assertTrue(now - last_activity < datetime.timedelta(seconds=10))
Expand All @@ -354,7 +356,11 @@ def session_expiry_test(self, key, expired):
"""
self.assertTrue(self.client.get('/home/').status_code, 200)
session = self.client.session
session[key] = expired
SessionExpiryPolicyMiddleware._set_datetime_in_session(
key,
expired,
session
)
session.save()
response = self.client.get('/home/')
self.assertRedirects(response,
Expand Down Expand Up @@ -392,7 +398,11 @@ def test_exempted_session_expiry_urls(self):
self.assertTrue(self.client.get('/home/').status_code, 200)

session = self.client.session
session[SessionExpiryPolicyMiddleware().LAST_ACTIVITY_KEY] = expired
SessionExpiryPolicyMiddleware._set_datetime_in_session(
SessionExpiryPolicyMiddleware.LAST_ACTIVITY_KEY,
expired,
session
)
session.save()

exempted_response = self.client.get('/accounts/login/')
Expand Down

0 comments on commit 40a3e8c

Please sign in to comment.