Merge branch 'with-dvcs'
[redakcja.git] / apps / django_cas / views.py
1 """CAS login/logout replacement views"""
2
3 from urllib import urlencode
4 from urlparse import urljoin
5
6 from django.http import get_host, HttpResponseRedirect, HttpResponseForbidden
7 from django.conf import settings
8 from django.contrib.auth import REDIRECT_FIELD_NAME
9
10 __all__ = ['login', 'logout']
11
12
13 def _service_url(request, redirect_to=None):
14     """Generates application service URL for CAS"""
15
16     protocol = ('http://', 'https://')[request.is_secure()]
17     host = get_host(request)
18     service = protocol + host + request.path
19     if redirect_to:
20         if '?' in service:
21             service += '&'
22         else:
23             service += '?'
24         service += urlencode({REDIRECT_FIELD_NAME: redirect_to.encode('utf-8')})
25     return service
26
27
28 def _redirect_url(request):
29     """Redirects to referring page, or CAS_REDIRECT_URL if no referrer is
30     set.
31     """
32
33     next = request.GET.get(REDIRECT_FIELD_NAME)
34     if not next:
35         if settings.CAS_IGNORE_REFERER:
36             next = settings.CAS_REDIRECT_URL
37         else:
38             next = request.META.get('HTTP_REFERER', settings.CAS_REDIRECT_URL)
39         prefix = (('http://', 'https://')[request.is_secure()] +
40                   get_host(request))
41         if next.startswith(prefix):
42             next = next[len(prefix):]
43     return next
44
45
46 def _login_url(service):
47     """Generates CAS login URL"""
48
49     params = {'service': service}
50     if settings.CAS_EXTRA_LOGIN_PARAMS:
51         params.update(settings.CAS_EXTRA_LOGIN_PARAMS)
52     return urljoin(settings.CAS_SERVER_URL, 'login') + '?' + urlencode(params)
53
54
55 def _logout_url(request, next_page=None):
56     """Generates CAS logout URL"""
57
58     url = urljoin(settings.CAS_SERVER_URL, 'logout')
59     if next_page:
60         protocol = ('http://', 'https://')[request.is_secure()]
61         host = get_host(request)
62         url += '?' + urlencode({'url': protocol + host + next_page})
63     return url
64
65
66 def login(request, next_page=None, required=False):
67     """Forwards to CAS login URL or verifies CAS ticket"""
68
69     print "LOGIN original NEXT_PAGE:", next_page
70     print request.GET
71     if not next_page:
72         next_page = _redirect_url(request)
73     print "LOGIN redirect NEXT_PAGE:", next_page
74
75     if request.user.is_authenticated():
76         message = "You are logged in as %s." % request.user.username
77         request.user.message_set.create(message=message)
78         return HttpResponseRedirect(next_page)
79     ticket = request.GET.get('ticket')
80     service = _service_url(request, next_page)
81     print "TICKET: ", ticket
82     print "SERVICE: ", service
83     if ticket:
84         from django.contrib import auth
85         user = auth.authenticate(ticket=ticket, service=service)
86         if user is not None:
87             auth.login(request, user)
88             name = user.first_name or user.username
89             message = "Login succeeded. Welcome, %s." % name
90             user.message_set.create(message=message)
91             return HttpResponseRedirect(next_page)
92         elif settings.CAS_RETRY_LOGIN or required:
93             return HttpResponseRedirect(_login_url(service))
94         else:
95             error = "<h1>Forbidden</h1><p>Login failed.</p>"
96             return HttpResponseForbidden(error)
97
98     else:
99         return HttpResponseRedirect(_login_url(service))
100
101
102 def logout(request, next_page=None):
103     """Redirects to CAS logout page"""
104
105     from django.contrib.auth import logout
106     logout(request)
107     if not next_page:
108         next_page = _redirect_url(request)
109     if settings.CAS_LOGOUT_COMPLETELY:
110         return HttpResponseRedirect(_logout_url(request, next_page))
111     else:
112         return HttpResponseRedirect(next_page)