I am trying to create a change password form in web2py. I am using db.auth_user table. I want to create a form with fields ['current_password', 'new_password', 'repeat_password']
Form should give a warning to user if the password is not entered correctly.
My code is:
request.vars.current_password = request.vars.current_password if request.vars.current_password else 'xxx'
user_password_form = SQLFORM.factory(Field('current_password', 'password',
requires=IS_EQUAL_TO(db(db.auth_user.id == auth.user_id).select('password').first().password)(
str(db.auth_user.password.validate(request.vars.current_password)[0]))),
Field('new_password', 'password'),
Field('repeat_password', 'password',
requires=IS_EQUAL_TO(request.vars.new_password,
'Passwords do not match')))
I have tested the validation for the following code and it sets a=1 if password is entered correctly. But on the form validation I couldn't figure it out how to implement it
if request.vars.current_password:
if db.auth_user.password.validate(request.vars.current_password)[0] == db(
db.auth_user.id == auth.user_id).select('password').first().password:
a=1
Any ideas how password validation can be achieved?
The web2py Auth system includes a built-in password change action. If you are using the default user
action in the default.py
controller, you access this form via /myapp/default/user/change_password.
If you prefer to create a separate controller action just for this purpose, you can simply do:
def change_password():
return dict(form=auth.change_password())
and in the associated view:
{{=form}}
Regarding your custom code, you cannot use the IS_EQUAL_TO
validator alone, as it takes an expression that must be equal to the value submitted with the form (you cannot call the validator with a transformed value as you have, as that will return a tuple, but the requires
attribute must be a callable object that takes a field and a value).
Instead, you could use the CRYPT
validator followed by the IS_EQUAL_TO
validator in a list -- the first validator will transform the submitted password to a hash, and the second will then test for equality with the stored password hash.
Alternatively, you could use:
def check_password(password):
new_hash = db.auth_user.password.validate(password)[0]
return new_hash == auth.user.password
form = SQLFORM.factory(Field('current_password', 'password')
requires=IS_EXPR(check_password)),
...)
The IS_EXPR
validator can take a function that will be passed the value, and the function should return True
or False
(note, this usage is not documented -- the book only shows the alternative usage, where you provide Python code as a string, which will be exec'ed
).