From 390118226dca712ea27488fe7a6f8b10dfe6b12b Mon Sep 17 00:00:00 2001 From: Place Jean-Marie Date: Sat, 16 Oct 2021 23:22:03 +0200 Subject: [PATCH 1/2] modification du formulaire de changement de mot de passe personnel --- app/api/auth.py | 2 +- app/templates/auth/change_password.html | 46 +++++++++++++ app/views/users.py | 90 +++++++++++++++++-------- 3 files changed, 108 insertions(+), 30 deletions(-) create mode 100644 app/templates/auth/change_password.html diff --git a/app/api/auth.py b/app/api/auth.py index 0226976c..24348aab 100644 --- a/app/api/auth.py +++ b/app/api/auth.py @@ -33,7 +33,7 @@ token_auth = HTTPTokenAuth() @basic_auth.verify_password def verify_password(username, password): - user = User.query.filter_by(username=username).first() + user = User.query.filter_by(user_name=username).first() if user and user.check_password(password): return user diff --git a/app/templates/auth/change_password.html b/app/templates/auth/change_password.html new file mode 100644 index 00000000..228982ab --- /dev/null +++ b/app/templates/auth/change_password.html @@ -0,0 +1,46 @@ +{% extends "base.html" %} +{% import 'bootstrap/wtf.html' as wtf %} + +{% macro render_field(field) %} + + {{ field.label }} + {{ field(**kwargs)|safe }} + {% if field.errors %} + + {% endif %} + + +{% endmacro %} + +{% block app_content %} +

Changez vos données personnelles

+

Identifiez vous avez votre mot de passe actuel

+

Vous pouvez changer votre mot de passe (laisez les champs vides sinon)

+

et/ou votre adresse email.

+ +
+ {{ form.user_name }} + {{ form.csrf_token }} + + {{ render_field(form.old_password, size=14, style="padding:1px;") }} + {{ render_field(form.new_password, size=14, style="padding:1px;") }} + {{ render_field(form.bis_password, size=14, style="padding:1px;") }} + {{ render_field(form.email, size=40, style="padding:1px;") }} + {{ render_field(form.submit) }} +
+
+ +{#
#} +{#
Votre identifiant: {{user.user_name}}
#} +{#
#} +{##} +{#
#} +{#
#} +{# {{ wtf.quick_form(form) }}#} +{#
#} +{#
#} +{% endblock %} \ No newline at end of file diff --git a/app/views/users.py b/app/views/users.py index 98d14f30..84f17660 100644 --- a/app/views/users.py +++ b/app/views/users.py @@ -38,12 +38,15 @@ import re from xml.etree import ElementTree import flask -from flask import g, url_for, request, current_app +from flask import g, url_for, request, current_app, flash from flask import redirect, render_template from flask_login import current_user +from wtforms import HiddenField, PasswordField, StringField, SubmitField +from wtforms.validators import DataRequired, Email, ValidationError, EqualTo from app import db +from app.api.auth import verify_password from app.auth.forms import DeactivateUserForm from app.auth.models import Permission from app.auth.models import User @@ -69,6 +72,40 @@ from app.scodoc.sco_import_users import generate_password from app.scodoc.sco_permissions_check import can_handle_passwd from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.views import users_bp as bp +from flask_wtf import FlaskForm + +_ = lambda x: x # sans babel +_l = _ + + +class ChangePasswordForm(FlaskForm): + user_name = HiddenField() + old_password = PasswordField(_l("Ancien mot de passe")) + new_password = PasswordField(_l("Nouveau mot de passe")) + bis_password = PasswordField( + _l("Répéter"), + validators=[ + EqualTo( + "new_password", + message="Les deux saisies sont " "différentes, recommencez", + ), + ], + ) + email = StringField(_l("Email"), validators=[DataRequired(), Email()]) + submit = SubmitField(_l("Modifier")) + + def validate_email(self, email): + user = User.query.filter_by(email=email.data).first() + if user is not None and self.user_name.data != user.user_name: + raise ValidationError(_("Please choose a different email address.")) + + def validate_new_password(self, new_password): + if new_password.data != "" and not is_valid_password(new_password.data): + raise ValidationError(f"Mot de passe trop simple, recommencez") + + def validate_old_password(self, old_password): + if not verify_password(self.user_name.data, old_password.data): + raise ValidationError("Ancien mot de passe incorrect, recommenccez") @bp.route("/") @@ -676,7 +713,7 @@ def get_user_list_xml(dept=None, start="", limit=25): return scu.send_file(data, mime=scu.XML_MIMETYPE) -@bp.route("/form_change_password") +@bp.route("/form_change_password", methods=["GET", "POST"]) @scodoc @permission_required(Permission.ScoView) @scodoc7func @@ -685,36 +722,31 @@ def form_change_password(user_name=None): Un utilisateur peut toujours changer son propre mot de passe. """ if not user_name: - u = current_user + user = current_user else: - u = User.query.filter_by(user_name=user_name).first() - H = [html_sco_header.sco_header(user_check=False)] - F = html_sco_header.sco_footer() + user = User.query.filter_by(user_name=user_name).first() + # check access - if not can_handle_passwd(u): - return ( - "\n".join(H) - + "

Vous n'avez pas la permission de changer ce mot de passe

" - + F + if not can_handle_passwd(user): + return "\n".join( + [ + html_sco_header.sco_header(user_check=False), + "

Vous n'avez pas la permission de changer ce mot de passe

", + html_sco_header.sco_footer(), + ] ) - # - H.append( - """

Changement du mot de passe de %(nomplogin)s

-

-

- - -
Nouveau mot de passe:
Confirmation:
- - -

-

Note: en ScoDoc 9, les utilisateurs peuvent changer eux-même leur mot de passe - en indiquant l'adresse mail associée à leur compte. -

-""" - % {"nomplogin": u.get_nomplogin(), "user_name": user_name} - ) - return "\n".join(H) + F + form = ChangePasswordForm(user_name=user.user_name, email=user.email) + if form.validate_on_submit(): + messages = [] + if form.new_password.data != "": # change password + user.set_password(form.new_password.data) + messages.append("Mot de passe modifié") + if form.email.data != user.email: # change email + user.email = form.email.data + messages.append("Adresse email modifiée") + db.session.commit() + flash("\n".join(messages)) + return render_template("auth/change_password.html", form=form) @bp.route("/change_password", methods=["POST"]) From a909a307c022f323bd19b0b329bac2653d80de03 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 17 Oct 2021 11:19:01 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Am=C3=A9liorer=20page=20infos=20utilisateur?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/auth/forms.py | 7 +- app/auth/routes.py | 4 +- app/scodoc/sco_users.py | 97 +------------------ app/templates/auth/change_password.html | 26 +++-- .../auth/reset_password_request.html | 2 +- app/templates/auth/user_info_page.html | 67 +++++++++++++ app/templates/base.html | 13 ++- app/templates/email/reset_password.html | 2 +- app/views/users.py | 50 ++++++++-- sco_version.py | 2 +- 10 files changed, 147 insertions(+), 123 deletions(-) create mode 100644 app/templates/auth/user_info_page.html diff --git a/app/auth/forms.py b/app/auth/forms.py index dd1f68ef..3d70054d 100644 --- a/app/auth/forms.py +++ b/app/auth/forms.py @@ -43,8 +43,11 @@ class UserCreationForm(FlaskForm): class ResetPasswordRequestForm(FlaskForm): - email = StringField(_l("Email"), validators=[DataRequired(), Email()]) - submit = SubmitField(_l("Valider ce mot de passe")) + email = StringField( + _l("Adresse email associée à votre compte ScoDoc:"), + validators=[DataRequired(), Email()], + ) + submit = SubmitField(_l("Envoyer")) class ResetPasswordForm(FlaskForm): diff --git a/app/auth/routes.py b/app/auth/routes.py index 61f2bcea..df340151 100644 --- a/app/auth/routes.py +++ b/app/auth/routes.py @@ -98,7 +98,9 @@ def reset_password_request(): current_app.logger.info( "reset_password_request: for unkown user '{}'".format(form.email.data) ) - flash(_("Voir les instructions envoyées par mail")) + flash( + _("Voir les instructions envoyées par mail (pensez à regarder vos spams)") + ) return redirect(url_for("auth.login")) return render_template( "auth/reset_password_request.html", title=_("Reset Password"), form=form diff --git a/app/scodoc/sco_users.py b/app/scodoc/sco_users.py index 3f1b646d..eaf43494 100644 --- a/app/scodoc/sco_users.py +++ b/app/scodoc/sco_users.py @@ -32,6 +32,7 @@ import re from flask import url_for, g, request +from flask.templating import render_template from flask_login import current_user @@ -271,102 +272,6 @@ def user_info(user_name_or_id=None, user=None): return info -def user_info_page(user_name=None): - """Display page of info about given user. - If user_name not specified, user current_user - """ - from app.scodoc.sco_permissions_check import can_handle_passwd - - # peut on divulguer ces infos ? - if not can_handle_passwd(current_user, allow_admindepts=True): - raise AccessDenied("Vous n'avez pas la permission de voir cette page") - - dept = g.scodoc_dept - if not user_name: - user = current_user - else: - user = User.query.filter_by(user_name=user_name).first() - if not user: - raise ScoValueError("invalid user_name") - H = [ - html_sco_header.sco_header( - page_title="Utilisateur %s" % user.user_name, - ) - ] - F = html_sco_header.sco_footer() - H.append("

Utilisateur: %s" % user.user_name) - info = user.to_dict() - if info: - H.append(" (%(status_txt)s)" % info) - H.append("

") - if not info: - H.append( - "

L' utilisateur '%s' n'est pas défini dans ce module.

" % user_name - ) - if user.has_permission(Permission.ScoEditAllNotes, dept): - H.append("

(il peut modifier toutes les notes de %s)

" % dept) - if user.has_permission(Permission.ScoEditAllEvals, dept): - H.append("

(il peut modifier toutes les évaluations de %s)

" % dept) - if user.has_permission(Permission.ScoImplement, dept): - H.append("

(il peut creer des formations en %s)

" % dept) - else: - H.append( - """

- Login : %(user_name)s
- Nom : %(nom)s
- Prénom : %(prenom)s
- Mail : %(email)s
- Roles : %(roles_string)s
- Dept : %(dept)s
- Dernière modif mot de passe: %(date_modif_passwd)s
- Date d'expiration: %(date_expiration)s -

") - - if current_user.user_name == user_name: - H.append( - '

Se déconnecter: logout

' - % url_for("auth.logout") - ) - # Liste des permissions - H.append( - '

Permissions de cet utilisateur dans le département %s:

    ' - % dept - ) - for p in Permission.description: - perm = getattr(Permission, p) - if user.has_permission(perm, dept): - b = "oui" - else: - b = "non" - H.append("
  • %s : %s
  • " % (Permission.description[p], b)) - H.append("
") - - if current_user.has_permission(Permission.ScoUsersAdmin, dept): - H.append( - '

Liste de tous les utilisateurs

' - % url_for("users.index_html", scodoc_dept=g.scodoc_dept) - ) - return "\n".join(H) + F - - def check_modif_user( edit, enforce_optionals=False, diff --git a/app/templates/auth/change_password.html b/app/templates/auth/change_password.html index 228982ab..702059c8 100644 --- a/app/templates/auth/change_password.html +++ b/app/templates/auth/change_password.html @@ -17,21 +17,27 @@ {% endmacro %} {% block app_content %} -

Changez vos données personnelles

-

Identifiez vous avez votre mot de passe actuel

-

Vous pouvez changer votre mot de passe (laisez les champs vides sinon)

-

et/ou votre adresse email.

- +

Modification du compte ScoDoc {{form.user_name.data}}

+
+

Identifiez-vous avez votre mot de passe actuel

+

Vous pouvez changer le mot de passe et/ou l'adresse email.

+

Les champs vides ne seront pas changés.

+
{{ form.user_name }} {{ form.csrf_token }} - {{ render_field(form.old_password, size=14, style="padding:1px;") }} - {{ render_field(form.new_password, size=14, style="padding:1px;") }} - {{ render_field(form.bis_password, size=14, style="padding:1px;") }} - {{ render_field(form.email, size=40, style="padding:1px;") }} - {{ render_field(form.submit) }} + {{ render_field(form.old_password, size=14, + style="padding:1px; margin-left: 1em; margin-top: 4px;") }} + {{ render_field(form.new_password, size=14, + style="padding:1px; margin-left: 1em; margin-top: 12px;") }} + {{ render_field(form.bis_password, size=14, + style="padding:1px; margin-left: 1em; margin-top: 4px;") }} + {{ render_field(form.email, size=40, + style="padding:1px; margin-top: 12px;margin-bottom: 16px; margin-left: 1em;") }}
+ + #} diff --git a/app/templates/auth/reset_password_request.html b/app/templates/auth/reset_password_request.html index 6fc7329f..99a37fb2 100644 --- a/app/templates/auth/reset_password_request.html +++ b/app/templates/auth/reset_password_request.html @@ -2,7 +2,7 @@ {% import 'bootstrap/wtf.html' as wtf %} {% block app_content %} -

Reset Password

+

Demande d'un nouveau mot de passe

{{ wtf.quick_form(form) }} diff --git a/app/templates/auth/user_info_page.html b/app/templates/auth/user_info_page.html new file mode 100644 index 00000000..69592999 --- /dev/null +++ b/app/templates/auth/user_info_page.html @@ -0,0 +1,67 @@ +{% extends "base.html" %} +{% import 'bootstrap/wtf.html' as wtf %} + +{% block app_content %} + +

Utilisateur: {{user.user_name}} ({{'actif' if user.active else 'fermé'}})

+

+Login : {{user.user_name}}
+Nom : {{user.nom or ""}}
+Prénom : {{user.prenom or ""}}
+Mail : {{user.email}}
+Roles : {{user.get_roles_string()}}
+Dept : {{user.dept or ""}}
+Dernière modif mot de passe: +{{user.date_modif_passwd.isoformat() if user.date_modif_passwd else ""}}
+Date d'expiration: +{{user.date_expiration.isoformat() if user.date_expiration else "(sans limite)"}} +

+

+ +{% if current_user.id == user.id %} +

Se déconnecter: +logout +

+{% endif %} + +{# Liste des permissions #} +
+

Permissions de cet utilisateur dans le département {dept}:

+
    +{% for p in Permission.description %} +
  • {{Permission.description[p]}} : + {{ + "oui" if user.has_permission(Permission.get_by_name(p), dept) else "non" + }} +
  • +{% endfor %} +
+
+ +{% if current_user.has_permission(Permission.ScoUsersAdmin, dept) %} +

Liste de tous les utilisateurs

+ +{% endif %} + + +{% endblock %} \ No newline at end of file diff --git a/app/templates/base.html b/app/templates/base.html index 0be7c6fc..815ba7b7 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -22,12 +22,19 @@ ScoDoc
+