From 2aa2fd539f7f28a964ff1398a0f0c5f2bea1549e Mon Sep 17 00:00:00 2001 From: Lephe Date: Thu, 8 Jul 2021 15:01:24 +0200 Subject: [PATCH] clean up account forms (factor + syntax) (#70) * Factor the update account forms (user and admin) * Slightly cleaner syntax (I hope), also a bit shorter --- app/forms/account.py | 279 +++++++++----------------- app/routes/account/account.py | 10 +- app/templates/admin/edit_account.html | 3 + 3 files changed, 102 insertions(+), 190 deletions(-) diff --git a/app/forms/account.py b/app/forms/account.py index d1a7c25..70d4c82 100644 --- a/app/forms/account.py +++ b/app/forms/account.py @@ -10,275 +10,176 @@ class RegistrationForm(FlaskForm): username = StringField( 'Pseudonyme', description='Ce nom est définitif !', - validators=[ - InputRequired(), - vd.name.valid, - vd.name.available, - ], - ) + validators=[InputRequired(), vd.name.valid, vd.name.available]) + email = EmailField( 'Adresse Email', validators=[ InputRequired(), Email(message="Adresse email invalide."), - vd.email, - ], - ) + vd.email + ]) + password = PasswordField( 'Mot de passe', - validators=[ - InputRequired(), - vd.password.is_strong, - ], - ) + validators=[InputRequired(), vd.password.is_strong]) + password2 = PasswordField( 'Répéter le mot de passe', validators=[ InputRequired(), - EqualTo('password', message="Les mots de passe doivent être identiques."), - ], - ) + EqualTo('password', message="Les mots de passe doivent être identiques.") + ]) + guidelines = BooleanField( """J'accepte les CGU""", - validators=[ - InputRequired(), - ], - ) + validators=[InputRequired()]) + newsletter = BooleanField( 'Inscription à la newsletter', - description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.', - ) - submit = SubmitField( - "S'inscrire", - ) + description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.') + + submit = SubmitField("S'inscrire") -class UpdateAccountForm(FlaskForm): +class UpdateAccountBaseForm(FlaskForm): avatar = FileField( 'Avatar', - validators=[ - Optional(), - vd.file.is_image, - vd.file.avatar_size, - ], - ) + validators=[Optional(), vd.file.is_image, vd.file.avatar_size]) + email = EmailField( 'Adresse email', validators=[ Optional(), Email(message="Addresse email invalide."), vd.email, - vd.password.old_password, - ], - ) + # For users: vd.password.old_password is added dynamically + ]) + password = PasswordField( 'Nouveau mot de passe', + description="L'ancien mot de passe ne pourra pas être récupéré !", validators=[ Optional(), vd.password.is_strong, - vd.password.old_password, - ], - ) - password2 = PasswordField( - 'Répéter le mot de passe', - validators=[ - Optional(), - EqualTo('password', message="Les mots de passe doivent être identiques."), - ], - ) - old_password = PasswordField( - 'Mot de passe actuel', - validators=[ - Optional(), - ], - ) + # For users: vd.password.old_password is added dynamically + ]) + birthday = DateField( 'Anniversaire', - validators=[ - Optional(), - ], - ) + validators=[Optional()]) + signature = TextAreaField( 'Signature', - validators=[ - Optional(), - ] - ) + validators=[Optional()]) + biography = TextAreaField( 'Présentation', - validators=[ - Optional(), - ] - ) + validators=[Optional()]) + title = SelectField( 'Titre', coerce=int, validators=[ Optional(), - vd.own_title, - ] - ) + # For users: vd.own_title (admins can assign any title!) + ]) + newsletter = BooleanField( 'Inscription à la newsletter', - description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.', - ) + description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.') + + submit = SubmitField('Mettre à jour') + + +class UpdateAccountForm(UpdateAccountBaseForm): + password2 = PasswordField( + 'Répéter le mot de passe', + validators=[ + Optional(), + EqualTo('password', message="Les mots de passe doivent être identiques.") + ]) + + old_password = PasswordField( + 'Mot de passe actuel', + validators=[Optional()]) + theme = RadioField( 'Thème du site', choices=[ ('default_theme', 'Thème par défaut (clair)'), ('FK_dark_theme', 'Thème sombre de FlamingKite'), - ], - ) - submit = SubmitField('Mettre à jour') + ]) + + +class AdminUpdateAccountForm(UpdateAccountBaseForm): + username = StringField( + 'Pseudonyme', + validators=[Optional(), vd.name.valid, vd.name.available]) + + email_confirmed = BooleanField( + "Confirmer l'email", + description="Si décoché, l'utilisateur devra demander explicitement un" + " email de validation, ou faire valider son adresse email par un" + " administrateur.") + + xp = DecimalField( + 'XP', + validators=[Optional()]) class DeleteAccountBaseForm(FlaskForm): transfer = BooleanField( 'Conserver les posts sous forme anonyme', description="Aucune information personnelle n'est conservée ; seul le texte de posts reste. Cela permet de garder un historique fidèle des échanges.", - default=True - ) + default=True) + delete = BooleanField( 'Confirmer la suppression', - validators=[ - InputRequired(), - ], - description='Attention, cette opération est irréversible !' - ) - submit = SubmitField( - 'Supprimer le compte', - ) + validators=[InputRequired()], + description='Attention, cette opération est irréversible !') + + submit = SubmitField('Supprimer le compte') + class DeleteAccountForm(DeleteAccountBaseForm): old_password = PasswordField( 'Mot de passe', - validators=[ - InputRequired(), - vd.password.old_password, - ], - ) + validators=[InputRequired(), vd.password.old_password]) + + +class AdminDeleteAccountForm(DeleteAccountBaseForm): + pass + class AskResetPasswordForm(FlaskForm): email = EmailField( 'Adresse email', - validators=[ - Optional(), - Email(message="Addresse email invalide."), - ], - ) + validators=[Optional(), Email(message="Addresse email invalide.")]) + submit = SubmitField('Valider') class ResetPasswordForm(FlaskForm): password = PasswordField( 'Mot de passe', - validators=[ - Optional(), - vd.password.is_strong, - ], - ) + validators=[Optional(), vd.password.is_strong]) + password2 = PasswordField( 'Répéter le mot de passe', validators=[ Optional(), - EqualTo('password', message="Les mots de passe doivent être identiques."), - ], - ) + EqualTo('password', message="Les mots de passe doivent être identiques.") + ]) + submit = SubmitField('Valider') -class AdminUpdateAccountForm(FlaskForm): - username = StringField( - 'Pseudonyme', - validators=[ - Optional(), - vd.name.valid, - vd.name.available, - ], - ) - avatar = FileField( - 'Avatar', - validators=[ - Optional(), - vd.file.is_image, - vd.file.avatar_size, - ], - ) - email = EmailField( - 'Adresse email', - validators=[ - Optional(), - Email(message="Addresse email invalide."), - vd.email, - ], - ) - email_confirmed = BooleanField( - "Confirmer l'email", - description="Si décoché, l'utilisateur devra demander explicitement un email " - "de validation, ou faire valider son adresse email par un administrateur.", - ) - password = PasswordField( - 'Mot de passe', - description="L'ancien mot de passe ne pourra pas être récupéré !", - validators=[ - Optional(), - vd.password.is_strong, - ], - ) - xp = DecimalField( - 'XP', - validators=[ - Optional(), - ] - ) - birthday = DateField( - 'Anniversaire', - validators=[ - Optional(), - ], - ) - signature = TextAreaField( - 'Signature', - validators=[ - Optional(), - ], - ) - biography = TextAreaField( - 'Présentation', - validators=[ - Optional(), - ], - ) - title = SelectField( - 'Titre', - coerce=int, - validators=[ - Optional(), - # Admin can set any title to any member! - ] - ) - newsletter = BooleanField( - 'Inscription à la newsletter', - description='Un mail par trimestre environ, pour être prévenu des concours, évènements et nouveautés.', - ) - submit = SubmitField( - 'Mettre à jour', - ) - - class AdminAccountEditTrophyForm(FlaskForm): # Boolean inputs are generated on-the-fly from trophy list - submit = SubmitField( - 'Modifier', - ) + submit = SubmitField('Modifier') class AdminAccountEditGroupForm(FlaskForm): # Boolean inputs are generated on-the-fly from group list - submit = SubmitField( - 'Modifier', - ) - - -class AdminDeleteAccountForm(DeleteAccountBaseForm): - pass + submit = SubmitField('Modifier') diff --git a/app/routes/account/account.py b/app/routes/account/account.py index 9dede19..31720ef 100644 --- a/app/routes/account/account.py +++ b/app/routes/account/account.py @@ -9,6 +9,7 @@ from app.utils.render import render from app.utils.send_mail import send_validation_mail, send_reset_password_mail from app.utils.priv_required import guest_only import app.utils.ldap as ldap +import app.utils.validators as vd from itsdangerous import URLSafeTimedSerializer from config import V5Config @@ -20,8 +21,15 @@ def edit_account(): titles = [(t.id, t.name) for t in current_user.trophies if isinstance(t, Title)] titles.insert(0, (-1, "Membre")) form.title.choices = titles + + extra_vd = { + "email": [vd.password.old_password], + "password": [vd.password.old_password], + "title": [vd.own_title], + } + if form.submit.data: - if form.validate_on_submit(): + if form.is_submitted() and form.validate(extra_validators=extra_vd): current_user.update( avatar=form.avatar.data or None, email=form.email.data or None, diff --git a/app/templates/admin/edit_account.html b/app/templates/admin/edit_account.html index 4f61a47..724ef25 100644 --- a/app/templates/admin/edit_account.html +++ b/app/templates/admin/edit_account.html @@ -40,6 +40,9 @@ {{ form.email_confirmed.label }} {{ form.email_confirmed(checked=user.email_confirmed) }}
{{ form.email_confirmed.description }}
+ {% for error in form.email_confirmed.errors %} + {{ error }} + {% endfor %}
{{ form.password.label }}