django-publicauth / publicauth / backends /

from django.shortcuts import render_to_response, redirect
from django.conf import settings as global_settings
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from django.template import RequestContext
from django.contrib import messages
from django.contrib import auth
from django.http import Http404

from annoying.exceptions import Redirect

from publicauth.models import PublicID
from publicauth.utils import str_to_class
from publicauth import settings
from publicauth import lang

class BaseBackend(object):

    PROFILE_MAPPING = property(lambda self: getattr(global_settings, "%s_PROFILE_MAPPING" % self.provider.upper(), {}))
    EXTRA_FORM = property(lambda self: getattr(global_settings, "%s_EXTRA_FORM" % self.provider.upper(), 'publicauth.forms.ExtraForm'))

    def __init__(self, provider):
        self.provider = provider
        self._identity = None

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

    def get_identity(self):
        return self._identity

    def begin(self, request, data):
        raise NotImplementedError

    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.
        raise NotImplementedError
    def attach_account(self, request, user):
        Attach PublicID account to regular django 
        account and then login user.
        PublicID.objects.create(user=user, identity=self.get_identity(), provider=self.provider)
        messages.add_message(request, messages.SUCCESS, lang.ACCOUNTS_MERGED)
        auth.authenticate(identity=self.get_identity(), provider=self.provider)
        auth.login(request, user)
        raise Redirect(global_settings.LOGIN_REDIRECT_URL)

    def login_user(self, request):
        if settings.PUBLICID_ACTIVATION_REQUIRED and not request.user.is_active:
            messages.add_message(request, messages.ERROR, lang.NOT_ACTIVATED)
            raise Redirect("/")

        user = auth.authenticate(identity=self.get_identity(), provider=self.provider)
        if user:
            messages.add_message(request, messages.SUCCESS, lang.SUCCESSFULLY_AUTHENTICATED)
            auth.login(request, user)
            raise Redirect(global_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(self.EXTRA_FORM)(data, fields=self.PROFILE_MAPPING)
        if form.is_valid():
  , 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']
                except KeyError:
                    redirect_url = global_settings.LOGIN_REDIRECT_URL
                raise Redirect(redirect_url)
            return data

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

    def validate_response(self, request):

    def extra(self, request):
        Handle registration of new user with extra data for profile
            identity = request.session['identity']
        except KeyError:
            raise Http404

        if request.method == "POST":
            form = str_to_class(self.EXTRA_FORM)(request.POST)
            if form.is_valid():
                user =, self.provider)
                del request.session['identity']
                user = auth.authenticate(identity=identity, provider=self.provider)
                if user:
                    auth.login(request, user)
                    next_url = request.session['next_url']
                    del request.session['next_url']
                    return redirect(next_url)
            initial = request.session['extra']
            form = str_to_class(self.EXTRA_FORM)(initial=initial)

        return render_to_response(     
                                    {'form': form},