Restrict next url parameter
[astakos] / snf-astakos-app / astakos / im / target / redirect.py
index 19784c3..82ae1db 100644 (file)
@@ -36,29 +36,41 @@ from django.shortcuts import redirect
 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, logout
-from django.http import HttpResponse, HttpResponseBadRequest
+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, urlparse, parse_qsl
 
 from astakos.im.settings import COOKIE_NAME, COOKIE_DOMAIN
-from astakos.im.util import set_cookie, has_signed_terms
+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 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.
+    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 == '':
@@ -67,7 +79,7 @@ def login(request):
     if request.user.is_authenticated():
         # if user has not signed the approval terms
         # redirect to approval terms with next the request path
-        if not has_signed_terms(request.user):
+        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))
@@ -86,8 +98,10 @@ def login(request):
         renew = request.GET.get('renew', None)
         if renew == '':
             request.user.renew_token()
-            request.user.save()
-            
+            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)