]> git.parisson.com Git - django-social-auth.git/commitdiff
Code improves and simplifications to dynamic models loading. Refs #370
authorMatías Aguirre <matiasaguirre@gmail.com>
Tue, 3 Jul 2012 02:13:47 +0000 (23:13 -0300)
committerMatías Aguirre <matiasaguirre@gmail.com>
Tue, 3 Jul 2012 02:13:47 +0000 (23:13 -0300)
16 files changed:
social_auth/admin.py
social_auth/backends/__init__.py
social_auth/backends/pipeline/associate.py
social_auth/backends/pipeline/social.py
social_auth/backends/pipeline/user.py
social_auth/backends/utils.py
social_auth/conf.py [deleted file]
social_auth/context_processors.py
social_auth/db/__init__.py [new file with mode: 0644]
social_auth/db/base.py [new file with mode: 0644]
social_auth/db/django_models.py [new file with mode: 0644]
social_auth/db/mongoengine_models.py [new file with mode: 0644]
social_auth/django_models.py [deleted file]
social_auth/models.py
social_auth/mongoengine_models.py [deleted file]
social_auth/store.py

index fad8d78b25f15970aa74d86c70f3838c213d4225..3386abe279f19b17ccfce6cb1552aa7cd0b97bed 100644 (file)
@@ -1,16 +1,11 @@
 """Admin settings"""
+from social_auth.utils import setting
 
 
-from social_auth import conf
-
-
-if conf.get_models_module().NAME == 'django_models':
-
+if setting('SOCIAL_AUTH_MODELS') in (None, 'social_auth.db.django_models'):
     from django.contrib import admin
-
     from social_auth.models import UserSocialAuth, Nonce, Association
 
-
     class UserSocialAuthOption(admin.ModelAdmin):
         """Social Auth user options"""
         list_display = ('id', 'user', 'provider', 'uid')
@@ -19,20 +14,17 @@ if conf.get_models_module().NAME == 'django_models':
         raw_id_fields = ('user',)
         list_select_related = True
 
-
     class NonceOption(admin.ModelAdmin):
         """Nonce options"""
         list_display = ('id', 'server_url', 'timestamp', 'salt')
         search_fields = ('server_url',)
 
-
     class AssociationOption(admin.ModelAdmin):
         """Association options"""
         list_display = ('id', 'server_url', 'assoc_type')
         list_filter = ('assoc_type',)
         search_fields = ('server_url',)
 
-
     admin.site.register(UserSocialAuth, UserSocialAuthOption)
     admin.site.register(Nonce, NonceOption)
     admin.site.register(Association, AssociationOption)
index bb6b3e6c8516d64beafe3660c862b795bf1b08f8..5acc43b26a25e4c68f99bf80e2a2cda1b3b646ce 100644 (file)
@@ -24,8 +24,7 @@ from django.contrib.auth.backends import ModelBackend
 from django.utils import simplejson
 from django.utils.importlib import import_module
 
-from social_auth.models import get_social_auth_for_user
-from social_auth.models import get_user
+from social_auth.models import UserSocialAuth
 from social_auth.utils import setting, log, model_to_ctype, ctype_to_model, \
                               clean_partial_pipeline
 from social_auth.store import DjangoOpenIDStore
@@ -186,11 +185,10 @@ class SocialAuthBackend(ModelBackend):
             return {}
 
     def get_user(self, user_id):
-        
         """
         Return user with given ID from the User model used by this backend
         """
-        return get_user(user_id)
+        return UserSocialAuth.get_user(user_id)
 
 
 class OAuthBackend(SocialAuthBackend):
@@ -405,9 +403,11 @@ class BaseAuth(object):
         Override if extra operations are needed.
         """
         if association_id:
-            get_social_auth_for_user(user).get(id=association_id).delete()
+            UserSocialAuth.get_social_auth_for_user(user)\
+                            .get(id=association_id).delete()
         else:
-            get_social_auth_for_user(user).filter(provider=self.AUTH_BACKEND.name).delete()
+            UserSocialAuth.get_social_auth_for_user(user)\
+                            .filter(provider=self.AUTH_BACKEND.name).delete()
 
     def build_absolute_uri(self, path=None):
         """Build absolute URI for given path. Replace http:// schema with
index 225844b1d6f5d1794731c4bd3e787069a074f815..493cc50335c949f29d791359a7e9d21ef9b0f9c8 100644 (file)
@@ -1,5 +1,7 @@
+from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
+
 from social_auth.utils import setting
-from social_auth.models import get_user_by_email
+from social_auth.models import UserSocialAuth
 from social_auth.backends.pipeline import warn_setting
 from social_auth.backends.exceptions import AuthException
 
@@ -15,8 +17,8 @@ def associate_by_email(details, *args, **kwargs):
         # only if it's a single object. AuthException is raised if multiple
         # objects are returned
         try:
-            return {'user': get_user_by_email(email=email)}
-        except User.MultipleObjectsReturned:
+            return {'user': UserSocialAuth.get_user_by_email(email=email)}
+        except MultipleObjectsReturned:
             raise AuthException(kwargs['backend'], 'Not unique email address.')
-        except User.DoesNotExist:
+        except ObjectDoesNotExist:
             pass
index 624fda8df277deaae0ddb86aaa307f8c79301c1b..2b4c08543ae7f59927a33e08c7285ffa11e16957 100644 (file)
@@ -1,8 +1,7 @@
 from django.db.utils import IntegrityError
 
 from social_auth.utils import setting
-from social_auth.models import create_social_auth
-from social_auth.models import get_social_auth
+from social_auth.models import UserSocialAuth
 from social_auth.backends.pipeline import warn_setting
 from social_auth.backends.exceptions import AuthException
 from django.utils.translation import ugettext
@@ -14,12 +13,11 @@ def social_auth_user(backend, uid, user=None, *args, **kwargs):
 
     Raise AuthException if UserSocialAuth entry belongs to another user.
     """
-    social_user = get_social_auth(backend.name, uid)
+    social_user = UserSocialAuth.get_social_auth(backend.name, uid)
     if social_user:
         if user and social_user.user != user:
-            raise AuthException(backend, ugettext('This %(provider)s account already in use.') % {
-                'provider':backend.name,
-            })
+            msg = ugettext('This %(provider)s account already in use.')
+            raise AuthException(backend, msg % {'provider': backend.name})
         elif not user:
             user = social_user.user
     return {'social_user': social_user, 'user': user}
@@ -31,7 +29,7 @@ def associate_user(backend, user, uid, social_user=None, *args, **kwargs):
         return None
 
     try:
-        social = create_social_auth(user, uid, backend.name)
+        social = UserSocialAuth.create_social_auth(user, uid, backend.name)
     except IntegrityError:
         # Protect for possible race condition, those bastard with FTL
         # clicking capabilities, check issue #131:
index 16eb1a334ee6943ae6bd73a0111564ebc9b45865..a9f21ddb7a7262de35255faef22af575c2f41ff6 100644 (file)
@@ -1,16 +1,15 @@
 from uuid import uuid4
 
 from social_auth.utils import setting
-from social_auth.models import create_user as create_user_in_db
-from social_auth.models import simple_user_exists
-from social_auth.models import USERNAME, USERNAME_MAX_LENGTH
+from social_auth.models import UserSocialAuth, USERNAME
 from social_auth.backends.pipeline import warn_setting
 from social_auth.signals import socialauth_not_registered, \
                                 socialauth_registered, \
                                 pre_update
 
 
-def get_username(details, user=None, user_exists=simple_user_exists,
+def get_username(details, user=None,
+                 user_exists=UserSocialAuth.simple_user_exists,
                  *args, **kwargs):
     """Return an username for new user. Return current user username
     if user was given.
@@ -37,15 +36,16 @@ def get_username(details, user=None, user_exists=simple_user_exists,
     uuid_length = setting('SOCIAL_AUTH_UUID_LENGTH', 16)
     username_fixer = setting('SOCIAL_AUTH_USERNAME_FIXER', lambda u: u)
 
-    short_username = username[:USERNAME_MAX_LENGTH - uuid_length]
-    final_username = username_fixer(username)[:USERNAME_MAX_LENGTH]
+    max_length = UserSocialAuth.username_max_length()
+    short_username = username[:max_length - uuid_length]
+    final_username = username_fixer(username)[:max_length]
 
     # Generate a unique username for current user using username
     # as base but adding a unique hash at the end. Original
     # username is cut to avoid any field max_length.
     while user_exists(username=final_username):
         username = short_username + uuid4().get_hex()[:uuid_length]
-        final_username = username_fixer(username)[:USERNAME_MAX_LENGTH]
+        final_username = username_fixer(username)[:max_length]
 
     return {'username': final_username}
 
@@ -70,7 +70,7 @@ def create_user(backend, details, response, uid, username, user=None, *args,
 
     email = details.get('email') or None
     return {
-        'user': create_user_in_db(username=username, email=email),
+        'user': UserSocialAuth.create_user(username=username, email=email),
         'is_new': True
     }
 
index 566036c429b8db59f6a0fd5b394aa524543c979c..4e9a1ba5e12087cd6d86b62ed3438d4560b2e7fb 100644 (file)
@@ -4,13 +4,13 @@ from oauth2 import Consumer as OAuthConsumer, Token, Request as OAuthRequest, \
 
 from django.utils import simplejson
 
-from social_auth.models import resolve_user_or_id
+from social_auth.models import UserSocialAuth
 
 
 def consumer_oauth_url_request(backend, url, user_or_id, redirect_uri='/',
                                json=True):
     """Builds and retrieves an OAuth signed response."""
-    user = resolve_user_or_id(user_or_id)
+    user = UserSocialAuth.resolve_user_or_id(user_or_id)
     oauth_info = user.social_auth.filter(provider=backend.AUTH_BACKEND.name)[0]
     token = Token.from_string(oauth_info.tokens['access_token'])
     request = build_consumer_oauth_request(backend, token, url, redirect_uri)
@@ -22,7 +22,8 @@ def consumer_oauth_url_request(backend, url, user_or_id, redirect_uri='/',
 
 
 def build_consumer_oauth_request(backend, token, url, redirect_uri='/',
-                                 oauth_verifier=None, extra_params=None, method=HTTP_METHOD):
+                                 oauth_verifier=None, extra_params=None,
+                                 method=HTTP_METHOD):
     """Builds a Consumer OAuth request."""
     params = {'oauth_callback': redirect_uri}
     if extra_params:
diff --git a/social_auth/conf.py b/social_auth/conf.py
deleted file mode 100644 (file)
index a3f5d88..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-"""Centralized definition of settings"""
-
-
-from django.utils import importlib
-from social_auth.utils import setting
-
-
-SOCIAL_AUTH_MODELS = setting('SOCIAL_AUTH_MODELS', 'social_auth.django_models')
-
-
-def get_models_module():
-    """Load and return the module specified by the SOCIAL_AUTH_MODELS config
-    setting.
-
-    """
-    return importlib.import_module(SOCIAL_AUTH_MODELS)
index 99c39d6699eb7c06a057723d4273efa23eeb7090..129c5b84e0d7faf618cb0e277022fcf14500bfb8 100644 (file)
@@ -1,6 +1,6 @@
+from social_auth.models import UserSocialAuth
 from social_auth.backends import get_backends
 from social_auth.utils import group_backend_by_type
-from social_auth.models import get_social_auth_for_user
 
 
 # Note: social_auth_backends, social_auth_by_type_backends and
@@ -40,7 +40,7 @@ def social_auth_by_name_backends(request):
 
     if hasattr(user, 'is_authenticated') and user.is_authenticated():
         accounts.update((assoc.provider.replace('-', '_'), assoc)
-                            for assoc in get_social_auth_for_user(user))
+                    for assoc in UserSocialAuth.get_social_auth_for_user(user))
 
     return {'social_auth': accounts}
 
@@ -65,7 +65,7 @@ def backends_data(user):
     # user comes from request.user usually, on /admin/ it will be an instance
     # of auth.User and this code will fail if a custom User model was defined
     if hasattr(user, 'is_authenticated') and user.is_authenticated():
-        associated = get_social_auth_for_user(user)
+        associated = UserSocialAuth.get_social_auth_for_user(user)
         not_associated = list(set(available) -
                               set(assoc.provider for assoc in associated))
         values['associated'] = associated
diff --git a/social_auth/db/__init__.py b/social_auth/db/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/social_auth/db/base.py b/social_auth/db/base.py
new file mode 100644 (file)
index 0000000..333d3f9
--- /dev/null
@@ -0,0 +1,160 @@
+"""Models mixins for Social Auth"""
+import base64
+from datetime import datetime
+
+from django.utils.timezone import utc
+
+from openid.association import Association as OIDAssociation
+
+from social_auth.utils import setting
+
+
+class UserSocialAuthMixin(object):
+    User = None
+    user = ''
+    provider = ''
+
+    def __unicode__(self):
+        """Return associated user unicode representation"""
+        return u'%s - %s' % (unicode(self.user), self.provider.title())
+
+    @property
+    def tokens(self):
+        """Return access_token stored in extra_data or None"""
+        # Make import here to avoid recursive imports :-/
+        from social_auth.backends import get_backends
+        backend = get_backends().get(self.provider)
+        if backend:
+            return backend.AUTH_BACKEND.tokens(self)
+        else:
+            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.
+        """
+        if self.extra_data:
+            name = setting('SOCIAL_AUTH_EXPIRATION', 'expires')
+            try:
+                return datetime.utcfromtimestamp(self.extra_data.get(name))\
+                               .replace(tzinfo=utc)
+            except (ValueError, TypeError):
+                pass
+        return None
+
+    @classmethod
+    def username_max_length(cls):
+        raise NotImplementedError('Implement in subclass')
+
+    @classmethod
+    def simple_user_exists(cls, *args, **kwargs):
+        """
+        Return True/False if a User instance exists with the given arguments.
+        Arguments are directly passed to filter() manager method.
+        """
+        return cls.User.objects.filter(*args, **kwargs).count() > 0
+
+    @classmethod
+    def create_user(cls, *args, **kwargs):
+        return cls.User.objects.create(*args, **kwargs)
+
+    @classmethod
+    def get_user(cls, pk):
+        try:
+            return cls.User.objects.get(pk=pk)
+        except cls.User.DoesNotExist:
+            return None
+
+    @classmethod
+    def get_user_by_email(cls, email):
+        return cls.User.objects.get(email=email)
+
+    @classmethod
+    def resolve_user_or_id(cls, user_or_id):
+        if isinstance(user_or_id, cls.User):
+            return user_or_id
+        return cls.User.objects.get(pk=user_or_id)
+
+    @classmethod
+    def get_social_auth(cls, provider, uid):
+        try:
+            return cls.objects.get(provider=provider, uid=uid)
+        except cls.DoesNotExist:
+            return None
+
+    @classmethod
+    def get_social_auth_for_user(cls, user):
+        return user.social_auth.all()
+
+    @classmethod
+    def create_social_auth(cls, user, uid, provider):
+        return cls.objects.create(user=user, uid=uid, provider=provider)
+
+    @classmethod
+    def store_association(cls, server_url, association):
+        from social_auth.models import 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()
+
+    @classmethod
+    def get_oid_associations(cls, server_url, handle=None):
+        from social_auth.models import Association
+        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)
+
+    @classmethod
+    def delete_associations(cls, ids_to_delete):
+        from social_auth.models import Association
+        Association.objects.filter(pk__in=ids_to_delete).delete()
+
+    @classmethod
+    def use_nonce(cls, server_url, timestamp, salt):
+        from social_auth.models import Nonce
+        return Nonce.objects.get_or_create(server_url=server_url,
+                                           timestamp=timestamp,
+                                           salt=salt)[1]
+
+
+class NonceMixin(object):
+    """One use numbers"""
+    server_url = ''
+    timestamp = 0
+    salt = ''
+
+    def __unicode__(self):
+        """Unicode representation"""
+        return self.server_url
+
+
+class AssociationMixin(object):
+    """OpenId account association"""
+    server_url = ''
+    handle = ''
+    secret = ''
+    issued = 0
+    lifetime = 0
+    assoc_type = ''
+
+    def __unicode__(self):
+        """Unicode representation"""
+        return '%s %s' % (self.handle, self.issued)
diff --git a/social_auth/db/django_models.py b/social_auth/db/django_models.py
new file mode 100644 (file)
index 0000000..df89f8d
--- /dev/null
@@ -0,0 +1,75 @@
+"""Django ORM models for Social Auth"""
+from django.db import models
+
+from social_auth.db.base import UserSocialAuthMixin, AssociationMixin, \
+                                NonceMixin
+from social_auth.fields import JSONField
+from social_auth.utils import setting
+
+
+# If User class is overridden, it *must* provide the following fields
+# and methods work with django-social-auth:
+#
+#   username   = CharField()
+#   last_login = DateTimeField()
+#   is_active  = BooleanField()
+#   def is_authenticated():
+#       ...
+if setting('SOCIAL_AUTH_USER_MODEL'):
+    UserModel = models.get_model(*setting('SOCIAL_AUTH_USER_MODEL')\
+                                    .rsplit('.', 1))
+else:
+    from django.contrib.auth.models import User as UserModel
+
+
+# TODO make this a complementary config setting to SOCIAL_AUTH_USER_MODEL
+USERNAME = 'username'
+
+
+class UserSocialAuth(models.Model, UserSocialAuthMixin):
+    """Social Auth association model"""
+    User = UserModel
+    user = models.ForeignKey(UserModel, related_name='social_auth')
+    provider = models.CharField(max_length=32)
+    uid = models.CharField(max_length=255)
+    extra_data = JSONField(default='{}')
+
+    class Meta:
+        """Meta data"""
+        unique_together = ('provider', 'uid')
+        app_label = 'social_auth'
+
+    @classmethod
+    def create_user(cls, *args, **kwargs):
+        return cls.User.objects.create_user(*args, **kwargs)
+
+    @classmethod
+    def get_social_auth(cls, provider, uid):
+        try:
+            return cls.objects.select_related('user').get(provider=provider,
+                                                          uid=uid)
+        except UserSocialAuth.DoesNotExist:
+            return None
+
+
+class Nonce(models.Model, NonceMixin):
+    """One use numbers"""
+    server_url = models.CharField(max_length=255)
+    timestamp = models.IntegerField()
+    salt = models.CharField(max_length=40)
+
+    class Meta:
+        app_label = 'social_auth'
+
+
+class Association(models.Model, AssociationMixin):
+    """OpenId account association"""
+    server_url = models.CharField(max_length=255)
+    handle = models.CharField(max_length=255)
+    secret = models.CharField(max_length=255)  # Stored base64 encoded
+    issued = models.IntegerField()
+    lifetime = models.IntegerField()
+    assoc_type = models.CharField(max_length=64)
+
+    class Meta:
+        app_label = 'social_auth'
diff --git a/social_auth/db/mongoengine_models.py b/social_auth/db/mongoengine_models.py
new file mode 100644 (file)
index 0000000..ec179b4
--- /dev/null
@@ -0,0 +1,50 @@
+"""
+MongoEngine models for Social Auth
+
+Requires MongoEngine 0.6.10
+"""
+from mongoengine import DictField, Document, IntField, ReferenceField, \
+                        StringField
+from mongoengine.django.auth import User
+
+from social_auth.db.base import UserSocialAuthMixin, AssociationMixin, \
+                                NonceMixin
+
+
+# TODO make this a complementary config setting to SOCIAL_AUTH_USER_MODEL
+USERNAME = 'username'
+
+
+class UserSocialAuth(Document, UserSocialAuthMixin):
+    """Social Auth association model"""
+    user = ReferenceField(User)
+    provider = StringField(max_length=32)
+    uid = StringField(max_length=255, unique_with='provider')
+    extra_data = DictField()
+
+    @classmethod
+    def get_social_auth_for_user(cls, user):
+        return cls.objects(user=user)
+
+    @classmethod
+    def create_social_auth(cls, user, uid, provider):
+        if not isinstance(type(uid), basestring):
+            uid = str(uid)
+        return cls.objects.create(user=user, uid=uid, provider=provider)
+
+
+class Nonce(Document, NonceMixin):
+    """One use numbers"""
+    server_url = StringField(max_length=255)
+    timestamp = IntField()
+    salt = StringField(max_length=40)
+
+
+class Association(Document, AssociationMixin):
+    """OpenId account association"""
+    server_url = StringField(max_length=255)
+    handle = StringField(max_length=255)
+    secret = StringField(max_length=255)  # Stored base64 encoded
+    issued = IntField()
+    lifetime = IntField()
+    assoc_type = StringField(max_length=64)
diff --git a/social_auth/django_models.py b/social_auth/django_models.py
deleted file mode 100644 (file)
index 122aeb6..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-"""Django ORM models for Social Auth"""
-import base64
-from datetime import datetime
-
-from django.db import models
-from django.utils.timezone import utc
-
-from openid.association import Association as OIDAssociation
-
-from social_auth.fields import JSONField
-from social_auth.utils import setting
-
-
-NAME = 'django_models'
-
-
-# If User class is overridden, it *must* provide the following fields
-# and methods work with django-social-auth:
-#
-#   username   = CharField()
-#   last_login = DateTimeField()
-#   is_active  = BooleanField()
-#   def is_authenticated():
-#       ...
-
-if setting('SOCIAL_AUTH_USER_MODEL'):
-    User = models.get_model(*setting('SOCIAL_AUTH_USER_MODEL').rsplit('.', 1))
-else:
-    from django.contrib.auth.models import User
-
-
-# TODO make this a complementary config setting to SOCIAL_AUTH_USER_MODEL
-USERNAME = 'username'
-USERNAME_MAX_LENGTH = User._meta.get_field(USERNAME).max_length
-
-
-def simple_user_exists(*args, **kwargs):
-    """Return True/False if a User instance exists with the given arguments.
-    Arguments are directly passed to filter() manager method."""
-    return User.objects.filter(*args, **kwargs).exists()
-
-
-def create_user(*args, **kwargs):
-    return User.objects.create_user(*args, **kwargs)
-
-
-def get_user(user_id):
-    try:
-        return User.objects.get(id=user_id)
-    except User.DoesNotExist:
-        return None
-
-
-def get_user_by_email(email):
-    return User.objects.get(email=email)
-
-
-def resolve_user_or_id(user_or_id):
-    if isinstance(user_or_id, User):
-       return user_or_id
-    return User.objects.get(pk=user_or_id)
-
-
-def get_social_auth(provider, uid):
-    try:
-        return UserSocialAuth.objects.select_related('user').get(
-                provider=provider, uid=uid)
-    except UserSocialAuth.DoesNotExist:
-        return None
-
-
-def get_social_auth_for_user(user):
-    return user.social_auth.all()
-
-
-def create_social_auth(user, uid, provider):
-    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')
-    provider = models.CharField(max_length=32)
-    uid = models.CharField(max_length=255)
-    extra_data = JSONField(default='{}')
-
-    class Meta:
-        """Meta data"""
-        unique_together = ('provider', 'uid')
-        app_label = 'social_auth'
-
-    def __unicode__(self):
-        """Return associated user unicode representation"""
-        return u'%s - %s' % (unicode(self.user), self.provider.title())
-
-    @property
-    def tokens(self):
-        """Return access_token stored in extra_data or None"""
-        # Make import here to avoid recursive imports :-/
-        from social_auth.backends import get_backends
-        backend = get_backends().get(self.provider)
-        if backend:
-            return backend.AUTH_BACKEND.tokens(self)
-        else:
-            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.
-        """
-        if self.extra_data:
-            name = setting('SOCIAL_AUTH_EXPIRATION', 'expires')
-            try:
-                return datetime.utcfromtimestamp(self.extra_data.get(name))\
-                               .replace(tzinfo=utc)
-            except (ValueError, TypeError):
-                pass
-        return None
-
-
-class Nonce(models.Model):
-    """One use numbers"""
-    server_url = models.CharField(max_length=255)
-    timestamp = models.IntegerField()
-    salt = models.CharField(max_length=40)
-
-    class Meta:
-        app_label = 'social_auth'
-
-    def __unicode__(self):
-        """Unicode representation"""
-        return self.server_url
-
-
-class Association(models.Model):
-    """OpenId account association"""
-    server_url = models.CharField(max_length=255)
-    handle = models.CharField(max_length=255)
-    secret = models.CharField(max_length=255)  # Stored base64 encoded
-    issued = models.IntegerField()
-    lifetime = models.IntegerField()
-    assoc_type = models.CharField(max_length=64)
-
-    class Meta:
-        app_label = 'social_auth'
-
-    def __unicode__(self):
-        """Unicode representation"""
-        return '%s %s' % (self.handle, self.issued)
index 144a125a07db4b4faed8a516a90803670fe81f42..64293f8708f89e38ce7ee07384f3bd0525c4bbf5 100644 (file)
@@ -1,11 +1,11 @@
 """Social auth models"""
-# TODO define protocol for implementing modules...
+from django.utils.importlib import import_module
 
-from social_auth import conf
+from social_auth.utils import setting
 
 
-models_module = conf.get_models_module()
+SOCIAL_AUTH_MODELS_MODULE = import_module(setting('SOCIAL_AUTH_MODELS',
+                                               'social_auth.db.django_models'))
 
-this_module = globals()
-for key in dir(models_module):
-    this_module[key] = getattr(models_module, key)
+globals().update((name, getattr(SOCIAL_AUTH_MODELS_MODULE, name))
+                    for name in dir(SOCIAL_AUTH_MODELS_MODULE))
diff --git a/social_auth/mongoengine_models.py b/social_auth/mongoengine_models.py
deleted file mode 100644 (file)
index 89c01d1..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-"""MongoEngine models for Social Auth
-
-Requires MongoEngine 0.6.10
-
-"""
-# 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
-from mongoengine import ReferenceField
-from mongoengine import StringField
-from social_auth.utils import setting
-
-
-NAME = 'mongoengine_models'
-
-
-# If User class is overridden, it *must* provide the following fields
-# and methods work with django-social-auth:
-#
-#   username   = CharField()
-#   last_login = DateTimeField()
-#   is_active  = BooleanField()
-#   def is_authenticated():
-#       ...
-
-if setting('SOCIAL_AUTH_USER_MODEL'):
-    User = models.get_model(*setting('SOCIAL_AUTH_USER_MODEL').rsplit('.', 1))
-else:
-    from mongoengine.django.auth import User
-
-
-# TODO make this a complementary config setting to SOCIAL_AUTH_USER_MODEL
-USERNAME = 'username'
-USERNAME_MAX_LENGTH = getattr(User, USERNAME).max_length
-
-
-def simple_user_exists(*args, **kwargs):
-    """Return True/False if a User instance exists with the given arguments.
-    Arguments are directly passed to filter() manager method."""
-    return User.objects.filter(*args, **kwargs).count()
-
-
-def create_user(*args, **kwargs):
-    return User.objects.create(*args, **kwargs)
-
-
-def get_user(user_id):
-    try:
-        return User.objects.get(id=user_id)
-    except User.DoesNotExist:
-        return None
-
-
-def get_user_by_email(email):
-    return User.objects.get(email=email)
-
-
-def resolve_user_or_id(user_or_id):
-    if isinstance(user_or_id, User):
-       return user_or_id
-    return User.objects.get(pk=user_or_id)
-
-
-def get_social_auth(provider, uid):
-    try:
-        return UserSocialAuth.objects.get(provider=provider, uid=uid)
-    except UserSocialAuth.DoesNotExist:
-        return None
-
-
-def get_social_auth_for_user(user):
-    return UserSocialAuth.objects(user=user)
-
-
-def create_social_auth(user, uid, provider):
-    if type(uid) is not str:
-        uid = str(uid)
-    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)
-    provider = StringField(max_length=32)
-    uid = StringField(max_length=255, unique_with='provider')
-    extra_data = DictField()
-
-    def __unicode__(self):
-        """Return associated user unicode representation"""
-        return u'%s - %s' % (unicode(self.user), self.provider)
-
-    @property
-    def tokens(self):
-        """Return access_token stored in extra_data or None"""
-        # Make import here to avoid recursive imports :-/
-        from social_auth.backends import get_backends
-        backend = get_backends().get(self.provider)
-        if backend:
-            return backend.AUTH_BACKEND.tokens(self)
-        else:
-            return {}
-
-    def expiration_delta(self):
-        """Return saved session expiration seconds if any. Is returned in
-        the form of a timedelta data type. None is returned if there's no
-        value stored or it's malformed.
-        """
-        if self.extra_data:
-            name = setting('SOCIAL_AUTH_EXPIRATION', 'expires')
-            try:
-                return timedelta(seconds=int(self.extra_data.get(name)))
-            except (ValueError, TypeError):
-                pass
-        return None
-
-
-class Nonce(Document):
-    """One use numbers"""
-    server_url = StringField(max_length=255)
-    timestamp = IntField()
-    salt = StringField(max_length=40)
-
-    def __unicode__(self):
-        """Unicode representation"""
-        return self.server_url
-
-
-class Association(Document):
-    """OpenId account association"""
-    server_url = StringField(max_length=255)
-    handle = StringField(max_length=255)
-    secret = StringField(max_length=255)  # Stored base64 encoded
-    issued = IntField()
-    lifetime = IntField()
-    assoc_type = StringField(max_length=64)
-
-    def __unicode__(self):
-        """Unicode representation"""
-        return '%s %s' % (self.handle, self.issued)
index e4fcd0925034ed49282d2c9624882344fa6177ec..22f120904f34455eb319f84e2ab4fbe6cb241bb9 100644 (file)
@@ -1,14 +1,10 @@
 """OpenId storage that saves to django models"""
 import time
-import base64
 
 from openid.store.interface import OpenIDStore
 from openid.store.nonce import SKEW
 
-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
+from social_auth.models import UserSocialAuth
 
 
 class DjangoOpenIDStore(OpenIDStore):
@@ -20,11 +16,12 @@ class DjangoOpenIDStore(OpenIDStore):
 
     def storeAssociation(self, server_url, association):
         """Store new assocition if doesn't exist"""
-        store_association(server_url, association)
+        UserSocialAuth.store_association(server_url, association)
 
     def getAssociation(self, server_url, handle=None):
         """Return stored assocition"""
-        oid_associations = get_oid_associations(server_url, handle)
+        oid_associations = UserSocialAuth.get_oid_associations(server_url,
+                                                               handle)
         associations = [association
                         for assoc_id, association in oid_associations
                         if association.getExpiresIn() > 0]
@@ -32,7 +29,7 @@ class DjangoOpenIDStore(OpenIDStore):
                    if association.getExpiresIn() == 0]
 
         if expired:  # clear expired associations
-            delete_associations(expired)
+            UserSocialAuth.delete_associations(expired)
 
         if associations:  # return most recet association
             return associations[0]
@@ -41,4 +38,4 @@ class DjangoOpenIDStore(OpenIDStore):
         """Generate one use number and return *if* it was created"""
         if abs(timestamp - time.time()) > SKEW:
             return False
-        return use_nonce(server_url, timestamp, salt)
+        return UserSocialAuth.use_nonce(server_url, timestamp, salt)