Skip to content

Commit

Permalink
Improved user creation handling, closes gh-3
Browse files Browse the repository at this point in the history
  • Loading branch information
omab committed Dec 27, 2010
1 parent d90d0db commit 219b5bb
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 138 deletions.
64 changes: 33 additions & 31 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ third parties.
--------
Features
--------
This app provides user registration and login using social sites credentials,
some features are:
This application provides user registration and login using social sites
credentials, some features are:

- Registration and Login using social sites using the following providers
at the moment:
Expand Down Expand Up @@ -50,7 +50,7 @@ Dependencies that must be meet to use the app:
------------
Installation
------------
- Add social_auth app to PYTHONPATH and installed apps::
- Add social_auth to PYTHONPATH and installed applications::

INSTALLED_APPS = (
...
Expand All @@ -63,6 +63,8 @@ Installation
'social_auth.backends.TwitterOAuthBackend',
'social_auth.backends.FacebookOAuthBackend',
'social_auth.backends.OrkutOAuthBackend',
'social_auth.backends.GoogleOpenIDBackend',
'social_auth.backends.YahooOpenIDBackend',
'social_auth.backends.OpenIDBackend',
'django.contrib.auth.backends.ModelBackend',
)
Expand All @@ -76,21 +78,21 @@ Installation
ORKUT_CONSUMER_KEY = ''
ORKUT_CONSUMER_SECRET = ''

- Setup login urls::
- Setup login URLs::

LOGIN_URL = '/login-form/'
LOGIN_REDIRECT_URL = '/logged-in/'
LOGIN_ERROR_URL = '/login-error/'

Check Django documentation at `Login url`_ and `Login redirect url`_
Check Django documentation at `Login URL`_ and `Login redirect URL`_

- Configure authentication and association complete URL names to avoid
possible clashes::

SOCIAL_AUTH_COMPLETE_URL_NAME = 'namespace:complete'
SOCIAL_AUTH_ASSOCIATE_URL_NAME = 'namespace:association_complete'

- Add urls entries::
- Add URLs entries::

urlpatterns = patterns('',
...
Expand Down Expand Up @@ -118,40 +120,37 @@ Installation

SOCIAL_AUTH_EXTRA_DATA = False

- It's possible to override the used User class if needed::
- It's possible to override the used User model if needed::

SOCIAL_AUTH_USER_MODEL = 'myapp.CustomUser'

this class must define the following fields::
This class *must* have a custom `Model Manager`_ with a create_user method
that resembles the one on `auth.UserManager`_.

Also, it's highly recommended that this class define the following fields::

username = CharField(...)
email = EmailField(...)
password = CharField(...)
last_login = DateTimeField(blank=True)
is_active = BooleanField(...)

and the methods::

is_authenticated()

These are needed to ensure django-auth integration. AttributeError is raised
if any of these are missing.
and the method::

Also the following are recommended but not enforced::
is_authenticated():
...

first_name = CharField(...)
last_name = CharField(...)
These are needed to ensure a better django-auth integration, in other case
`login_required`_ won't be usable. A warning is displayed if any of these are
missing. By default `auth.User`_ is used.

By default `auth.User`_ is used. Check example application for
implementation details, but first, please take a look to `User Profiles`_,
it might solve your case.
Check example application for implementation details, but first, please take
a look to `User Profiles`_, it might be what you were looking for.


-------
Signals
-------
A pre_update signal is sent when user data is about to be updated with new
values from auth service provider, this apply to new users and already
values from authorization service provider, this apply to new users and already
existent ones. This is useful to update custom user fields or `User Profiles`_,
for example, to store user gender, location, etc. Example::

Expand Down Expand Up @@ -190,7 +189,7 @@ Twitter offers per application keys named "Consumer Key" and
"Consumer Secret". To enable Twitter these two keys are needed.
Further documentation at `Twitter development resources`_:

- Register a new app at `Twitter App Creation`_,
- Register a new application at `Twitter App Creation`_,

- mark the "Yes, use Twitter for login" checkbox, and

Expand All @@ -199,7 +198,7 @@ Further documentation at `Twitter development resources`_:
TWITTER_CONSUMER_KEY
TWITTER_CONSUMER_SECRET

- You don't need to specify the url callback
- You don't need to specify the URL callback


--------
Expand All @@ -209,7 +208,7 @@ Facebook works similar to Twitter but it's simpler to setup and
redirect URL is passed as a parameter when issuing an authorization.
Further documentation at `Facebook development resources`_:

- Register a new app at `Facebook App Creation`_, and
- Register a new application at `Facebook App Creation`_, and

- fill "App Id" and "App Secret" values in values::

Expand Down Expand Up @@ -262,22 +261,25 @@ Base work is copyrighted by:
Copyright (C) 2007 Simon Willison
Copyright (C) 2008-2010 Canonical Ltd.

.. _Model Manager: http://docs.djangoproject.com/en/dev/topics/db/managers/#managers
.. _Login URL: http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#login-url
.. _Login redirect URL: http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#login-redirect-url
.. _AUTHENTICATION_BACKENDS: http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#authentication-backends
.. _auth.User: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L186
.. _auth.UserManager: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L114
.. _login_required: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py#L39
.. _User Profiles: http://www.djangobook.com/en/1.0/chapter12/#cn222
.. _OpenId: http://openid.net/
.. _OAuth: http://oauth.net/
.. _django-twitter-oauth: https://github.com/henriklied/django-twitter-oauth
.. _django-openid-auth: https://launchpad.net/django-openid-auth
.. _python-openid: http://pypi.python.org/pypi/python-openid/
.. _python-oauth: https://github.com/leah/python-oauth
.. _Login url: http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#login-url
.. _Login redirect url: http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#login-redirect-url
.. _Twitter development resources: http://dev.twitter.com/pages/auth
.. _Twitter App Creation: http://twitter.com/apps/new
.. _dnsmasq: http://www.thekelleys.org.uk/dnsmasq/doc.html
.. _Facebook development resources: http://developers.facebook.com/docs/authentication/
.. _Facebook App Creation: http://developers.facebook.com/setup/
.. _AUTHENTICATION_BACKENDS: http://docs.djangoproject.com/en/dev/ref/settings/?from=olddocs#authentication-backends
.. _auth.User: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L186
.. _User Profiles: http://www.djangobook.com/en/1.0/chapter12/#cn222
.. _caioariede: https://github.com/caioariede
.. _Google support: http://www.google.com/support/a/bin/answer.py?hl=en&answer=162105
.. _Orkut API: http://code.google.com/apis/orkut/docs/rest/developers_guide_protocol.html#Authenticating
Expand Down
30 changes: 16 additions & 14 deletions example/app/models.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# Define a custom User class to work with django-social-auth
#
# from django.db import models
#
# class CustomUser(models.Model):
# username = models.CharField(max_length=128)
# email = models.EmailField()
# password = models.CharField(max_length=128)
# last_login = models.DateTimeField(blank=True, null=True)
# first_name = models.CharField(max_length=128, blank=True)
# last_name = models.CharField(max_length=128, blank=True)
# is_active = models.BooleanField(default=True)
#
# def is_authenticated(self):
# return True
from django.db import models


class CustomUserManager(models.Manager):
def create_user(self, username, email):
return self.model._default_manager.create(username=username)


class CustomUser(models.Model):
username = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)

objects = CustomUserManager()

def is_authenticated(self):
return True
16 changes: 10 additions & 6 deletions example/app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@


def home(request):
if request.user.is_authenticated():
return HttpResponseRedirect('done')
return HttpResponse(Template(
"""
<html>
Expand Down Expand Up @@ -44,6 +46,7 @@ def home(request):

@login_required
def done(request):
names = request.user.social_auth.values_list('provider', flat=True)
return HttpResponse(Template(
"""
<html>
Expand All @@ -65,11 +68,11 @@ def done(request):
<h2>Associate new credentials:</h2>
<div>
<ul>
<li><a href="/associate/twitter/">Twitter</a></li>
<li><a href="/associate/facebook/">Facebook</a></li>
<li><a href="/associate/orkut/">Orkut</a></li>
<li><a href="/associate/google/">Google</a></li>
<li><a href="/associate/yahoo/">Yahoo</a></li>
<li><a href="/associate/twitter/">Twitter</a> {% if twitter %}(associated){% endif %}</li>
<li><a href="/associate/facebook/">Facebook</a> {% if facebook %}(associated){% endif %}</li>
<li><a href="/associate/orkut/">Orkut</a> {% if orkut %}(associated){% endif %}</li>
<li><a href="/associate/google/">Google</a> {% if google %}(associated){% endif %}</li>
<li><a href="/associate/yahoo/">Yahoo</a> {% if yahoo %}(associated){% endif %}</li>
<li>
<form action="/associate/openid/" method="post">{% csrf_token %}
<label for="openid_identifier">Other provider:</label>
Expand All @@ -81,7 +84,8 @@ def done(request):
</div>
</body>
</html>
""").render(RequestContext(request)),
""").render(RequestContext(request, dict((name.lower(), True)
for name in names))),
content_type='text/html;charset=UTF-8')


Expand Down
2 changes: 2 additions & 0 deletions example/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
AUTHENTICATION_BACKENDS = (
'social_auth.backends.TwitterBackend',
'social_auth.backends.FacebookBackend',
'social_auth.backends.GoogleBackend',
'social_auth.backends.YahooBackend',
'social_auth.backends.OpenIDBackend',
'django.contrib.auth.backends.ModelBackend',
)
Expand Down
15 changes: 12 additions & 3 deletions social_auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from .store import DjangoOpenIDStore
from .backends import TwitterBackend, OrkutBackend, FacebookBackend, \
OpenIDBackend
OpenIDBackend, GoogleBackend, YahooBackend
from .conf import AX_ATTRS, SREG_ATTR, OPENID_ID_FIELD, SESSION_NAME, \
OPENID_GOOGLE_URL, OPENID_YAHOO_URL, TWITTER_SERVER, \
TWITTER_REQUEST_TOKEN_URL, TWITTER_ACCESS_TOKEN_URL, \
Expand Down Expand Up @@ -54,7 +54,12 @@ def uses_redirect(self):


class OpenIdAuth(BaseAuth):
"""OpenId process handling"""
"""
OpenId process handling
@AUTH_BACKEND Authorization backend related with this service
"""
AUTH_BACKEND = OpenIDBackend

def auth_url(self):
openid_request = self.setup_request()
# Construct completion URL, including page we should redirect to
Expand All @@ -78,7 +83,7 @@ def auth_complete(self, *args, **kwargs):
if not response:
raise ValueError, 'This is an OpenID relying party endpoint'
elif response.status == SUCCESS:
kwargs.update({'response': response, OpenIDBackend.name: True})
kwargs.update({'response': response, self.AUTH_BACKEND.name: True})
return authenticate(*args, **kwargs)
elif response.status == FAILURE:
raise ValueError, 'OpenID authentication failed: %s' % response.message
Expand Down Expand Up @@ -140,13 +145,17 @@ def openid_url(self):

class GoogleAuth(OpenIdAuth):
"""Google OpenID authentication"""
AUTH_BACKEND = GoogleBackend

def openid_url(self):
"""Return Google OpenID service url"""
return OPENID_GOOGLE_URL


class YahooAuth(OpenIdAuth):
"""Yahoo OpenID authentication"""
AUTH_BACKEND = YahooBackend

def openid_url(self):
"""Return Yahoo OpenID service url"""
return OPENID_YAHOO_URL
Expand Down
Loading

0 comments on commit 219b5bb

Please sign in to comment.