2733: Ensure we always ask for the existing password before allowing a change r=mergify[bot] a=nextgens

## What type of PR?

enhancement

## What does this PR do?

Ensure we always ask for the existing password before allowing a change.

### Related issue(s)

## Prerequisites
Before we can consider review and merge, please make sure the following list is done and checked.
If an entry in not applicable, you can check it or remove it from the list.

- [ ] In case of feature or enhancement: documentation updated accordingly
- [x] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/workflow.html#changelog) entry file.


Co-authored-by: Florent Daigniere <nextgens@freenetproject.org>
This commit is contained in:
bors[bot]
2023-04-04 07:11:56 +00:00
committed by GitHub
4 changed files with 21 additions and 8 deletions

View File

@@ -128,6 +128,12 @@ class UserPasswordForm(flask_wtf.FlaskForm):
pwned = fields.HiddenField(label='', default=-1)
submit = fields.SubmitField(_('Update password'))
class UserPasswordChangeForm(flask_wtf.FlaskForm):
current_pw = fields.PasswordField(_('Current password'), [validators.DataRequired()])
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Password check'), [validators.DataRequired()])
pwned = fields.HiddenField(label='', default=-1)
submit = fields.SubmitField(_('Update password'))
class UserReplyForm(flask_wtf.FlaskForm):
reply_enabled = fields.BooleanField(_('Enable automatic reply'))

View File

@@ -20,7 +20,7 @@
</a>
</li>
<li class="nav-item" role="none">
<a href="{{ url_for('.user_password') }}" class="nav-link" role="menuitem">
<a href="{{ url_for('.user_password_change') }}" class="nav-link" role="menuitem">
<i class="nav-icon fa fa-lock"></i>
<p>{% trans %}Update password{% endtrans %}</p>
</a>

View File

@@ -99,18 +99,13 @@ def user_settings(user_email):
flask.url_for('.user_list', domain_name=user.domain.name))
return flask.render_template('user/settings.html', form=form, user=user)
@ui.route('/user/password', methods=['GET', 'POST'], defaults={'user_email': None})
@ui.route('/user/password/<path:user_email>', methods=['GET', 'POST'])
@access.owner(models.User, 'user_email')
def user_password(user_email):
def _process_password_change(form, user_email):
user_email_or_current = user_email or flask_login.current_user.email
user = models.User.query.get(user_email_or_current) or flask.abort(404)
form = forms.UserPasswordForm()
if form.validate_on_submit():
if form.pw.data != form.pw2.data:
flask.flash('Passwords do not match', 'error')
else:
elif user_email or models.User.login(user_email_or_current, form.current_pw.data):
if msg := utils.isBadOrPwned(form):
flask.flash(msg, "error")
return flask.render_template('user/password.html', form=form, user=user)
@@ -121,8 +116,19 @@ def user_password(user_email):
if user_email:
return flask.redirect(flask.url_for('.user_list',
domain_name=user.domain.name))
else:
flask.flash('Wrong current password', 'error')
return flask.render_template('user/password.html', form=form, user=user)
@ui.route('/user/password', methods=['GET', 'POST'], defaults={'user_email': None})
@access.owner(models.User, 'user_email')
def user_password_change(user_email):
return _process_password_change(forms.UserPasswordChangeForm(), user_email)
@ui.route('/user/password/<path:user_email>', methods=['GET', 'POST'])
@access.domain_admin(models.User, 'user_email')
def user_password(user_email):
return _process_password_change(forms.UserPasswordForm(), user_email)
@ui.route('/user/reply', methods=['GET', 'POST'], defaults={'user_email': None})
@ui.route('/user/reply/<path:user_email>', methods=['GET', 'POST'])

View File

@@ -0,0 +1 @@
Ensure we ask for the existing password before processing a password change request.