"""Django ORM models for Social Auth"""
+
+
+import base64
from datetime import timedelta
from django.db import models
+from openid.association import Association as OIDAssociation
from social_auth.fields import JSONField
from social_auth.utils import setting
return UserSocialAuth.objects.create(user=user, uid=uid, provider=provider)
+def store_association(server_url, association):
+ args = {'server_url': server_url, 'handle': association.handle}
+ try:
+ assoc = Association.objects.get(**args)
+ except Association.DoesNotExist:
+ assoc = Association(**args)
+ assoc.secret = base64.encodestring(association.secret)
+ assoc.issued = association.issued
+ assoc.lifetime = association.lifetime
+ assoc.assoc_type = association.assoc_type
+ assoc.save()
+
+
+def get_oid_associations(server_url, handle=None):
+ args = {'server_url': server_url}
+ if handle is not None:
+ args['handle'] = handle
+
+ return sorted([
+ (assoc.id,
+ OIDAssociation(assoc.handle,
+ base64.decodestring(assoc.secret),
+ assoc.issued,
+ assoc.lifetime,
+ assoc.assoc_type))
+ for assoc in Association.objects.filter(**args)
+ ], key=lambda x: x[1].issued, reverse=True)
+
+
+def delete_associations(ids_to_delete):
+ Association.objects.filter(pk__in=ids_to_delete).delete()
+
+
+def use_nonce(server_url, timestamp, salt):
+ return Nonce.objects.get_or_create(server_url=server_url,
+ timestamp=timestamp,
+ salt=salt)[1]
+
+
class UserSocialAuth(models.Model):
"""Social Auth association model"""
user = models.ForeignKey(User, related_name='social_auth')
# TODO extract common code into base objects/mixins
+import base64
from datetime import timedelta
+
+from openid.association import Association as OIDAssociation
+
from mongoengine import DictField
from mongoengine import Document
from mongoengine import IntField
return UserSocialAuth.objects.create(user=user, uid=uid, provider=provider)
+def store_association(server_url, association):
+ args = {'server_url': server_url, 'handle': association.handle}
+ try:
+ assoc = Association.objects.get(**args)
+ except Association.DoesNotExist:
+ assoc = Association(**args)
+ assoc.secret = base64.encodestring(association.secret)
+ assoc.issued = association.issued
+ assoc.lifetime = association.lifetime
+ assoc.assoc_type = association.assoc_type
+ assoc.save()
+
+
+def get_oid_associations(server_url, handle=None):
+ args = {'server_url': server_url}
+ if handle is not None:
+ args['handle'] = handle
+
+ return sorted([
+ (assoc.id,
+ OIDAssociation(assoc.handle,
+ base64.decodestring(assoc.secret),
+ assoc.issued,
+ assoc.lifetime,
+ assoc.assoc_type))
+ for assoc in Association.objects.filter(**args)
+ ], key=lambda x: x[1].issued, reverse=True)
+
+
+def use_nonce(server_url, timestamp, salt):
+ return Nonce.objects.get_or_create(server_url=server_url,
+ timestamp=timestamp,
+ salt=salt)[1]
+
+
+def delete_associations(ids_to_delete):
+ Association.objects.filter(pk__in=ids_to_delete).delete()
+
+
class UserSocialAuth(Document):
"""Social Auth association model"""
user = ReferenceField(User)
import time
import base64
-from openid.association import Association as OIDAssociation
from openid.store.interface import OpenIDStore
from openid.store.nonce import SKEW
-from social_auth.models import Association, Nonce
+from social_auth.models import delete_associations
+from social_auth.models import get_oid_associations
+from social_auth.models import store_association
+from social_auth.models import use_nonce
class DjangoOpenIDStore(OpenIDStore):
def storeAssociation(self, server_url, association):
"""Store new assocition if doesn't exist"""
- args = {'server_url': server_url, 'handle': association.handle}
- try:
- assoc = Association.objects.get(**args)
- except Association.DoesNotExist:
- assoc = Association(**args)
- assoc.secret = base64.encodestring(association.secret)
- assoc.issued = association.issued
- assoc.lifetime = association.lifetime
- assoc.assoc_type = association.assoc_type
- assoc.save()
+ store_association(server_url, association)
def getAssociation(self, server_url, handle=None):
"""Return stored assocition"""
- args = {'server_url': server_url}
- if handle is not None:
- args['handle'] = handle
-
- associations, expired = [], []
- for assoc in Association.objects.filter(**args):
- association = OIDAssociation(assoc.handle,
- base64.decodestring(assoc.secret),
- assoc.issued,
- assoc.lifetime,
- assoc.assoc_type)
- if association.getExpiresIn() == 0:
- expired.append(assoc.id)
- else:
- associations.append(association)
+ oid_associations = get_oid_associations(server_url, handle)
+ associations = [association
+ for assoc_id, association in oid_associations
+ if association.getExpiresIn() > 0]
+ expired = [assoc_id for assoc_id, association in oid_associations
+ if association.getExpiresIn() == 0]
if expired: # clear expired associations
- Association.objects.filter(pk__in=expired).delete()
+ delete_associations(expired)
if associations: # return most recet association
- associations.sort(key=lambda x: x.issued, reverse=True)
return associations[0]
def useNonce(self, server_url, timestamp, salt):
"""Generate one use number and return *if* it was created"""
if abs(timestamp - time.time()) > SKEW:
return False
- return Nonce.objects.get_or_create(server_url=server_url,
- timestamp=timestamp,
- salt=salt)[1]
+ return use_nonce(server_url, timestamp, salt)