-
Notifications
You must be signed in to change notification settings - Fork 0
/
login.py
149 lines (124 loc) · 5.65 KB
/
login.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from django.contrib import auth
from django.core.urlresolvers import reverse
from django.utils.http import urlquote
from django.http import HttpResponseRedirect
from django.template import RequestContext
from menclave import settings as settings
from menclave.urls import get_default_route
from menclave.aenclave.html import html_error, render_html_template
from menclave.aenclave.json_response import json_error
from menclave.aenclave.xml import xml_error
#------------------------------- Permissions --------------------------------#
def get_anon_user():
username = settings.ANONYMOUS_USER
try:
anon = auth.models.User.objects.get(username = username)
except auth.models.User.DoesNotExist:
anon = auth.models.User.objects.create_user(username, '', '')
anon.set_unusable_password()
anon.save()
return anon
def permission_required(perm, action, erf=html_error, perm_fail_erf=None):
"""
Requre the user to have a permission or display an error message.
perm - Permission to check.
action - the type of action attempted
erf - Error return function, takes request, text, title.
perm_fail_erf - define this to use a different erf for permissions
failures.
"""
if perm_fail_erf is None:
perm_fail_erf = erf
def decorator(real_handler):
def request_handler(request, *args, **kwargs):
if not request.user.is_authenticated():
# Check if the anonymous user has access.
anon = get_anon_user()
if anon.has_perm(perm):
return real_handler(request, *args, **kwargs)
# Otherwise, show error message.
error_text = ('You must <a href="%s">log in</a> to do that.' %
reverse('menclave-login'))
return erf(request, error_text, action)
elif not request.user.has_perm(perm):
# Check if the anonymous user has access.
anon = get_anon_user()
if anon.has_perm(perm):
return real_handler(request, *args, **kwargs)
# Otherwise, show error message.
error_text = ('You need more permissions to do that.')
return perm_fail_erf(request, error_text, action)
else:
return real_handler(request, *args, **kwargs)
return request_handler
return decorator
def permission_required_redirect(perm, redirect_field_name):
"""
Mimicks functionality of django.contrib.auth.permission_required
"""
def erf(request, error_text, action):
path = urlquote(request.get_full_path())
tup = settings.LOGIN_URL, redirect_field_name, path
return HttpResponseRedirect('%s?%s=%s' % tup)
return permission_required(perm, '', erf, html_error)
def permission_required_xml(perm):
return permission_required(perm, '', lambda r,text,act: xml_error(text))
def permission_required_json(perm):
return permission_required(perm, '', lambda r,text,act: json_error(text))
#------------------------------- Login/Logout --------------------------------#
def login(request):
form = request.POST
## If not using SSL, try redirecting.
#if not request.is_secure():
#url = 'https' + request.build_absolute_uri()[4:]
#return HttpResponseRedirect(url)
# First try SSL Authentication
user = auth.authenticate(request=request)
# Otherwise, treat this like a text login and show the login page if
# necessary.
if user is None:
# If the user isn't trying to log in, then just display the login page.
if not form.get('login', False):
goto = request.GET.get('goto', None)
if not goto:
# The Django login_required decorator passes 'next' as the
# redirect, so we look for that if 'goto' is missing.
goto = request.GET.get('next', None)
context = RequestContext(request)
return render_html_template('login.html', request,
{'redirect_to': goto},
context_instance=context)
# Check if the username and password are correct.
user = auth.authenticate(username=form.get('username', ''),
password=form.get('password', ''))
# If the username/password are invalid or SSL authentication failed tell
# the user to try again.
error_message = ''
if user is None:
error_message = 'Invalid username/password.'
# If the user account is disabled, then no dice.
elif not user.is_active:
error_message = ('The user account for <tt>%s</tt> has been disabled.' %
user.username)
if error_message:
return render_html_template('login.html', request,
{'error_message': error_message,
'redirect_to': form.get('goto', None)},
context_instance=RequestContext(request))
# Otherwise, we're good to go, so log the user in.
auth.login(request, user)
# hack to try to pass them back to http land
default_route = get_default_route()
goto = request.REQUEST.get('goto', default_route)
# hack to prevent infinite loop.
if goto == '':
goto = default_route
if goto.startswith('https'):
goto = goto.replace('^https', 'http')
return HttpResponseRedirect(goto)
def logout(request):
auth.logout(request)
# TODO(rryan) remove aenclave specificity
default_route = get_default_route()
goto = request.REQUEST.get('goto', default_route)
return HttpResponseRedirect(goto)