Source

django-publicauth / openauth / backends / __init__.py

from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from django.contrib import auth
from django.conf import settings as global_settings
from django import forms

from annoying.exceptions import Redirect

from openauth.models import SocialID
from openauth.utils import str_to_class
from openauth import settings


class BaseBackend(forms.Form):

    PROFILE_MAPPING = property(lambda self: getattr(global_settings, "%s_PROFILE_MAPPING" % self.provider.upper(), {}))

    def __init__(self, *args, **kwargs):
        self._identity = None
        self.request = kwargs.pop('request', {})
        self.provider = kwargs.pop('provider', None)
        super(BaseBackend, self).__init__(*args, **kwargs)

    def set_identity(self, identity):
        self._identity = identity

    def get_identity(self):
        return self._identity

    def complete(self, request):
        """
        Login user if its identity already exists,
        Create new user in case that no extra fields are required
        and user with such identity doesnt exists.
        Merge accounts if user already logged in and identity is new.
        """
        pass
    
    def attach_account(self, request, user):
        """
        Attach SocialID account to regular django 
        account and then login user.
        """
        SocialID.objects.create(user=user, identity=self.get_identity(), provider=self.provider)
        request.flash['success'] =  _('OpenId record was added to your account')
        auth.authenticate(identity=self.get_identity(), provider=self.provider)
        auth.login(request, user)
        raise Redirect(settings.LOGIN_REDIRECT_URL)

    def login_user(self, request):
        if settings.SOCIALID_ACTIVATION_REQUIRED and not request.user.is_active:
            request.flash['error'] =  _('Your account is not activated. Please activate it first.')
            raise Redirect("/")
        user = auth.authenticate(identity=self.get_identity(), provider=self.provider)
        if user:
            request.flash['success'] =  _('You have successfully authenticated')
            auth.login(request, user)
            raise Redirect(settings.LOGIN_REDIRECT_URL)

    def set_profile_fields(self, request, extra):
        """
        Try to fetch extra data from provider, if this data is enough
        to validate EXTRA_FORM then call save method of form class and 
        login user.
        """
        data = {}

        for field in self.PROFILE_MAPPING:
            data.update(self.extract_data(extra, field))

        form = str_to_class(settings.SOCIALID_EXTRA_FORM)(data, fields=self.PROFILE_MAPPING)
        if form.is_valid():
            form.save(self.get_identity(), self.provider)
            user = auth.authenticate(identity=self.get_identity(), provider=self.provider)
            if user:
                auth.login(request, user)
                redirect_url = request.session['next_url']
                del request.session['next_url']
                raise Redirect(redirect_url)
        else:
            return data

    def extract_data(self, data, field):
        try:
            return {self.PROFILE_MAPPING[field][0]: data.get(field, '')}
        except AttributeError:
            return {self.PROFILE_MAPPING[field][0]: ''}

    def validate_response(self, request):
        pass