from . import ( ldap_client ) from flask import ( Blueprint, render_template, flash, current_app ) from flask_wtf import ( FlaskForm ) from wtforms import ( StringField, PasswordField, SubmitField, EmailField ) from wtforms.validators import ( ValidationError, DataRequired, EqualTo, Length, Regexp, Email ) bp = Blueprint('password', __name__, url_prefix='/password') class ChangePasswordForm(FlaskForm): # Minimal password length minlength = 9 # Form username = StringField(label=('Login'), validators=[DataRequired(), Length(max=64)], render_kw={"onkeyup": "validate_username()"}) currentpassword = PasswordField(label=('Current password'), validators=[DataRequired()]) newpassword = PasswordField(label=('New password'), validators=[DataRequired(), Length(min=minlength), Regexp("^(?=.*[a-z])"), Regexp("^(?=.*[A-Z])"), Regexp("^(?=.*\\d)"), ], render_kw={"onkeyup": "validate_username_form" f"({minlength})"}) confirm_password = PasswordField( label=('Confirm Password'), validators=[DataRequired(message='* Required'), EqualTo('newpassword')], render_kw={"onkeyup": f"validate_username_form({minlength})"}) submit = SubmitField( label=('Change my password'), render_kw={ "disabled": "true", "onclick": f"validate_username_form({minlength})"}) # Validators def validate_username(self, username): excluded_chars = " *?!'^+%&/()=}][{$#;\\\"" for char in self.username.data: if char in excluded_chars: raise ValidationError( f"Character {char} is not allowed in an username.") class ResetPasswordForm(FlaskForm): email = EmailField(label=('Email address'), validators=[DataRequired(), Email()], render_kw={"onkeyup": "validate_email()"}) submit = SubmitField( label=('Change my password'), render_kw={ "disabled": "true", "onclick": "validate_email()"}) @bp.route('/change', methods=["GET", "POST"]) def change(): form = ChangePasswordForm() if form.validate_on_submit(): client = ldap_client.Client(address=current_app.config["LDAP_ADDR"], port=current_app.config["LDAP_PORT"], base_dn=current_app.config["BASE_DN"], tls=current_app.config["LDAP_TLS"]) bind_status = client.bind( form.username._value(), form.currentpassword._value()) if bind_status[0] is False: flash("Connection failed, are you sure that your login and" f" password are correct ? ({client.link.last_error})") elif client.change_pwd(bind_status[1], form.newpassword._value()) is False: flash("An error occured and your password was not changed, sorry." f"({client.link.last_error})") client.unbind() else: flash('Your password has been changed !') client.unbind() return render_template('change.html', form=form) @bp.route('/reset', methods=["GET"]) def reset(): return render_template('reset.html')