b2e54f25a0da4a47225cb9584f21666d215f58e2
[django-cas-provider.git] / cas_provider / views.py
1 from django.conf import settings
2 from django.contrib.auth import login as auth_login, \
3     logout as auth_logout
4 from django.http import HttpResponse, HttpResponseRedirect
5 from django.shortcuts import render_to_response
6 from django.template import RequestContext
7 from forms import LoginForm
8 from models import ServiceTicket, LoginTicket
9
10
11 __all__ = ['login', 'validate', 'logout', 'service_validate']
12
13
14 INVALID_TICKET = 1
15 INVALID_SERVICE = 2
16 INVALID_REQUEST = 3
17
18 ERROR_MESSAGES = (
19     (INVALID_TICKET, u'The provided ticket is invalid.'),
20     (INVALID_SERVICE, u'Service is invalid'),
21     (INVALID_REQUEST, u'Not all required parameters were sent.'),
22 )
23
24
25 def login(request, template_name='cas/login.html', \
26                 success_redirect=settings.LOGIN_REDIRECT_URL,
27                 warn_template_name='cas/warn.html'):
28     service = request.GET.get('service', None)
29     if request.user.is_authenticated():
30         if service is not None:
31             if request.GET.get('warn', False):
32                 return render_to_response(warn_template_name, {
33                     'service': service,
34                     'warn': False
35                 }, context_instance=RequestContext(request))
36             ticket = ServiceTicket.objects.create(service=service, user=request.user)
37             return HttpResponseRedirect(ticket.get_redirect_url())
38         else:
39             return HttpResponseRedirect(success_redirect)
40     if request.method == 'POST':
41         form = LoginForm(request.POST)
42         if form.is_valid():
43             user = form.get_user()
44             auth_login(request, user)
45             service = form.cleaned_data.get('service')
46             if service is not None:
47                 ticket = ServiceTicket.objects.create(service=service, user=user)
48                 success_redirect = ticket.get_redirect_url()
49             return HttpResponseRedirect(success_redirect)
50     else:
51         form = LoginForm(initial={
52             'service': service,
53             'lt': LoginTicket.objects.create()
54         })
55     return render_to_response(template_name, {
56         'form': form,
57         'errors': form.get_errors()
58     }, context_instance=RequestContext(request))
59
60
61 def validate(request):
62     """Validate ticket via CAS v.1 protocol"""
63     service = request.GET.get('service', None)
64     ticket_string = request.GET.get('ticket', None)
65     if service is not None and ticket_string is not None:
66         try:
67             ticket = ServiceTicket.objects.get(ticket=ticket_string)
68             username = ticket.user.username
69             ticket.delete()
70             return HttpResponse("yes\n%s\n" % username)
71         except:
72             pass
73     return HttpResponse("no\n\n")
74
75
76 def logout(request, template_name='cas/logout.html'):
77     url = request.GET.get('url', None)
78     auth_logout(request)
79     return render_to_response(template_name, {'url': url}, \
80                               context_instance=RequestContext(request))
81
82
83 def service_validate(request):
84     """Validate ticket via CAS v.2 protocol"""
85     service = request.GET.get('service', None)
86     ticket_string = request.GET.get('ticket', None)
87     if service is None or ticket_string is None:
88         return _cas2_error_response(INVALID_REQUEST)
89
90     try:
91         ticket = ServiceTicket.objects.get(ticket=ticket_string)
92     except ServiceTicket.DoesNotExist:
93         return _cas2_error_response(INVALID_TICKET)
94
95     if settings.CAS_CHECK_SERVICE and ticket.service != service:
96         ticket.delete()
97         return _cas2_error_response(INVALID_SERVICE)
98
99     username = ticket.user.username
100     ticket.delete()
101     return _cas2_sucess_response(username)
102
103
104 def _cas2_error_response(code):
105     return HttpResponse(u''''<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
106             <cas:authenticationFailure code="%(code)s">
107                 %(message)s
108             </cas:authenticationFailure>
109         </cas:serviceResponse>''' % {
110             'code': code,
111             'message': dict(ERROR_MESSAGES).get(code)
112     }, mimetype='text/xml')
113
114
115 def _cas2_sucess_response(username):
116     return HttpResponse(u'''<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
117         <cas:authenticationSuccess>
118             <cas:user>%(username)s</cas:user>
119         </cas:authenticationSuccess>
120     </cas:serviceResponse>''' % {'username': username}, mimetype='text/xml')