"""
MongoEngine models for Social Auth

Requires MongoEngine 0.6.10
"""
try:
    from django.contrib.auth.hashers import UNUSABLE_PASSWORD
    _ = UNUSABLE_PASSWORD  # to quiet flake
except (ImportError, AttributeError):
    UNUSABLE_PASSWORD = '!'

from mongoengine import DictField, Document, IntField, ReferenceField, \
                        StringField
from mongoengine.django.auth import User
from mongoengine.queryset import OperationError

from social_auth.db.base import UserSocialAuthMixin, AssociationMixin, \
                                NonceMixin


class UserSocialAuth(Document, UserSocialAuthMixin):
    """Social Auth association model"""
    user = ReferenceField(User, dbref=True)
    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)

    @classmethod
    def username_max_length(cls):
        return UserSocialAuth.user_model().username.max_length

    @classmethod
    def email_max_length(cls):
        return UserSocialAuth.user_model().email.max_length

    @classmethod
    def user_model(cls):
        return User

    @classmethod
    def create_user(cls, *args, **kwargs):
        # Empty string makes email regex validation fail
        if kwargs.get('email') == '':
            kwargs['email'] = None
        kwargs.setdefault('password', UNUSABLE_PASSWORD)
        return cls.user_model().create_user(*args, **kwargs)

    @classmethod
    def allowed_to_disconnect(cls, user, backend_name, association_id=None):
        if association_id is not None:
            qs = cls.objects.filter(id__ne=association_id)
        else:
            qs = cls.objects.filter(provider__ne=backend_name)
        qs = qs.filter(user=user)

        if hasattr(user, 'has_usable_password'):
            valid_password = user.has_usable_password()
        else:
            valid_password = True

        return valid_password or qs.count() > 0


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)


def is_integrity_error(exc):
    return exc.__class__ is OperationError and 'E11000' in exc.message

@@ -243,16 +243,66 @@
  = '!'%0A%0A
+from django.utils.importlib import import_module%0A%0A
 from mon
@@ -406,49 +406,8 @@
 eld%0A
-from mongoengine.django.auth import User%0A
 from
@@ -451,16 +451,54 @@
 nError%0A%0A
+from social_auth.utils import setting%0A
 from soc
@@ -607,16 +607,256 @@
 Mixin%0A%0A%0A
+USER_MODEL_MODULE, USER_MODEL_NAME = (%0A    setting('SOCIAL_AUTH_USER_MODEL') or%0A    setting('AUTH_USER_MODEL') or%0A    'mongoengine.django.auth.User'%0A).rsplit('.', 1)%0AUSER_MODEL = getattr(import_module(USER_MODEL_MODULE), USER_MODEL_NAME)%0A%0A%0A
 class Us
@@ -967,19 +967,25 @@
 eField(U
-ser
+SER_MODEL
 , dbref=
@@ -1729,19 +1729,25 @@
 return U
-ser
+SER_MODEL
 %0A%0A    @c

Allow custom user support for mongoengine backends