-"""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
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):
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 \
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
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:
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)