offline avatar offline committed 5ab638f

openauth2 initial code

Comments (0)

Files changed (20)

openauth/__init__.py

+from django.contrib.auth.models import User
+
+from openauth.models import SocialID
 from openauth import signals
 from openauth import settings
 from openauth import lang
+
+
+class SocialBackend(object):
+    """
+    Add this Authentication Backend to 
+    AUTHENTICATION_BACKENDS tuple in your settings.py
+    """
+
+    def get_user(self, user_id):
+        try:
+            return User.objects.get(pk=user_id)
+        except User.DoesNotExist:
+            return None
+
+    def authenticate(self, identity=None, provider="basic"):
+        """
+        Authenticate user by social identity.
+        """
+        if identity:
+            try:
+                user = SocialID.objects.get(identity=identity, provider=provider).user
+                return user
+            except SocialID.DoesNotExist:
+                return None
+        else:
+            return None

openauth/admin.py

 from django.contrib import admin
 
-from openauth.models import OpenID
+from openauth.models import SocialID
 
 
-class OpenIDAdmin(admin.ModelAdmin):
-    list_display = ['user', 'url']
+class SocialIDAdmin(admin.ModelAdmin):
+    list_display = ['user', 'provider', 'identity']
 
-admin.site.register(OpenID, OpenIDAdmin)
+admin.site.register(SocialID, SocialIDAdmin)
 

openauth/backends.py

-from django.contrib.auth.models import User
-
-from openauth.models import OpenID
-
-
-class OpenIDBackend(object):
-    """
-    Don't forget to add this backend to the 
-    AUTHENTICATION_BACKENDS settins of your project
-    if you need OpenID authentication.
-    """
-    def authenticate(self, openid_url=None):
-        """
-        Authenticate user by OpenId url or email in case of gmail or yahoo.
-        """
-        if openid_url:
-            try:
-                user = OpenID.objects.get(url=openid_url).user
-                return user
-            except OpenID.DoesNotExist:
-                return None
-        else:
-            return None
-
-    def get_user(self, user_id):
-        try:
-            return User.objects.get(pk=user_id)
-        except User.DoesNotExist:
-            return None
-

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 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):
+
+    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.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 = {}
+        if extra:
+            for field in getattr(settings, "%s_EXTRA_FIELDS" % self.provider.upper()):
+                if self._have_profile_name(field):
+                    profile_field = self._get_profile_field_name(field)
+                    data.update(self.extract_data(extra, profile_field, field))
+
+        form = str_to_class(settings.SOCIALID_EXTRA_FORM)(data)
+        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, profile_field, field):
+        return {profile_field: data.get(field, '')}
+
+    def _have_extra_fields(self): 
+        pass
+
+    def _have_profile_name(self, field):
+        return field in getattr(settings, "%s_PROFILE_MAPPING" % self.provider.upper())
+
+    def _get_profile_field_name(self, field):
+        mapping = getattr(settings,"%s_PROFILE_MAPPING" % self.provider.upper())
+        return mapping[field]
+
+    def validate_response(self, request):
+        pass

openauth/backends/facebook.py

+from __future__ import absolute_import 
+
+from django.utils.translation import ugettext as _
+from django.contrib import auth
+
+from annoying.exceptions import Redirect
+
+from openauth.backends import BaseBackend
+from openauth import settings
+
+
+class FacebookBackend(BaseBackend):
+    
+    def validate_response(self, request):
+        if not request.facebook.validate_cookie_signature(request.COOKIES):
+            request.flash['error'] = _('Invalid response received from facebook server, please start the authentication process again')
+            raise Redirect('openauth-social-login')
+        else:
+            uid = request.facebook.api_key
+            self.set_identity(int(request.COOKIES.get('%s_user' % uid)))
+
+    def complete(self, request, response):
+        extra = request.facebook.users.getInfo([self.get_identity()], settings.FACEBOOK_EXTRA_FIELDS)[0]
+        self.set_profile_fields(request, extra)
+
+        request.session['identity'] = self.get_identity()
+
+        raise Redirect('openauth-social-extra', 'facebook')
+

openauth/backends/google.py

+from __future__ import absolute_import
+
+from openid.extensions.ax import FetchRequest, AttrInfo, FetchResponse
+
+from openauth.backends.openid import OpenIDBackend
+from openauth import settings
+
+
+class GoogleBackend(OpenIDBackend):
+    
+    def get_extra_data(self, resp):
+        return FetchResponse.fromSuccessResponse(resp)
+
+    def extract_data(self, data, profile_field, field):
+        return {profile_field: data.getSingle(settings.AX_URIS[field], '')}
+

openauth/backends/openid.py

+from __future__ import absolute_import 
+
+from openid.consumer import consumer, discover
+from openid.extensions.sreg import SRegRequest, SRegResponse
+from openid.extensions.ax import FetchRequest, AttrInfo, FetchResponse
+
+from django.utils.translation import ugettext as _
+from django.core.urlresolvers import reverse
+from django.contrib import auth
+from django import forms
+
+from annoying.exceptions import Redirect
+
+from openauth.backends import BaseBackend
+from openauth.utils import str_to_class
+from openauth import settings
+
+
+class OpenIDBackend(BaseBackend):
+
+    openid_url = forms.CharField(u'OpenID URL', widget=forms.TextInput())
+
+    def clean_openid_url(self):
+        """
+        Url is stripped and http:// is added in case url doesnt begin with it.
+
+        Validate openid url, try to login user or show form error if 
+        OpenID server returned reject response or doesnt respond at all.
+        """
+        openid_url = self.cleaned_data['openid_url'].strip()
+        if not openid_url.startswith("http"):
+            openid_url = "http://%s" % openid_url
+        return_url = self.request.build_absolute_uri(reverse('openauth-social-complete', args=[self.provider]))
+        self.request.session['openid_return_to'] = return_url
+        client = consumer.Consumer(self.request.session, None)
+
+        try:
+            openid_request = client.begin(openid_url)
+            sreg = SRegRequest(required=settings.OPENID_EXTRA_FIELDS)
+            openid_request.addExtension(sreg)
+            ax_msg = FetchRequest()
+            for detail in settings.GOOGLE_EXTRA_FIELDS:
+                ax_msg.add(AttrInfo(settings.AX_URIS[detail], required=True))
+            openid_request.addExtension(ax_msg)
+
+            redirect_url = openid_request.redirectURL(realm='http://' + self.request.get_host(), return_to=return_url)
+            raise Redirect(redirect_url)
+
+        except discover.DiscoveryFailure:
+            raise forms.ValidationError(_('Could not find OpenID server'))
+
+        return openid_url
+
+
+    def validate_response(self, request):
+        """
+        Validate response from OpenID server.
+        Set identity in case of successfull validation.
+        """
+        client = consumer.Consumer(request.session, None)
+        data = request.GET.copy()
+        data.update(request.POST)
+
+        try:
+            resp = client.complete(data, request.session['openid_return_to'])
+        except KeyError:
+            request.flash['error'] = _('Invalid response received from OpenID server, please start the authentication process again')
+            raise Redirect('openauth-social-login')
+        if resp.status == consumer.CANCEL:
+            request.flash['warn'] = _('You have cancelled OpenID authentication')
+            raise Redirect('openauth-social-login')
+        elif resp.status == consumer.FAILURE:
+            request.flash['error'] =  _('OpenID authentication failed. Reason: %s') % resp.message
+            raise Redirect('openauth-social-login')
+        elif resp.status == consumer.SUCCESS:
+            self.set_identity(resp.identity_url)
+            del self.request.session['openid_return_to']
+            return resp
+
+    def complete(self, request, response):
+        extra = self.get_extra_data(response)
+        data = self.set_profile_fields(request, extra)
+        request.session['extra'] = data
+        self.request.session['identity'] = self.get_identity()
+        raise Redirect('openauth-social-extra', self.provider)
+
+    def get_extra_data(self, resp):
+        return SRegResponse.fromSuccessResponse(resp)
+

openauth/backends/twitter.py

+from __future__ import absolute_import 
+
+import urllib
+import urlparse
+
+from oauth.oauth import OAuthConsumer, OAuthToken, OAuthRequest, OAuthSignatureMethod_HMAC_SHA1
+
+from django.utils.translation import ugettext as _
+from django.core.urlresolvers import reverse
+from django.contrib.auth.models import User
+from django.contrib import auth
+
+from annoying.exceptions import Redirect
+
+from openauth import settings
+from openauth.backends import BaseBackend
+from openauth.models import SocialID
+
+
+CONSUMER_KEY = "g7ajf7OPlUzhMM9JBPk3ZQ"
+CONSUMER_SECRET = "MCKHvJquCldbTjLG3rCwyVwWhsQkaX1X8JQy83dDHQ"
+REQUEST_TOKEN_URL = "http://twitter.com/oauth/request_token"
+ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token"
+AUTHORIZE_URL = "http://twitter.com/oauth/authorize"
+
+
+class TwitterBackend(BaseBackend):
+
+    def clean(self):
+        consumer = OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
+        signature_method = OAuthSignatureMethod_HMAC_SHA1()
+        callback = self.request.build_absolute_uri(reverse('openauth-social-complete', args=[self.provider]))
+        oauth_req = OAuthRequest.from_consumer_and_token(consumer, callback=callback, http_url=REQUEST_TOKEN_URL)
+        oauth_req.sign_request(signature_method, consumer, None)
+        response = urllib.urlopen(oauth_req.to_url()).read()
+
+        token = OAuthToken.from_string(response) # instatiate token
+
+        oauth_req = OAuthRequest.from_consumer_and_token(consumer, token, http_url=AUTHORIZE_URL)
+        oauth_req.sign_request(signature_method, consumer, token)
+        raise Redirect(oauth_req.to_url())
+        
+
+    def complete(self, request, response):
+        signature_method = OAuthSignatureMethod_HMAC_SHA1()
+        data = request.GET.copy()
+        consumer = OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
+        oauth_token = data['oauth_token']
+        oauth_verifier = data['oauth_verifier']
+        oauth_req = OAuthRequest.from_consumer_and_token(consumer, http_url=ACCESS_TOKEN_URL)
+        oauth_req.set_parameter('oauth_token', oauth_token)
+        oauth_req.set_parameter('oauth_verifier', oauth_verifier)
+        oauth_req.sign_request(signature_method, consumer, None)
+        response = urllib.urlopen(oauth_req.to_url()).read()
+        self.set_identity(urlparse.parse_qs(response, keep_blank_values=False)['oauth_token'][0])
+        user = auth.authenticate(identity=self.get_identity(), provider=self.provider)
+
+        extra = self.get_extra_data(response)
+        data = self.set_profile_fields(request, extra)
+        request.session['extra'] = data
+        self.request.session['identity'] = self.get_identity()
+        raise Redirect('openauth-social-extra', self.provider)
+
+    def get_extra_data(self, response):
+        return urlparse.parse_qs(response, keep_blank_values=False)
+
+    def extract_data(self, data, profile_field, field):
+        try:
+            return {profile_field: data.get(field, '')[0]}
+        except IndexError:
+            return {profile_field: ''}
+            
+

openauth/forms.py

-from openid.consumer import consumer, discover
-from openid.extensions import sreg, ax
-
 from django import forms
 from django.contrib.auth.models import User
 from django.contrib.auth import login as login_user
 from annoying.functions import get_object_or_None
 from annoying.decorators import autostrip
 
-from openauth.utils import uri_to_username, attach_openid_data
+from openauth.utils import uri_to_username
 from openauth.fields import LoginField, PasswordField
-from openauth.models import OpenID
+from openauth.models import SocialID
 from openauth import settings
 
 
 ResetPasswordForm = autostrip(ResetPasswordForm)
 
 
-class OpenIDLoginForm(forms.Form):
-    openid_url = forms.CharField(u'OpenID URL', widget=forms.TextInput())
-
+class SocialIDExtraForm(forms.Form):
     def __init__(self, *args, **kwargs):
-        self.request = kwargs.pop('request', {})
-        super(OpenIDLoginForm, self).__init__(*args, **kwargs)
-
-    def clean(self):
-        """
-        Validate the data, try to login user or show form error if 
-        OpenID server returned reject response
-        """
-        request = self.request
-        super(OpenIDLoginForm, self).clean()
-        if self.is_valid():
-            openid_url = self.cleaned_data['openid_url']
-            return_url = request.build_absolute_uri(reverse('openauth-openid-complete'))
-            request.session['openid_return_to'] = return_url
-            client = consumer.Consumer(request.session, None)
-            try:
-                auth_request = client.begin(openid_url)
-                attach_openid_data(auth_request)
-                redirect_url = auth_request.redirectURL(realm='http://' + request.get_host(), return_to=return_url)
-                self.redirect_url = redirect_url
-
-            except discover.DiscoveryFailure:
-                raise forms.ValidationError(_('Could not find OpenID server'))
-        return self.cleaned_data
-
-
-class OpenIDRegistrationForm(forms.Form):
-    def __init__(self, *args, **kwargs):
-        for key, value in settings.OPENID_PROFILE_MAPPING.items():
+        for key, value in settings.SOCIALID_EXTRA_FIELDS_MAPPING.items():
             self.base_fields[value] = forms.CharField()
             if value == 'email':
                 self.base_fields[value] = forms.EmailField()
-        super(OpenIDRegistrationForm, self).__init__(*args, **kwargs)
+        super(SocialIDExtraForm, self).__init__(*args, **kwargs)
 
     def clean_login(self):
         login = self.cleaned_data['login']
             raise forms.ValidationError("This username already taken");
         return login
 
-    def save(self, openid_url):
+    def save(self, identity, provider):
         user = User.objects.create(username=self.cleaned_data['login'])
-        if settings.OPENID_ACTIVATION_REQUIRED:
+        if settings.SOCIALID_ACTIVATION_REQUIRED:
             user.is_active = False
         user.save()
-        OpenID(user=user, url=openid_url).save()
+        SocialID.objects.create(user=user, identity=identity, provider=provider)
         return user
 
 
 
 NewPasswordForm = autostrip(NewPasswordForm)
 
-
-class NewEmailForm(forms.Form):
-    """
-    Form for email chanage.
-    """
-    email = forms.EmailField(label=_(u'New email'))
-
-    def save(self):
-        pass
-
-
-class EditUserForm(forms.Form):
-    def __init__(self, user, *args, **kwargs):
-        self.user = user
-        self.base_fields['username'] = forms.CharField(max_length=254, initial=user.username)
-        super(EditUserForm, self).__init__(*args, **kwargs)
-
-    def save(self):
-        self.user.username = self.cleaned_data['username']
-        self.user.save()
-        return self.user
-
-EditUserForm = autostrip(EditUserForm)

openauth/models.py

 
 User.username = models.CharField(max_length=30, unique=settings.UNIQUE_USERNAME)
 
-class OpenID(models.Model):
+
+class SocialID(models.Model):
     user = models.ForeignKey(User)
-    url = models.CharField(u'OpenID URL', max_length=255, unique=True)
+    identity = models.CharField(u'Social ID', max_length=255, unique=True)
+    provider = models.CharField(u'Social Authentication provider name', max_length=255)
 
     def __unicode__(self):
-        return self.url
-
+        return "%s -> %s" % (self.provider, self.identity)

openauth/settings.py

 
 ### OPENID_REGISTRATION_FORM #######################################################################
 # See REGISTRATION_FORM description above                                                          #
-OPENID_REGISTRATION_FORM = get_config("OPENID_REGISTRATION_FORM",                                  #
-                                        "openauth.forms.OpenIDRegistrationForm")                   #
+SOCIALID_EXTRA_FORM = get_config("SOCIALID_EXTRA_FORM", "openauth.forms.SocialIDExtraForm")        #
 ####################################################################################################
 
-### OPENID_ACTIVATION_REQUIRED #####################################################################
+OPENID_ACTIVATION_REQUIRED = get_config("OPENID_ACTIVATION_REQUIRED", False)                       #
+
+### SOCIAL_ACTIVATION_REQUIRED #####################################################################
 # If activation is not required, user will be signed in immidiatly after OpenID registration       #
 # process. By default this activation is depend on regular activation setting                      #
-OPENID_ACTIVATION_REQUIRED = get_config("OPENID_ACTIVATION_REQUIRED", ACTIVATION_REQUIRED)         #
+SOCIALID_ACTIVATION_REQUIRED = get_config("OPENID_ACTIVATION_REQUIRED", ACTIVATION_REQUIRED)       #
 ####################################################################################################
 
 ### OPENID_EXTRA_FIELDS  ###########################################################################
 OPENID_PROFILE_MAPPING = get_config("OPENID_PROFILE_MAPPING", {'nickname': 'login'})               #
 ####################################################################################################
 
+SOCIALID_EXTRA_FIELDS_MAPPING = get_config("SOCIALID_EXTRA_FIELDS_MAPPING", {'nickname': 'login', 'emai': 'email'}) #
+
 ### AX_URIS ########################################################################################
 # This dict contains mapping of SREG fields to AX uris, you probably don't need to change it       #
 # http://www.axschema.org/types/                                                                   #
 }                                                                                                  #
 ####################################################################################################
 
+
+### BACKEND_MAPPING ################################################################################
+BACKEND_MAPPING = get_config("BACKEND_MAPPING", {                                                  #
+    'openid': 'openauth.backends.openid.OpenIDBackend',                                            #
+    'google': 'openauth.backends.google.GoogleBackend',                                            #
+    'twitter': 'openauth.backends.twitter.TwitterBackend',                                         #
+    'facebook': 'openauth.backends.facebook.FacebookBackend',                                      #
+    #'oauth': 'openauth.backends.oauth.OAuthBackend',                                               #
+    }                                                                                              #
+)                                                                                                  #
+####################################################################################################
+
+### DEFAULT_LOGIN_TEMPLATE #########################################################################
+DEFAULT_LOGIN_TEMPLATE = get_config("DEFAULT_LOGIN_TEMPLATE", "openauth/login.html")               #
+                                                                                                   #
+####################################################################################################
+
+### DEFAULT_LOGIN_TEMPLATE #########################################################################
+DEFAULT_LOGIN_FORM = get_config("DEFAULT_LOGIN_FORM", "openauth.backends.openid.OpenIDBackend")    #
+                                                                                                   #
+####################################################################################################
+
+GOOGLE_OPENID_URL = "https://www.google.com/accounts/o8/id"
+
+
+REGISTRATION_DISABLED_REDIRECT = get_config("REGISTRATION_DISABLED_REDIRECT", "/")
+
+FACEBOOK_EXTRA_FIELDS = ['name']
+FACEBOOK_PROFILE_MAPPING = get_config("FACEBOOK_PROFILE_MAPPING", {'name': 'login'})        
+
+GOOGLE_EXTRA_FIELDS = ['nickname', 'email', 'fullname', 'dob', 'gender']
+GOOGLE_PROFILE_MAPPING = get_config("GOOGLE_PROFILE_MAPPING", {'nickname': 'login', 'email': 'email'})        
+
+TWITTER_EXTRA_FIELDS = ['screen_name']
+TWITTER_PROFILE_MAPPING = get_config("TWITTER_PROFILE_MAPPING", {'screen_name': 'login', 'email': 'email'})        

openauth/templates/openauth/openid_login.html

-{% extends 'base.html' %}
-
-{% block content %}
-<script type="text/javascript">
-function chooseProvider(provider) {
-    var form = document.getElementById('openid_login');
-    var url = document.getElementById('id_openid_url');
-    if (provider == 'google') {
-        url.value = 'https://www.google.com/accounts/o8/id';
-        form.submit();
-    } else if(provider == 'yahoo') {
-        url.value =  'http://yahoo.com';
-        form.submit();
-    } else {
-        alert('unknown provider');
-    }
-}
-</script>
-<h2>OpenID Authorization and Registration</h2>
-
-<form action="." method="post" id="openid_login">
-    {{ form.as_table }}
-    <p>Or with <input type="button" name="auth_google" onclick="chooseProvider('google')" value="Google"/></p>
-    <p>Or with <input type="button" name="auth_yahoo" onclick="chooseProvider('yahoo')" value="Yahoo"/></p>
-    <p><input type="submit" value="Continue"/></p>
-</form>
-{% endblock %}

openauth/templates/openauth/openid_registration.html

-{% extends 'base.html' %}
-{% load i18n %}
-
-{% block content %}
-<h2>{% trans "Registration with OpenID: last step" %}</h2>
-<p><label>{% trans "OpenID URL" %}:</label> {{ openid_url }}</p>
-<form method="post">
-    <formfield>
-        <legend>Регистрация через OpenID</legend>
-        <div class="wide">{{ form.as_p }}</div>
-        <p><input type="submit" value="{% trans "Submit" %}"/></p>
-    </formfield>
-</form>
-{% endblock %}

openauth/templates/openauth/social_extra.html

+{% extends 'base.html' %}
+{% load i18n %}
+
+{% block content %}
+<h2>{% trans "Registration with OpenID: last step" %}</h2>
+<p><label>{% trans "OpenID URL" %}:</label> {{ openid_url }}</p>
+<form method="post">
+    <formfield>
+        <legend>Регистрация через OpenID</legend>
+        <div class="wide">{{ form.as_p }}</div>
+        <p><input type="submit" value="{% trans "Submit" %}"/></p>
+    </formfield>
+</form>
+{% endblock %}

openauth/templates/openauth/social_login.html

+{% extends 'base.html' %}
+
+{% block content %}
+<form action="{% url openauth-social-login 'openid' %}" method="post" id="openid_login">
+    {{ form.as_table }}
+    <p><input type="submit" value="Continue"/></p>
+</form>
+
+<a href="{% url openauth-social-login 'google' %}?openid_url=https://www.google.com/accounts/o8/id">Google</a>
+
+
+<a href="#" onclick="return fb_login();" id="facebook">Login with facebook</a>
+
+<script type="text/javascript" src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php"></script>
+<script type="text/javascript">
+    FB.init("{{ request.facebook.api_key }}", "{% url openauth-facebook-xdreceiver %}");
+
+    function fb_login() {
+        FB.Connect.requireSession(function(test) {
+            window.location = "{% url openauth-social-complete 'facebook' %}";
+        });
+        return false;
+    }
+</script>
+
+{% endblock %}
+
+

openauth/templates/openauth/xdreceiver.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <body>
+        <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
+    </body>
+</html>
 
 from openauth import views
 
+
 urlpatterns = patterns('',
     url(r'^registration/$', views.registration, name='openauth-registration'),
     url(r'^login/$', views.login, name='openauth-login'),
-    url(r'^openid-login/$', views.openid_login, name='openauth-openid-login'),
-    url(r'^openid-complete/$', views.openid_complete, name='openauth-openid-complete'),
-    url(r'^openid-registration/$', views.openid_registration, name='openauth-openid-registration'),
+    url(r'^social-login/$', views.social_login, name='openauth-social-login'),
+    url(r'^social-login/(\w+)/$', views.social_login, name='openauth-social-login'),
+    url(r'^social-complete/(\w+)/$', views.social_complete, name='openauth-social-complete'),
+    url(r'^social-extra/(\w+)/$', views.social_extra, name='openauth-social-extra'),
     url(r'^logout/$', views.logout, name='openauth-logout'),
     url(r'^reset-password/$', views.reset_password, name='openauth-reset-password'),
     url(r'^change-password/$', views.change_password, name='openauth-change-password'),
-    url(r'^user/$', views.show_user, name='openauth-show-user'),
-    url(r'^user/(\d+)/$', views.show_user, name='openauth-show-user'),
-    url(r'^users/$', views.users, name='openauth-show-users'),
-    url(r'^edit/(\d+)/$', views.edit_user, name='openauth-edit-user'),
-    #url(r'^email_changed/$', views.email_changed, name='auth_email_changed'),
+    url(r'^xdreceiver/$', views.xdreceiver, name='openauth-facebook-xdreceiver'),
 )

openauth/utils.py

 import time
 import pickle
 
+try:
+    from hashlib import md5
+except ImportError:
+    import md5
+    md5 = md5.new
+
 from functools import wraps
+from urllib import urlencode
 
 from openid.extensions.sreg import SRegRequest, SRegResponse
 from openid.extensions.ax import FetchRequest, AttrInfo, FetchResponse
 
-from django.shortcuts import redirect
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.importlib import import_module
+from django.conf import settings as django_settings
 from django.utils.translation import ugettext as _
 from django.core.urlresolvers import reverse
-from django.conf import settings as django_settings
+from django.template.loader import get_template
+from django.template import Context
+from django.shortcuts import redirect
+from django.core.mail import send_mail
 
 from notify import notify_user
 
+import openauth
 from openauth import settings
 
 
 def unicode_urlencode(params):
     """A unicode aware version of urllib.urlencode"""
-    from urllib import urlencode
 
     if isinstance(params, dict):
         params = params.items()
 
 
 def generate_hash(string=None):
-    try:
-        from hashlib import md5
-    except ImportError:
-        import md5
-        md5 = md5.new
+    """Generate random or md5 version of string"""
 
     if not string:
         string = str(time.time()) + django_settings.SECRET_KEY
     First line of template should contain the subject of email.
     Return tuple with subject and content.
     """
-    import re
-
-    from django.template.loader import get_template
-    from django.template import Context
 
     template = get_template(template_path)
     context = Context(kwargs)
 
     **kwargs may contain variables for template rendering.
     """
-    from django.core.mail import send_mail
 
     subject, content = parse_template(template_path, **kwargs)
     count = send_mail(subject, content, django_settings.DEFAULT_FROM_EMAIL,
     return re.sub('r[^0-9a-z]', '_', uri)
 
 
-def have_profile_name(field):
-    return field in settings.OPENID_PROFILE_MAPPING
+def get_instance_from_path(path, *args, **kwargs):
+    """
+    Return an instance of a class, given the dotted
+    Python import path (as a string) to the backend class.
 
+    If the backend cannot be located (e.g., because no such module
+    exists, or because the module does not contain a class of the
+    appropriate name), ``django.core.exceptions.ImproperlyConfigured``
+    is raised.
 
-def get_profile_field_name(field):
-    profile_field = settings.OPENID_PROFILE_MAPPING[field]
-    return profile_field
+    """
+    i = path.rfind('.')
+    module, attr = path[:i], path[i+1:]
+    try:
+        mod = import_module(module)
+    except ImportError, e:
+        raise ImproperlyConfigured('Error loading registration backend %s: "%s"' % (module, e))
+    try:
+        backend_class = getattr(mod, attr)
+    except AttributeError:
+        raise ImproperlyConfigured('Module "%s" does not define a registration backend named "%s"' % (module, attr))
 
-
-def attach_openid_data(openid_request):
-    sreg = SRegRequest(required=settings.OPENID_EXTRA_FIELDS)
-    openid_request.addExtension(sreg)
-    ax_msg = FetchRequest()
-    for detail in settings.OPENID_EXTRA_FIELDS:
-        ax_msg.add(AttrInfo(settings.AX_URIS[detail], required=True))
-    openid_request.addExtension(ax_msg)
-
-
-def dump_openid_data(request, response):
-    request.session['authenticated_openid_url'] = response.identity_url
-    sreg_response = SRegResponse.fromSuccessResponse(response)
-    ax_response = FetchResponse.fromSuccessResponse(response)
-    request.session['sreg_response'] = pickle.dumps(sreg_response)
-    request.session['ax_response'] = pickle.dumps(ax_response)
-
-
-def extract_openid_data(request):
-    initial = {}
-    sreg_response = pickle.loads(request.session['sreg_response'])
-    ax_response = pickle.loads(request.session['ax_response'])
-    for field in settings.OPENID_EXTRA_FIELDS:
-        if have_profile_name(field):
-            profile_field = get_profile_field_name(field)
-            if sreg_response:
-                initial.update({profile_field: sreg_response.get(field, '')})
-            if ax_response:
-                initial.update({profile_field: ax_response.getSingle(settings.AX_URIS[field], '')})
-    return initial
-
+    return backend_class(*args, **kwargs)

openauth/views.py

 
 from confirmation.models import Confirmation
 from annoying.decorators import render_to
+from annoying.exceptions import Redirect
 from notify import notify_user
 
 from openauth import settings
-from openauth.forms import ResetPasswordForm, NewPasswordForm, LoginForm, \
-     OpenIDLoginForm, OpenIDRegistrationForm
-from openauth.utils import email_template, build_redirect_url, str_to_class, \
-    login_required, dump_openid_data, extract_openid_data
-from openauth.models import OpenID
+from openauth.forms import ResetPasswordForm, NewPasswordForm, LoginForm, SocialIDExtraForm
+from openauth.utils import email_template, build_redirect_url, str_to_class, login_required, get_instance_from_path
 
 
 @login_required(opposite=True)
                     return notify_user.success(request, "/", openauth.lang.PLEASE_ACTIVATE)
                 else:
                     user.delete()
-                    return notify_user.error(request, "/", openauth.lang.ERROR_SENDING_MAIL)
+                    request.flash['error'] = openauth.lang.ERROR_SENDING_MAIL
+                    return redirect("/")
             else:
                 if settings.AUTO_LOGIN:
                     user.backend = 'django.contrib.auth.backends.ModelBackend'
                     login_user(request, user)
-                    return notify_user.success(request, settings.LOGIN_REDIRECT_URL, 
-                                                openauth.lang.SUCCESSFULL_LOGIN)
-                return notify_user.success(request, "openauth-login", openauth.lang.LOGIN_NOW)
+                    request.flash['success'] = openauth.lang.SUCCESSFULL_LOGIN
+                    return redirect(settings.LOGIN_REDIRECT_URL)
+
+                request.flash['success'] = openauth.lang.LOGIN_NOW
+                return redirect("openauth-login")
     else:
         form = str_to_class(settings.REGISTRATION_FORM)()
     return {'form': form}
         form = LoginForm(request, request.POST)
         if form.is_valid():
             redirect_url = request.GET.get("next") or settings.LOGIN_REDIRECT_URL
-            return notify_user.success(request, redirect_url, openauth.lang.SUCCESSFULL_LOGIN)
+            request.flash['success'] = openauth.lang.SUCCESSFULL_LOGIN
+            return redirect(redirect_url)
     else:
         form = LoginForm(request=request)
     return {'form': form}
             confirmation = Confirmation.objects.create(user, settings.PASSWORD_RESET_TYPE, redirect_url=reverse("openauth-change-password"))
             args = {'domain': request.get_host(), 'url': confirmation.get_url(request)}
             if email_template(user.email, 'openauth/mail/reset_password.txt', **args):
-                return notify_user.notice(request, "/",  _('Check your email please'))
+                request.flash['notice'] =  _('Check your email please')
+                return redirect("/")
             else:
-                return notify_user.notice(request, "/", openauth.lang.ERROR_SENDING_MAIL)
+                request.flash['notice'] = openauth.lang.ERROR_SENDING_MAIL
+                return redirect("/")
     else:
         form = ResetPasswordForm()
     return {'form': form}
 
 
-@render_to('openauth/openid_login.html')
-def openid_login(request):
-    """
-    Display OpenID authentication form. This is also the first step
-    in OpenID registration. The actual login is in openid_complete 
-    function below.
-    """
-    if request.method == "POST":
-        form = OpenIDLoginForm(request.POST, request=request)
-        if form.is_valid():
-            next_url = request.GET.get("next") or settings.LOGIN_REDIRECT_URL
-            request.session['next_url'] = next_url
-            return redirect(form.redirect_url)
-    else:
-        form = OpenIDLoginForm()
-
-    return {'form': form}
-
-
-def openid_complete(request):
-    """
-    Complete OpenID authorization process.
-    If OpenID URL was successfuly authenticated:
-     * if no user with such URL exists and current user is authenticated then
-       assign OpenID url to this user
-     * if user with such URL exists then login as this user
-     * if no user with such URL exists then redirect to registration form
-    """
-    client = consumer.Consumer(request.session, None)
-    data = dict(request.GET.items())
-
-    # In case OpenID server responded with POST method
-    if request.method == "POST":
-        data.update(request.POST)
-    try:
-        resp = client.complete(data, request.session['openid_return_to'])
-        del request.session['openid_return_to']
-    except KeyError:
-        return notify_user.error(request, 
-                reverse("openauth-openid-login"),
-                _("Invalid response received from OpenID server, please start start the authentication process again")
-                )
-    if resp.status == consumer.CANCEL:
-        return notify_user.error(request, "/", _('You have cancelled OpenID authorization'))
-    elif resp.status == consumer.FAILURE:
-        return notify_user.error(request, "/", _('OpenID authorization failed. Reason: %s') % resp.message)
-    elif resp.status == consumer.SUCCESS:
-        redirect_url = request.session['next_url']
-        if request.user.is_authenticated():
-            try:
-                user = OpenID.objects.get(url=resp.identity_url).user
-            except OpenID.DoesNotExist:
-                OpenID(user=request.user, url=resp.identity_url).save()
-            del request.session['next_url']
-            return notify_user.success(request, redirect_url, _("Your OpenID account is saved"))
-        else:
-            user = auth.authenticate(openid_url=resp.identity_url)
-            if user:
-                if settings.OPENID_ACTIVATION_REQUIRED and not user.is_active:
-                    return notify_user.success(request, "/", _("Your account is not activated. Please activate it first."))
-                else:
-                    auth.login(request, user)
-                    del request.session['next_url']
-                    return notify_user.success(request, redirect_url, _("You have successfully authorized via OpenID"))
-            else:
-                if not settings.REGISTRATION_ALLOWED:
-                    return notify_user.notice(request, '/', openauth.lang.REGISTRATION_DISABLED)
-                # if user must fill addition fields to complete registration
-                # we ease this process by trying to fetch extra information
-                # from openid provider.
-                if not settings.OPENID_PROFILE_MAPPING:
-                    OpenID(user=request.user, url=resp.identity_url).save()
-                    if not settings.OPENID_ACTIVATION_REQUIRED:
-                        user = auth.authenticate(openid_url=resp.identity_url)
-                        if user:
-                            auth.login(request, user)
-                            del request.session['next_url']
-                            return notify_user.success(request, redirect_url, _("You have successfully authorized via OpenID"))
-                else:
-                    dump_openid_data(request, resp)
-                    return redirect(reverse('openauth-openid-registration'))
-
-    return notify_user.error(request, reverse("openauth-openid-login"), _("Invalid response received from OpenID server, please start start the authentication process again"))
-
-
-@render_to('openauth/openid_registration.html')
-def openid_registration(request):
-    """                                                
-    Handle registration new user with given authenticated_openid_url in session
-    """                                                          
-    try:
-        openid_url = request.session['authenticated_openid_url']
-    except KeyError:
-        raise Http404
-
-    if request.method == "POST":
-        form = str_to_class(settings.OPENID_REGISTRATION_FORM)(request.POST)
-        if form.is_valid():
-            user = form.save(openid_url)
-            del request.session['authenticated_openid_url']
-            if settings.OPENID_ACTIVATION_REQUIRED:
-                confirmation = Confirmation.objects.create(user, settings.ACTIVATION_TYPE)
-                params = {'domain': request.get_host(), 'email': user.email, 'url': confirmation.get_url(request)}
-                email_template(user.email, 'openauth/mail/registration.txt', **params)
-                return notify_user.success(request, "openauth-show-user", openauth.lang.PLEASE_ACTIVATE)
-            user = auth.authenticate(openid_url=openid_url)
-            if user:
-                auth.login(request, user)
-                redirect_url = request.session['next_url']
-                del request.session['next_url']
-                return notify_user.success(request, redirect_url, _("You have been successfully registred"))
-    else:                                        
-        initial = {}
-        if settings.OPENID_PROFILE_MAPPING:
-            initial = extract_openid_data(request)
-        form = str_to_class(settings.OPENID_REGISTRATION_FORM)(initial=initial)
-
-    return {'form': form, 'openid_url': openid_url}
-
-
-
 @login_required
 @render_to('openauth/change_password.html')
 def change_password(request):
 
     if form.is_valid():
         form.save(request.user)
-        url = reverse('openauth-show-user', args=[request.user.id])
-        return notify_user.success(request, url, _('Password was changed'))
+        request.flash['success'] =  _('Password was changed')
+        return redirect("/")
     return {'form': form}
 
 
 @login_required
 def logout(request):
     auth.logout(request)
-    return notify_user.success(request, "/", _('You have been logged out'))
+    request.flash['success'] = _('You have been logged out')
+    return redirect("/")
 
 
+@render_to('openauth/social_login.html')
+def social_login(request, provider=None):
+    """
+    Display authentication form. This is also the first step
+    in social registration. The actual login is in social_complete 
+    function below.
+    """
+    if provider:
+        path = settings.BACKEND_MAPPING[provider]
+        data = request.GET.copy()
+        data.update(request.POST)
+        form = get_instance_from_path(path, data, request=request, provider=provider)
+        next_url = request.GET.get("next") or settings.LOGIN_REDIRECT_URL
+        request.session['next_url'] = next_url
+        form.is_valid()
+    else:
+        form = get_instance_from_path(settings.DEFAULT_LOGIN_FORM)
 
-@login_required
-@render_to('openauth/edit_user.html')
-def edit_user(request, user_id):
-    user = get_object_or_404(User, pk=user_id)
-    if not request.user.is_authenticated() or user != request.user and not request.user.is_staff:
-        return redirect("/")
-    if request.POST:
-        form = str_to_class(settings.EDIT_USER_FORM)(user, request.POST, request.FILES)
+    return {'form': form}
+
+
+def social_complete(request, provider):
+    """
+    Complete SocialID authorization process.
+    If SocialID was successfuly authenticated:
+     * if no user with such ID exists and current user is authenticated then
+       assign SocialID to this user.
+     * if user with such ID exists and current user is anonimouse then login 
+       as this user.
+     * if no user with such ID exists and user must fill extra fields, 
+       redirect him to registration form.
+    """
+    path = settings.BACKEND_MAPPING[provider]
+    backend = get_instance_from_path(path, request=request, provider=provider)
+    response = backend.validate_response(request)
+    if request.user.is_authenticated():
+        backend.login_user(request)
+        backend.attach_account(request, request.user)
+    else:
+        backend.login_user(request)
+        if not settings.REGISTRATION_ALLOWED:
+            request.flash['warning'] =  openauth.lang.REGISTRATION_DISABLED
+            return redirect(settings.REGISTRATION_DISABLED_REDIRECT)
+    backend.complete(request, response)
+
+
+
+@render_to('openauth/social_extra.html')
+def social_extra(request, provider):
+    """                                                
+    Handle registration of new user with extra data for profile
+    """                                                          
+    path = settings.BACKEND_MAPPING[provider]
+    backend = get_instance_from_path(path, request=request, provider=provider)
+
+    try:
+        identity = request.session['identity']
+    except KeyError:
+        raise Http404
+
+
+    if request.method == "POST":
+        form = str_to_class(settings.SOCIALID_EXTRA_FORM)(request.POST)
         if form.is_valid():
-            form.save()
-            url = reverse('openauth-show-user', args=[request.user.id])
-            return notify_user.success(request, url, _('User details successfully changed'))
+            user = form.save(identity, provider)
+            del request.session['identity']
+            if settings.OPENID_ACTIVATION_REQUIRED:
+                confirmation = Confirmation.objects.create(user, settings.ACTIVATION_TYPE)
+                params = {'domain': request.get_host(), 'email': user.email, 'url': confirmation.get_url(request)}
+                email_template(user.email, 'openauth/mail/registration.txt', **params)
+                request.flash['success'] = openauth.lang.PLEASE_ACTIVATE
+                return redirect("/")
+            user = auth.authenticate(identity=identity, provider=provider)
+            if user:
+                auth.login(request, user)
+                redirect_url = request.session['next_url']
+                del request.session['next_url']
+                return redirect(redirect_url)
     else:
-        form = str_to_class(settings.EDIT_USER_FORM)(user)
+        initial = request.session['extra']
+        form = str_to_class(settings.SOCIALID_EXTRA_FORM)(initial=initial)
 
-    return {'form': form, 'user': user}
+    return {'form': form}
 
 
-
-@render_to('openauth/profile.html')
-def show_user(request, user_id=None):
-    """
-    Show user profile 
-    """
-    user_id = user_id or request.user.id
-    user = get_object_or_404(User, pk=user_id)
-    return {'user': user}
-
-
-@render_to('openauth/users.html')
-def users(request):
-    users = User.objects.filter(is_active=True).all()
-    return {'users': users}
-
+@render_to("openauth/xdreceiver.html")
+def xdreceiver(request):
+    return {}
+-e svn+http://oauth.googlecode.com/svn/code/python/oauth/@1137#egg=oauth
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.