1 # -*- coding: utf-8 -*-
3 # portal/views.py: views for the portal application
4 # This file is part of the Manifold project.
7 # Mohammed Yasin Rahman <mohammed-yasin.rahman@lip6.fr>
8 # Copyright 2014, UPMC Sorbonne Universités / LIP6
10 # This program is free software; you can redistribute it and/or modify it under
11 # the terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 3, or (at your option) any later version.
14 # This program is distributed in the hope that it will be useful, but WITHOUT
15 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 # You should have received a copy of the GNU General Public License along with
20 # this program; see the file COPYING. If not, write to the Free Software
21 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 Allows a user to reset their password by generating a one-time use link that can be used to reset the password, and sending that link to the user's
31 registered email address.
33 If the email address provided does not exist in the system, this view won't send an email, but the user won't receive any error message either.
34 This prevents information leaking to potential attackers. If you want to provide an error message in this case, you can subclass PasswordResetForm
35 and use the password_reset_form argument.
37 Users flagged with an unusable password - see set_unusable_password() - aren't allowed to request a password reset to prevent misuse when using an external
38 authentication source like LDAP. Note that they won't receive any error message since this would expose their account's existence but no mail will be sent either.
40 More Detail: https://docs.djangoproject.com/en/dev/topics/auth/default/#topics-auth-creating-users
46 from urllib.parse import urlparse, urlunparse
47 except ImportError: # Python 2
48 from urlparse import urlparse, urlunparse
50 from django.conf import settings
51 from django.core.urlresolvers import reverse
52 from django.http import HttpResponseRedirect, QueryDict
53 from django.template.response import TemplateResponse
54 from django.utils.http import base36_to_int, is_safe_url
55 from django.utils.translation import ugettext as _
56 from django.shortcuts import resolve_url
57 from django.views.decorators.debug import sensitive_post_parameters
58 from django.views.decorators.cache import never_cache
59 from django.views.decorators.csrf import csrf_protect
61 # Avoid shadowing the login() and logout() views below.
62 from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout as auth_logout, get_user_model
63 from django.contrib.auth.decorators import login_required
64 from portal.forms import PasswordResetForm, SetPasswordForm
65 from django.contrib.auth.tokens import default_token_generator
66 from django.contrib.sites.models import get_current_site
67 from django.contrib.auth.hashers import identify_hasher
73 from random import choice
75 from django.contrib import messages
76 from django.views.generic import View
77 from django.shortcuts import render
78 from django.http import HttpResponse, HttpResponseRedirect
80 from unfold.loginrequired import FreeAccessView
81 from ui.topmenu import topmenu_items_live
83 from manifoldapi.manifoldapi import execute_admin_query
84 from manifold.core.query import Query
85 from portal.actions import manifold_update_user
87 from portal.forms import PassResetForm
88 from portal.actions import manifold_update_user
90 from myslice.theme import ThemeView
92 # 4 views for password reset:
93 # - password_reset sends the mail
94 # - password_reset_done shows a success message for the above
95 # - password_reset_confirm checks the link the user clicked and
96 # prompts for a new password
97 # - password_reset_complete shows a success message for the above
100 def password_reset(request, is_admin_site=False,
101 template_name='password_reset_form.html',
102 email_template_name='password_reset_email.html',
103 subject_template_name='registration/password_reset_subject.txt',
104 password_reset_form=PasswordResetForm,
105 token_generator=default_token_generator,
106 post_reset_redirect=None,
111 themeview = ThemeView()
112 themeview.template_name = template_name
114 if post_reset_redirect is None:
115 post_reset_redirect = reverse('portal.django_passresetview.password_reset_done')
116 if request.method == "POST":
117 form = password_reset_form(request.POST)
120 ### email check in manifold DB ###
121 email = form.cleaned_data['email'].lower() # email inserted on the form
122 user_query = Query().get('local:user').select('user_id','email')
123 user_details = execute_admin_query(request, user_query)
125 for user_detail in user_details:
126 if user_detail['email']==email:
131 messages.error(request, 'Sorry, this email is not registered.')
134 'theme': themeview.theme
136 return TemplateResponse(request, themeview.template, context,current_app=current_app)
138 ### end of email check in manifold ###
141 'use_https': request.is_secure(),
142 'token_generator': token_generator,
143 'from_email': from_email,
144 'email_template_name': email_template_name,
145 'subject_template_name': subject_template_name,
149 opts = dict(opts, domain_override=request.get_host())
151 return HttpResponseRedirect(post_reset_redirect)
153 form = password_reset_form()
156 'theme': themeview.theme
158 if extra_context is not None:
159 context.update(extra_context)
160 return TemplateResponse(request, themeview.template, context,
161 current_app=current_app)
164 def password_reset_done(request,
165 template_name='password_reset_done.html',
166 current_app=None, extra_context=None):
167 themeview = ThemeView()
168 themeview.template_name = template_name
170 'theme' : themeview.theme
172 if extra_context is not None:
173 context.update(extra_context)
174 return TemplateResponse(request, themeview.template, context,
175 current_app=current_app)
178 # Doesn't need csrf_protect since no-one can guess the URL
179 @sensitive_post_parameters()
181 def password_reset_confirm(request, uidb36=None, token=None,
182 template_name='password_reset_confirm.html',
183 token_generator=default_token_generator,
184 set_password_form=SetPasswordForm,
185 post_reset_redirect=None,
186 current_app=None, extra_context=None):
188 View that checks the hash in a password reset link and presents a
189 form for entering a new password.
191 themeview = ThemeView()
192 themeview.template_name = template_name
194 UserModel = get_user_model()
195 assert uidb36 is not None and token is not None # checked by URLconf
196 if post_reset_redirect is None:
197 post_reset_redirect = reverse('portal.django_passresetview.password_reset_complete')
199 uid_int = base36_to_int(uidb36)
200 user = UserModel._default_manager.get(pk=uid_int)
201 except (ValueError, OverflowError, UserModel.DoesNotExist):
204 if user is not None and token_generator.check_token(user, token):
206 if request.method == 'POST':
207 form = set_password_form(user, request.POST)
210 ### manifold pass update ###
211 #password = form.cleaned_data('password1')
212 password=request.POST['new_password1']
213 #user_query = Query().get('local:user').select('user_id','email','password')
214 #user_details = execute_admin_query(request, user_query)
215 #for user_detail in user_details:
216 # if user_detail['email'] == user.email:
217 # user_detail['password'] = password
218 #updating password in local:user
219 user_params = { 'password': password}
220 manifold_update_user(request,user.email,user_params)
221 ### end of manifold pass update ###
225 return HttpResponseRedirect(post_reset_redirect)
227 form = set_password_form(None)
233 'validlink': validlink,
234 'theme' : themeview.theme
236 if extra_context is not None:
237 context.update(extra_context)
238 return TemplateResponse(request, themeview.template, context,
239 current_app=current_app)
242 def password_reset_complete(request,
243 template_name='password_reset_complete.html',
244 current_app=None, extra_context=None):
245 themeview = ThemeView()
246 themeview.template_name = template_name
248 'login_url': resolve_url(settings.LOGIN_URL),
249 'theme' : themeview.theme
251 if extra_context is not None:
252 context.update(extra_context)
253 return TemplateResponse(request, themeview.template, context,
254 current_app=current_app)