]> git.parisson.com Git - django-social-auth.git/commitdiff
Decorate views to retrieve backend or return http error if not correct. Closes gh-116
authorMatías Aguirre <matiasaguirre@gmail.com>
Sun, 14 Aug 2011 06:58:15 +0000 (03:58 -0300)
committerMatías Aguirre <matiasaguirre@gmail.com>
Sun, 14 Aug 2011 06:58:15 +0000 (03:58 -0300)
social_auth/views.py

index 8f88d9d1ba7cf649b78a7dd718b0912832e2215f..432574313a70d293847ed8dee8064a081e21b3c1 100644 (file)
@@ -1,4 +1,12 @@
-"""Views"""
+"""Views
+
+Notes:
+    * Some views are marked to avoid csrf tocken check becuase they relay
+      on third party providers that (if using POST) won't be sending crfs
+      token back.
+"""
+from functools import wraps
+
 from django.conf import settings
 from django.http import HttpResponseRedirect, HttpResponse, \
                         HttpResponseServerError
@@ -29,58 +37,56 @@ SOCIAL_AUTH_LAST_LOGIN = _setting('SOCIAL_AUTH_LAST_LOGIN',
 SESSION_EXPIRATION = _setting('SOCIAL_AUTH_SESSION_EXPIRATION', True)
 
 
+def dsa_view(redirect_name=None):
+    """Decorate djangos-social-auth views. Will check and retrieve backend
+    or return HttpResponseServerError if backend is not found.
+
+        redirect_name parameter is used to build redirect URL used by backend.
+    """
+    def dec(func):
+        @wraps(func)
+        def wrapper(request, backend, *args, **kwargs):
+            if redirect_name:
+                redirect = reverse(redirect_name, args=(backend,))
+            else:
+                redirect = request.path
+            print "BACKEND:", backend
+            backend = get_backend(backend, request, redirect)
+            print "BACKEND:", backend
+
+            if not backend:
+                return HttpResponseServerError('Incorrect authentication ' + \
+                                               'service')
+            return func(request, backend, *args, **kwargs)
+        return wrapper
+    return dec
+
+
+@dsa_view(COMPLETE_URL_NAME)
 def auth(request, backend):
     """Start authentication process"""
-    return auth_process(request, backend, COMPLETE_URL_NAME)
+    return auth_process(request, backend)
 
 
-@csrf_exempt  # If provider uses POST it won't be sending a CSRF token
+@csrf_exempt
 @transaction.commit_on_success
+@dsa_view()
 def complete(request, backend):
     """Authentication complete view, override this view if transaction
     management doesn't suit your needs."""
     return complete_process(request, backend)
 
 
-def complete_process(request, backend):
-    """Authentication complete process"""
-    user = auth_complete(request, backend)
-
-    if user and getattr(user, 'is_active', True):
-        login(request, user)
-        # user.social_user is the used UserSocialAuth instance defined
-        # in authenticate process
-        social_user = user.social_user
-
-        if SESSION_EXPIRATION :
-            # Set session expiration date if present and not disabled by
-            # setting. Use last social-auth instance for current provider,
-            # users can associate several accounts with a same provider.
-            if social_user.expiration_delta():
-                request.session.set_expiry(social_user.expiration_delta())
-
-        # store last login backend name in session
-        request.session[SOCIAL_AUTH_LAST_LOGIN] = social_user.provider
-
-        # Remove possible redirect URL from session, if this is a new account,
-        # send him to the new-users-page if defined.
-        url = NEW_USER_REDIRECT if NEW_USER_REDIRECT and \
-                                   getattr(user, 'is_new', False) else \
-              request.session.pop(REDIRECT_FIELD_NAME, '') or \
-              DEFAULT_REDIRECT
-    else:
-        url = LOGIN_ERROR_URL
-    return HttpResponseRedirect(url)
-
-
 @login_required
+@dsa_view(ASSOCIATE_URL_NAME)
 def associate(request, backend):
     """Authentication starting process"""
-    return auth_process(request, backend, ASSOCIATE_URL_NAME)
+    return auth_process(request, backend)
 
 
-@csrf_exempt  # If provider uses POST it won't be sending a CSRF token
+@csrf_exempt
 @login_required
+@dsa_view()
 def associate_complete(request, backend):
     """Authentication complete process"""
     if auth_complete(request, backend):
@@ -89,16 +95,13 @@ def associate_complete(request, backend):
               DEFAULT_REDIRECT
     else:
         url = LOGIN_ERROR_URL
-
     return HttpResponseRedirect(url)
 
 
 @login_required
+@dsa_view()
 def disconnect(request, backend, association_id=None):
     """Disconnects given backend from current logged in user."""
-    backend = get_backend(backend, request, request.path)
-    if not backend:
-        return HttpResponseServerError('Incorrect authentication service')
     backend.disconnect(request.user, association_id)
     url = request.REQUEST.get(REDIRECT_FIELD_NAME, '') or \
           DISCONNECT_REDIRECT_URL or \
@@ -106,13 +109,8 @@ def disconnect(request, backend, association_id=None):
     return HttpResponseRedirect(url)
 
 
-def auth_process(request, backend, complete_url_name):
+def auth_process(request, backend):
     """Authenticate using social backend"""
-    redirect = reverse(complete_url_name, args=(backend,))
-    backend = get_backend(backend, request, redirect)
-    if not backend:
-        return HttpResponseServerError('Incorrect authentication service')
-
     # Save any defined redirect_to value into session
     if REDIRECT_FIELD_NAME in request.REQUEST:
         data = request.POST if request.method == 'POST' else request.GET
@@ -131,10 +129,6 @@ def auth_process(request, backend, complete_url_name):
 
 def auth_complete(request, backend):
     """Complete auth process. Return authenticated user or None."""
-    backend = get_backend(backend, request, request.path)
-    if not backend:
-        return HttpResponseServerError('Incorrect authentication service')
-
     user = request.user if request.user.is_authenticated() else None
 
     try:
@@ -144,3 +138,34 @@ def auth_complete(request, backend):
         if error_key:  # store error in session
             request.session[error_key] = str(e)
     return user
+
+
+def complete_process(request, backend):
+    """Authentication complete process"""
+    user = auth_complete(request, backend)
+
+    if user and getattr(user, 'is_active', True):
+        login(request, user)
+        # user.social_user is the used UserSocialAuth instance defined
+        # in authenticate process
+        social_user = user.social_user
+
+        if SESSION_EXPIRATION :
+            # Set session expiration date if present and not disabled by
+            # setting. Use last social-auth instance for current provider,
+            # users can associate several accounts with a same provider.
+            if social_user.expiration_delta():
+                request.session.set_expiry(social_user.expiration_delta())
+
+        # store last login backend name in session
+        request.session[SOCIAL_AUTH_LAST_LOGIN] = social_user.provider
+
+        # Remove possible redirect URL from session, if this is a new account,
+        # send him to the new-users-page if defined.
+        url = NEW_USER_REDIRECT if NEW_USER_REDIRECT and \
+                                   getattr(user, 'is_new', False) else \
+              request.session.pop(REDIRECT_FIELD_NAME, '') or \
+              DEFAULT_REDIRECT
+    else:
+        url = LOGIN_ERROR_URL
+    return HttpResponseRedirect(url)