|
38
|
1 |
import re |
|
|
2 |
from django.conf import settings |
|
|
3 |
from django.contrib.auth import REDIRECT_FIELD_NAME |
|
|
4 |
# Avoid shadowing the login() view below. |
|
|
5 |
from django.contrib.auth import login as auth_login |
|
|
6 |
from django.contrib.auth.decorators import login_required |
|
|
7 |
from django.contrib.auth.forms import AuthenticationForm |
|
|
8 |
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm, PasswordChangeForm |
|
|
9 |
from django.contrib.auth.tokens import default_token_generator |
|
|
10 |
from django.views.decorators.csrf import csrf_protect |
|
|
11 |
from django.core.urlresolvers import reverse |
|
|
12 |
from django.shortcuts import render_to_response, get_object_or_404 |
|
|
13 |
from django.contrib.sites.models import Site, RequestSite |
|
|
14 |
from django.http import HttpResponseRedirect, Http404 |
|
|
15 |
from django.template import RequestContext |
|
|
16 |
from django.utils.http import urlquote, base36_to_int |
|
|
17 |
from django.utils.translation import ugettext as _ |
|
|
18 |
from django.contrib.auth.models import User |
|
|
19 |
from django.views.decorators.cache import never_cache |
|
|
20 |
|
|
|
21 |
@csrf_protect |
|
|
22 |
@never_cache |
|
|
23 |
def login(request, template_name='registration/login.html', |
|
|
24 |
redirect_field_name=REDIRECT_FIELD_NAME, |
|
|
25 |
authentication_form=AuthenticationForm): |
|
|
26 |
"""Displays the login form and handles the login action.""" |
|
|
27 |
|
|
|
28 |
redirect_to = request.REQUEST.get(redirect_field_name, '') |
|
|
29 |
|
|
|
30 |
if request.method == "POST": |
|
|
31 |
form = authentication_form(data=request.POST) |
|
|
32 |
if form.is_valid(): |
|
|
33 |
# Light security check -- make sure redirect_to isn't garbage. |
|
|
34 |
if not redirect_to or ' ' in redirect_to: |
|
|
35 |
redirect_to = settings.LOGIN_REDIRECT_URL |
|
|
36 |
|
|
|
37 |
# Heavier security check -- redirects to http://example.com should |
|
|
38 |
# not be allowed, but things like /view/?param=http://example.com |
|
|
39 |
# should be allowed. This regex checks if there is a '//' *before* a |
|
|
40 |
# question mark. |
|
|
41 |
elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to): |
|
|
42 |
redirect_to = settings.LOGIN_REDIRECT_URL |
|
|
43 |
|
|
|
44 |
# Okay, security checks complete. Log the user in. |
|
|
45 |
auth_login(request, form.get_user()) |
|
|
46 |
|
|
|
47 |
if request.session.test_cookie_worked(): |
|
|
48 |
request.session.delete_test_cookie() |
|
|
49 |
|
|
|
50 |
return HttpResponseRedirect(redirect_to) |
|
|
51 |
|
|
|
52 |
else: |
|
|
53 |
form = authentication_form(request) |
|
|
54 |
|
|
|
55 |
request.session.set_test_cookie() |
|
|
56 |
|
|
|
57 |
if Site._meta.installed: |
|
|
58 |
current_site = Site.objects.get_current() |
|
|
59 |
else: |
|
|
60 |
current_site = RequestSite(request) |
|
|
61 |
|
|
|
62 |
return render_to_response(template_name, { |
|
|
63 |
'form': form, |
|
|
64 |
redirect_field_name: redirect_to, |
|
|
65 |
'site': current_site, |
|
|
66 |
'site_name': current_site.name, |
|
|
67 |
}, context_instance=RequestContext(request)) |
|
|
68 |
|
|
|
69 |
def logout(request, next_page=None, template_name='registration/logged_out.html', redirect_field_name=REDIRECT_FIELD_NAME): |
|
|
70 |
"Logs out the user and displays 'You are logged out' message." |
|
|
71 |
from django.contrib.auth import logout |
|
|
72 |
logout(request) |
|
|
73 |
if next_page is None: |
|
|
74 |
redirect_to = request.REQUEST.get(redirect_field_name, '') |
|
|
75 |
if redirect_to: |
|
|
76 |
return HttpResponseRedirect(redirect_to) |
|
|
77 |
else: |
|
|
78 |
return render_to_response(template_name, { |
|
|
79 |
'title': _('Logged out') |
|
|
80 |
}, context_instance=RequestContext(request)) |
|
|
81 |
else: |
|
|
82 |
# Redirect to this page until the session has been cleared. |
|
|
83 |
return HttpResponseRedirect(next_page or request.path) |
|
|
84 |
|
|
|
85 |
def logout_then_login(request, login_url=None): |
|
|
86 |
"Logs out the user if he is logged in. Then redirects to the log-in page." |
|
|
87 |
if not login_url: |
|
|
88 |
login_url = settings.LOGIN_URL |
|
|
89 |
return logout(request, login_url) |
|
|
90 |
|
|
|
91 |
def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): |
|
|
92 |
"Redirects the user to the login page, passing the given 'next' page" |
|
|
93 |
if not login_url: |
|
|
94 |
login_url = settings.LOGIN_URL |
|
|
95 |
return HttpResponseRedirect('%s?%s=%s' % (login_url, urlquote(redirect_field_name), urlquote(next))) |
|
|
96 |
|
|
|
97 |
# 4 views for password reset: |
|
|
98 |
# - password_reset sends the mail |
|
|
99 |
# - password_reset_done shows a success message for the above |
|
|
100 |
# - password_reset_confirm checks the link the user clicked and |
|
|
101 |
# prompts for a new password |
|
|
102 |
# - password_reset_complete shows a success message for the above |
|
|
103 |
|
|
|
104 |
@csrf_protect |
|
|
105 |
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', |
|
|
106 |
email_template_name='registration/password_reset_email.html', |
|
|
107 |
password_reset_form=PasswordResetForm, token_generator=default_token_generator, |
|
|
108 |
post_reset_redirect=None): |
|
|
109 |
if post_reset_redirect is None: |
|
|
110 |
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done') |
|
|
111 |
if request.method == "POST": |
|
|
112 |
form = password_reset_form(request.POST) |
|
|
113 |
if form.is_valid(): |
|
|
114 |
opts = {} |
|
|
115 |
opts['use_https'] = request.is_secure() |
|
|
116 |
opts['token_generator'] = token_generator |
|
|
117 |
if is_admin_site: |
|
|
118 |
opts['domain_override'] = request.META['HTTP_HOST'] |
|
|
119 |
else: |
|
|
120 |
opts['email_template_name'] = email_template_name |
|
|
121 |
if not Site._meta.installed: |
|
|
122 |
opts['domain_override'] = RequestSite(request).domain |
|
|
123 |
form.save(**opts) |
|
|
124 |
return HttpResponseRedirect(post_reset_redirect) |
|
|
125 |
else: |
|
|
126 |
form = password_reset_form() |
|
|
127 |
return render_to_response(template_name, { |
|
|
128 |
'form': form, |
|
|
129 |
}, context_instance=RequestContext(request)) |
|
|
130 |
|
|
|
131 |
def password_reset_done(request, template_name='registration/password_reset_done.html'): |
|
|
132 |
return render_to_response(template_name, context_instance=RequestContext(request)) |
|
|
133 |
|
|
|
134 |
# Doesn't need csrf_protect since no-one can guess the URL |
|
|
135 |
def password_reset_confirm(request, uidb36=None, token=None, template_name='registration/password_reset_confirm.html', |
|
|
136 |
token_generator=default_token_generator, set_password_form=SetPasswordForm, |
|
|
137 |
post_reset_redirect=None): |
|
|
138 |
""" |
|
|
139 |
View that checks the hash in a password reset link and presents a |
|
|
140 |
form for entering a new password. |
|
|
141 |
""" |
|
|
142 |
assert uidb36 is not None and token is not None # checked by URLconf |
|
|
143 |
if post_reset_redirect is None: |
|
|
144 |
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_complete') |
|
|
145 |
try: |
|
|
146 |
uid_int = base36_to_int(uidb36) |
|
|
147 |
except ValueError: |
|
|
148 |
raise Http404 |
|
|
149 |
|
|
|
150 |
user = get_object_or_404(User, id=uid_int) |
|
|
151 |
context_instance = RequestContext(request) |
|
|
152 |
|
|
|
153 |
if token_generator.check_token(user, token): |
|
|
154 |
context_instance['validlink'] = True |
|
|
155 |
if request.method == 'POST': |
|
|
156 |
form = set_password_form(user, request.POST) |
|
|
157 |
if form.is_valid(): |
|
|
158 |
form.save() |
|
|
159 |
return HttpResponseRedirect(post_reset_redirect) |
|
|
160 |
else: |
|
|
161 |
form = set_password_form(None) |
|
|
162 |
else: |
|
|
163 |
context_instance['validlink'] = False |
|
|
164 |
form = None |
|
|
165 |
context_instance['form'] = form |
|
|
166 |
return render_to_response(template_name, context_instance=context_instance) |
|
|
167 |
|
|
|
168 |
def password_reset_complete(request, template_name='registration/password_reset_complete.html'): |
|
|
169 |
return render_to_response(template_name, context_instance=RequestContext(request, |
|
|
170 |
{'login_url': settings.LOGIN_URL})) |
|
|
171 |
|
|
|
172 |
@csrf_protect |
|
|
173 |
@login_required |
|
|
174 |
def password_change(request, template_name='registration/password_change_form.html', |
|
|
175 |
post_change_redirect=None, password_change_form=PasswordChangeForm): |
|
|
176 |
if post_change_redirect is None: |
|
|
177 |
post_change_redirect = reverse('django.contrib.auth.views.password_change_done') |
|
|
178 |
if request.method == "POST": |
|
|
179 |
form = password_change_form(user=request.user, data=request.POST) |
|
|
180 |
if form.is_valid(): |
|
|
181 |
form.save() |
|
|
182 |
return HttpResponseRedirect(post_change_redirect) |
|
|
183 |
else: |
|
|
184 |
form = password_change_form(user=request.user) |
|
|
185 |
return render_to_response(template_name, { |
|
|
186 |
'form': form, |
|
|
187 |
}, context_instance=RequestContext(request)) |
|
|
188 |
|
|
|
189 |
def password_change_done(request, template_name='registration/password_change_done.html'): |
|
|
190 |
return render_to_response(template_name, context_instance=RequestContext(request)) |