From: Matías Aguirre Date: Sun, 14 Aug 2011 06:58:15 +0000 (-0300) Subject: Decorate views to retrieve backend or return http error if not correct. Closes gh-116 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=3bbcee80d4a43f20481951211554da3914dec965;p=django-social-auth.git Decorate views to retrieve backend or return http error if not correct. Closes gh-116 --- diff --git a/social_auth/views.py b/social_auth/views.py index 8f88d9d..4325743 100644 --- a/social_auth/views.py +++ b/social_auth/views.py @@ -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)