From 7b4f32fba20a678eb5a7ed18acf5791f6ccddf39 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mat=C3=ADas=20Aguirre?= Date: Tue, 3 Jul 2012 16:43:30 -0300 Subject: [PATCH] Fix expiration calculation, add django backward compatibility code. Refs #381 --- social_auth/models.py | 36 +++++++++++++++++++++++++----------- social_auth/utils.py | 23 +++++++++++++++++++++++ social_auth/views.py | 5 +++-- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/social_auth/models.py b/social_auth/models.py index 87ce08a..28a58c1 100644 --- a/social_auth/models.py +++ b/social_auth/models.py @@ -1,9 +1,10 @@ """Social auth models""" -from datetime import datetime +import time +from datetime import datetime, date, timedelta from django.db import models -from django.utils.timezone import utc + from social_auth.fields import JSONField -from social_auth.utils import setting +from social_auth.utils import setting, utc # If User class is overridden, it *must* provide the following fields @@ -48,17 +49,30 @@ class UserSocialAuth(models.Model): return {} def expiration_datetime(self): - """Return saved session expiration seconds if any. Is returned in - the form of timezone-aware datetime. None is returned if there's no - value stored or it's malformed. + """Return provider session live seconds. Returns a timedelta ready to + use with session.set_expiry(). + + If provider returns a timestamp instead of session seconds to live, the + timedelta is inferred from current time (using UTC timezone). None is + returned if there's no value stored or it's invalid. """ - if self.extra_data: - name = setting('SOCIAL_AUTH_EXPIRATION', 'expires') + name = setting('SOCIAL_AUTH_EXPIRATION', 'expires') + if self.extra_data and name in self.extra_data: try: - return datetime.utcfromtimestamp(self.extra_data.get(name)).replace(tzinfo=utc) + expires = int(self.extra_data.get(name)) except (ValueError, TypeError): - pass - return None + return None + + now = datetime.now() + now_timestamp = time.mktime(now.timetuple()) + + # Detect if expires is a timestamp + if expires > now_timestamp: # expires is a datetime + return datetime.utcfromtimestamp(expires) \ + .replace(tzinfo=utc) - \ + now.replace(tzinfo=utc) + else: # expires is a timedelta + return timedelta(seconds=expires) class Nonce(models.Model): diff --git a/social_auth/utils.py b/social_auth/utils.py index 7542b05..8c38325 100644 --- a/social_auth/utils.py +++ b/social_auth/utils.py @@ -1,11 +1,34 @@ import urlparse import logging from collections import defaultdict +from datetime import timedelta, tzinfo from django.conf import settings from django.db.models import Model from django.contrib.contenttypes.models import ContentType +try: + from django.utils.timezone import utc as django_utc +except ImportError: # django < 1.4 + class UTC(tzinfo): + """UTC implementation taken from django 1.4.""" + def __repr__(self): + return '' + + def utcoffset(self, dt): + return timedelta(0) + + def tzname(self, dt): + return 'UTC' + + def dst(self, dt): + return timedelta(0) + + django_utc = None + + +utc = django_utc + def sanitize_log_data(secret, data=None, leave_characters=4): """ diff --git a/social_auth/views.py b/social_auth/views.py index 8f4bc3c..fc4966b 100644 --- a/social_auth/views.py +++ b/social_auth/views.py @@ -117,9 +117,10 @@ def complete_process(request, backend, *args, **kwargs): # Set session expiration date if present and not disabled by # setting. Use last social-auth instance for current provider, # users can associate several accounts with a same provider. - if social_user.expiration_datetime(): + expiration = social_user.expiration_datetime() + if expiration: try: - request.session.set_expiry(social_user.expiration_datetime()) + request.session.set_expiry(expiration) except OverflowError: # Handle django time zone overflow, set default expiry. request.session.set_expiry(None) -- 2.39.5