New CAS client
[redakcja.git] / apps / django_cas / views.py
diff --git a/apps/django_cas/views.py b/apps/django_cas/views.py
new file mode 100755 (executable)
index 0000000..110c646
--- /dev/null
@@ -0,0 +1,111 @@
+"""CAS login/logout replacement views"""
+
+from urllib import urlencode
+from urlparse import urljoin
+
+from django.http import get_host, HttpResponseRedirect, HttpResponseForbidden
+from django.conf import settings
+from django.contrib.auth import REDIRECT_FIELD_NAME
+
+__all__ = ['login', 'logout']
+
+def _service_url(request, redirect_to = None):
+    """Generates application service URL for CAS"""
+
+    protocol = ('http://', 'https://')[request.is_secure()]
+    host = get_host(request)
+    service = protocol + host + request.path
+    if redirect_to:
+        if '?' in service:
+            service += '&'
+        else:
+            service += '?'
+        service += urlencode({REDIRECT_FIELD_NAME: redirect_to.encode('utf-8')})
+    return service
+
+
+def _redirect_url(request):
+    """Redirects to referring page, or CAS_REDIRECT_URL if no referrer is
+    set.
+    """
+
+    next = request.GET.get(REDIRECT_FIELD_NAME)
+    if not next:
+        if settings.CAS_IGNORE_REFERER:
+            next = settings.CAS_REDIRECT_URL
+        else:
+            next = request.META.get('HTTP_REFERER', settings.CAS_REDIRECT_URL)
+        prefix = (('http://', 'https://')[request.is_secure()] +
+                  get_host(request))
+        if next.startswith(prefix):
+            next = next[len(prefix):]
+    return next
+
+
+def _login_url(service):
+    """Generates CAS login URL"""
+
+    params = {'service': service}
+    if settings.CAS_EXTRA_LOGIN_PARAMS:
+        params.update(settings.CAS_EXTRA_LOGIN_PARAMS)
+    return urljoin(settings.CAS_SERVER_URL, 'login') + '?' + urlencode(params)
+
+
+def _logout_url(request, next_page = None):
+    """Generates CAS logout URL"""
+
+    url = urljoin(settings.CAS_SERVER_URL, 'logout')
+    if next_page:
+        protocol = ('http://', 'https://')[request.is_secure()]
+        host = get_host(request)
+        url += '?' + urlencode({'url': protocol + host + next_page})
+    return url
+
+
+def login(request, next_page = None, required = False):
+    """Forwards to CAS login URL or verifies CAS ticket"""
+
+    print "LOGIN original NEXT_PAGE:", next_page
+    print request.GET
+    if not next_page:
+        next_page = _redirect_url(request)
+    print "LOGIN redirect NEXT_PAGE:", next_page
+
+    if request.user.is_authenticated():
+        message = "You are logged in as %s." % request.user.username
+        request.user.message_set.create(message = message)
+        return HttpResponseRedirect(next_page)
+    ticket = request.GET.get('ticket')
+    service = _service_url(request, next_page)
+    print "TICKET", ticket
+    print "SERVICE", service
+    if ticket:
+        from django.contrib import auth
+        user = auth.authenticate(ticket = ticket, service = service)
+        if user is not None:
+            auth.login(request, user)
+            name = user.first_name or user.username
+            message = "Login succeeded. Welcome, %s." % name
+            user.message_set.create(message = message)
+            return HttpResponseRedirect(next_page)
+        elif settings.CAS_RETRY_LOGIN or required:
+            return HttpResponseRedirect(_login_url(service))
+        else:
+            error = "<h1>Forbidden</h1><p>Login failed.</p>"
+            return HttpResponseForbidden(error)
+
+    else:
+        return HttpResponseRedirect(_login_url(service))
+
+
+def logout(request, next_page = None):
+    """Redirects to CAS logout page"""
+
+    from django.contrib.auth import logout
+    logout(request)
+    if not next_page:
+        next_page = _redirect_url(request)
+    if settings.CAS_LOGOUT_COMPLETELY:
+        return HttpResponseRedirect(_logout_url(request, next_page))
+    else:
+        return HttpResponseRedirect(next_page)