|
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)) |