from django.utils.translation import ugettext as _
from django.contrib import messages
from django.utils.http import urlencode
-from django.contrib.auth import login as auth_login, authenticate
-from django.http import HttpResponse
+from django.contrib.auth import authenticate
+from django.http import (
+ HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
+)
+from django.core.exceptions import ValidationError
+from django.views.decorators.http import require_http_methods
from urllib import quote
-from urlparse import urlunsplit, urlsplit
+from urlparse import urlunsplit, urlsplit, urlparse, parse_qsl
from astakos.im.settings import COOKIE_NAME, COOKIE_DOMAIN
-from astakos.im.util import set_cookie
+from astakos.im.util import set_cookie, restrict_next
+from astakos.im.functions import login as auth_login, logout
import logging
logger = logging.getLogger(__name__)
+@require_http_methods(["GET", "POST"])
def login(request):
"""
- If the request user is authenticated, redirects to `next` request parameter
- if exists, otherwise redirects to astakos index page displaying an error
- message.
- If the request user is not authenticated, redirects to login in order to
- return back here after successful login.
+ If there is no ``next`` request parameter redirects to astakos index page
+ displaying an error message.
+ If the request user is authenticated and has signed the approval terms,
+ redirects to `next` request parameter. If not, redirects to approval terms
+ in order to return back here after agreeing with the terms.
+ Otherwise, redirects to login in order to return back here after successful login.
"""
+ next = request.GET.get('next')
+ if not next:
+ return HttpResponseBadRequest(_('No next parameter'))
+ if not restrict_next(
+ next, domain=COOKIE_DOMAIN, allowed_schemes=('pithos',)
+ ):
+ return HttpResponseForbidden(_('Not allowed next parameter'))
+ force = request.GET.get('force', None)
+ response = HttpResponse()
+ if force == '':
+ logout(request)
+ response.delete_cookie(COOKIE_NAME, path='/', domain=COOKIE_DOMAIN)
if request.user.is_authenticated():
- next = request.GET.get('next')
- renew = request.GET.get('renew', None)
- if next:
- response = HttpResponse()
- if renew == '':
- request.user.renew_token()
- request.user.save()
-
- # authenticate before login
- user = authenticate(email=request.user.email, auth_token=request.user.auth_token)
- auth_login(request, user)
- set_cookie(response, user)
- logger.info('Token reset for %s' % request.user.email)
- parts = list(urlsplit(next))
- parts[3] = urlencode({'user': request.user.email, 'token': request.user.auth_token})
+ # if user has not signed the approval terms
+ # redirect to approval terms with next the request path
+ if not request.user.signed_terms():
+ # first build next parameter
+ parts = list(urlsplit(request.build_absolute_uri()))
+ params = dict(parse_qsl(parts[3], keep_blank_values=True))
+ # delete force parameter
+ parts[3] = urlencode(params)
+ next = urlunsplit(parts)
+
+ # build url location
+ parts[2] = reverse('latest_terms')
+ params = {'next':next}
+ parts[3] = urlencode(params)
url = urlunsplit(parts)
response['Location'] = url
response.status_code = 302
return response
- else:
- msg = _('No next parameter')
- messages.add_message(request, messages.ERROR, msg)
- url = reverse('astakos.im.views.index')
- return redirect(url)
+ renew = request.GET.get('renew', None)
+ if renew == '':
+ request.user.renew_token()
+ try:
+ request.user.save()
+ except ValidationError, e:
+ return HttpResponseBadRequest(e)
+ # authenticate before login
+ user = authenticate(email=request.user.email, auth_token=request.user.auth_token)
+ auth_login(request, user)
+ set_cookie(response, user)
+ logger.info('Token reset for %s' % request.user.email)
+ parts = list(urlsplit(next))
+ parts[3] = urlencode({'user': request.user.email, 'token': request.user.auth_token})
+ url = urlunsplit(parts)
+ response['Location'] = url
+ response.status_code = 302
+ return response
else:
- # redirect to login with self as next
- url = reverse('astakos.im.views.index')
- url = '%s?next=%s' % (url, quote(request.build_absolute_uri()))
- return redirect(url)
+ # redirect to login with next the request path
+
+ # first build next parameter
+ parts = list(urlsplit(request.build_absolute_uri()))
+ params = dict(parse_qsl(parts[3], keep_blank_values=True))
+ # delete force parameter
+ if 'force' in params:
+ del params['force']
+ parts[3] = urlencode(params)
+ next = urlunsplit(parts)
+
+ # build url location
+ parts[2] = reverse('astakos.im.views.index')
+ params = {'next':next}
+ parts[3] = urlencode(params)
+ url = urlunsplit(parts)
+ response['Location'] = url
+ response.status_code = 302
+ return response
\ No newline at end of file