Working on change password form

This commit is contained in:
Eskil Heyn Olsen
2013-01-11 22:35:54 -08:00
parent c5c27768f2
commit 9a47ec1ed9
5 changed files with 89 additions and 10 deletions
+8 -3
View File
@@ -97,7 +97,8 @@ _default_messages = {
'DISABLED_ACCOUNT': ('Account is disabled.', 'error'),
'PASSWORDLESS_LOGIN_SUCCESSFUL': ('You have successfuly logged in.', 'success'),
'PASSWORD_RESET': ('You successfully reset your password and you have been logged in automatically.', 'success'),
'PASSWORD_CHANGE': ('You successfully changes your password.', 'success'),
'PASSWORD_CHANGE': ('You successfully changed your password.', 'success'),
'INVALID_PASSWORD': ('Invalid password', 'error'),
'LOGIN': ('Please log in to access this page.', 'info'),
'REFRESH': ('Please reauthenticate to access this page.', 'info')
}
@@ -294,6 +295,9 @@ class _SecurityState(object):
def reset_password_context_processor(self, fn):
self._add_ctx_processor('reset_password', fn)
def change_password_context_processor(self, fn):
self._add_ctx_processor('change_password', fn)
def send_confirmation_context_processor(self, fn):
self._add_ctx_processor('send_confirmation', fn)
@@ -323,8 +327,8 @@ class Security(object):
def init_app(self, app, datastore=None, register_blueprint=True,
login_form=None, confirm_register_form=None,
register_form=None, forgot_password_form=None,
reset_password_form=None, send_confirmation_form=None,
passwordless_login_form=None):
reset_password_form=None, change_password_form=None,
send_confirmation_form=None, passwordless_login_form=None):
"""Initializes the Flask-Security extension for the specified
application and datastore implentation.
@@ -348,6 +352,7 @@ class Security(object):
register_form=register_form,
forgot_password_form=forgot_password_form,
reset_password_form=reset_password_form,
change_password_form=change_password_form,
send_confirmation_form=send_confirmation_form,
passwordless_login_form=passwordless_login_form)
+21 -4
View File
@@ -15,10 +15,11 @@ from flask import request, current_app
from flask.ext.wtf import Form as BaseForm, TextField, PasswordField, \
SubmitField, HiddenField, Required, BooleanField, EqualTo, Email, \
ValidationError, Length, Field
from flask.ext.login import current_user
from werkzeug.local import LocalProxy
from .confirmable import requires_confirmation
from .utils import verify_and_update_password, get_message
from .utils import verify_password, verify_and_update_password, get_message
# Convenient reference
_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
@@ -83,6 +84,7 @@ class NewPasswordFormMixin():
validators=[password_required,
Length(min=6, max=128)])
class PasswordConfirmFormMixin():
password_confirm = PasswordField("Retype Password",
validators=[EqualTo('password', message="Passwords do not match")])
@@ -97,7 +99,8 @@ class RegisterFormMixin():
def to_dict(form):
def is_field_and_user_attr(member):
return isinstance(member, Field) and hasattr(_datastore.user_model, member.name)
return isinstance(member, Field) and \
hasattr(_datastore.user_model, member.name)
fields = inspect.getmembers(form, is_field_and_user_attr)
return dict((key, value.data) for key, value in fields)
@@ -172,7 +175,7 @@ class LoginForm(Form, NextFormMixin):
self.email.errors.append('Specified user does not exist')
return False
if not verify_and_update_password(self.password.data, self.user):
self.password.errors.append('Invalid password')
self.password.errors.append(get_message('INVALID_PASSWORD')[0])
return False
if requires_confirmation(self.user):
self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
@@ -197,11 +200,25 @@ class ResetPasswordForm(Form, NewPasswordFormMixin, PasswordConfirmFormMixin):
submit = SubmitField("Reset Password")
class ChangePasswordForm(Form, PasswordFormMixin, PasswordConfirmFormMixin):
class ChangePasswordForm(Form, PasswordFormMixin):
"""The default Change password form"""
new_password = PasswordField("New Password",
validators=[password_required,
Length(min=6, max=128)])
new_password_confirm = PasswordField("Retype Password",
validators=[EqualTo('new_password', message="Passwords do not match")])
submit = SubmitField("Change Password")
def validate(self):
super(ChangePasswordForm, self).validate()
if self.password.data.strip() == '':
self.password.errors.append('Password not provided')
return False
if not verify_and_update_password(self.password.data, current_user):
self.password.errors.append(get_message('INVALID_PASSWORD')[0])
return False
return True
+4 -1
View File
@@ -5,6 +5,9 @@
{% if security.registerable %}
<li><a href="{{ url_for_security('register') }}">Register</a><br/></li>
{% endif %}
{% if security.changeable %}
<li><a href="{{ url_for_security('change_password') }}">Change password</a></li>
{% endif %}
{% if security.recoverable %}
<li><a href="{{ url_for_security('forgot_password') }}">Forgot password</a><br/></li>
{% endif %}
@@ -12,4 +15,4 @@
<li><a href="{{ url_for_security('send_confirmation') }}">Confirm account</a></li>
{% endif %}
</ul>
{% endif %}
{% endif %}
+31
View File
@@ -278,6 +278,32 @@ def reset_password(token):
**_ctx('reset_password'))
@login_required
def change_password():
"""View function which handles a change password request."""
form_class = _security.change_password_form
if request.json:
form = form_class(MultiDict(request.json))
else:
form = form_class()
if form.validate_on_submit():
#send_reset_password_instructions(form.user)
print 'VALID'
if request.json is None:
#do_flash(*get_message('PASSWORD_CHANGE'))
do_flash('dicks')
if request.json:
return _render_json(form)
return render_template('security/change_password.html',
change_password_form=form,
**_ctx('change_password'))
def create_blueprint(state, import_name):
"""Creates the security extension blueprint"""
@@ -311,6 +337,11 @@ def create_blueprint(state, import_name):
methods=['GET', 'POST'],
endpoint='reset_password')(reset_password)
if state.changeable:
bp.route(state.change_url,
methods=['GET', 'POST'],
endpoint='change_password')(change_password)
if state.confirmable:
bp.route(state.confirm_url,
methods=['GET', 'POST'],
+25 -2
View File
@@ -327,12 +327,35 @@ class ChangePasswordTest(SecurityTest):
def test_change_password(self):
self.authenticate()
r = self.client.post('/change/' + t, data={
r = self.client.get('/change', follow_redirects=True)
self.assertIn('Change password', r.data)
def test_change_password_invalid(self):
self.authenticate()
r = self.client.post('/change', data={
'password': 'notpassword',
'new_password': 'newpassword',
'new_password_confirm': 'newpassword'
}, follow_redirects=True)
print r
self.assertIn('Invalid password', r.data)
def test_change_password_mismatch(self):
self.authenticate()
r = self.client.post('/change', data={
'password': 'password',
'new_password': 'newpassword',
'new_password_confirm': 'notnewpassword'
}, follow_redirects=True)
self.assertIn('Passwords do not match', r.data)
def test_change_password_success(self):
self.authenticate()
r = self.client.post('/change', data={
'password': 'password',
'new_password': 'newpassword',
'new_password_confirm': 'newpassword'
}, follow_redirects=True)
self.assertIn('You successfully changed your password', r.data)