From 45d20789dd921028430ab91c4c5d464a6ac2c197 Mon Sep 17 00:00:00 2001 From: Place Jean-Marie Date: Fri, 15 Oct 2021 15:12:46 +0200 Subject: [PATCH 1/2] wip: avant tests --- app/static/js/user_form.js | 30 +++++++++++ app/templates/email/welcome.html | 16 ++++++ app/templates/email/welcome.txt | 11 ++++ app/views/users.py | 87 +++++++++++++++++++++++++++----- 4 files changed, 130 insertions(+), 14 deletions(-) create mode 100644 app/static/js/user_form.js create mode 100644 app/templates/email/welcome.html create mode 100644 app/templates/email/welcome.txt diff --git a/app/static/js/user_form.js b/app/static/js/user_form.js new file mode 100644 index 00000000..5cbdf490 --- /dev/null +++ b/app/static/js/user_form.js @@ -0,0 +1,30 @@ + +function refresh() { + if ($("input[name='welcome:list']").is(":checked")) { + $("input[name='reset_password:list']").closest("tr").css("display", "table-row") + if ($("input[name='reset_password:list']").is(":checked")) { + $("#tf_password").closest('tr').css("display", "none"); + $("#tf_password2").closest('tr').css("display", "none"); + } else { + // Le mot de passe doit être saisi + $("#tf_password").closest('tr').css("display", "table-row"); + $("#tf_password2").closest('tr').css("display", "table-row"); + } + } else { + // Le mot de passe doit être saisi + $("input[name='reset_password:list']").closest("tr").css("display", "none") + $("#tf_password").closest('tr').css("display", "table-row"); + $("#tf_password2").closest('tr').css("display", "table-row"); + } +} + +$(function() { + $("input[name='welcome:list']").click(function() { + refresh(); + }) + $("input[name='reset_password:list']").click(function() { + refresh(); + }) + refresh(); +}) + diff --git a/app/templates/email/welcome.html b/app/templates/email/welcome.html new file mode 100644 index 00000000..7f2d6ad6 --- /dev/null +++ b/app/templates/email/welcome.html @@ -0,0 +1,16 @@ +

Bienvenue {{ user.prenom }} {{ user.nom }},

+

+ Votre accès à ScoDoc vient d'être validé. + votre identifiant de connexion est: {{ user.user_name }} + + {% if token %} + Pour initialiser votre mot de passe ScoDoc, + + cliquez sur ce lien + . +

+

Vous pouvez aussi copier ce lien dans votre navigateur Web:

+

{{ url_for('auth.reset_password', token=token, _external=True) }}

+ {% endif %} + +

A bientôt !

\ No newline at end of file diff --git a/app/templates/email/welcome.txt b/app/templates/email/welcome.txt new file mode 100644 index 00000000..b15bceae --- /dev/null +++ b/app/templates/email/welcome.txt @@ -0,0 +1,11 @@ +Bienvenue {{ user.prenom }} {{ user.nom }}, + +Votre accès à ScoDoc vient d'être validé. +Votre identifiant de connexion est: {{ user.user_name }} + +{% if token %} + Pour initialiser votre mot de passe ScoDoc, suivre le lien: + {{ url_for('auth.reset_password', token=token, _external=True) }} +{% endif %} + +

A bientôt !

\ No newline at end of file diff --git a/app/views/users.py b/app/views/users.py index cddcf195..c4a7daa4 100644 --- a/app/views/users.py +++ b/app/views/users.py @@ -38,7 +38,7 @@ import re from xml.etree import ElementTree import flask -from flask import g, url_for, request +from flask import g, url_for, request, current_app from flask import redirect, render_template from flask_login import current_user @@ -49,6 +49,7 @@ from app.auth.models import Permission from app.auth.models import User from app.auth.models import Role from app.auth.models import UserRole +from app.email import send_email from app.models import Departement from app.decorators import ( @@ -63,6 +64,7 @@ from app.scodoc import sco_utils as scu from app.scodoc import sco_xml from app import log from app.scodoc.sco_exceptions import AccessDenied, ScoValueError +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 @@ -100,7 +102,10 @@ def create_user_form(user_name=None, edit=0, all_roles=1): initvalues = {} edit = int(edit) all_roles = int(all_roles) - H = [html_sco_header.sco_header(bodyOnLoad="init_tf_form('')")] + H = [html_sco_header.sco_header( + bodyOnLoad="init_tf_form('')", + javascripts=["js/user_form.js"], + )] F = html_sco_header.sco_footer() if edit: if not user_name: @@ -214,7 +219,32 @@ def create_user_form(user_name=None, edit=0, all_roles=1): "title": "Pseudo (login)", "size": 20, "allow_null": False, - "explanation": "nom utilisé pour la connexion. Doit être unique parmi tous les utilisateurs.", + "explanation": "nom utilisé pour la connexion. Doit être unique parmi tous les utilisateurs. " + "Lettres ou chiffres uniquement.", + }, + ), + ("formsemestre_id", {"input_type": "hidden"}), + ( + "welcome", + { + "title": "Message d'accueil", + "input_type": "checkbox", + "explanation": "Envoie un mail d'accueil à l'utilsateur.", + "labels": ("",), + "allowed_values": ("1",), + "default": "1", + }, + ), + ( + "reset_password", + { + "title": "réinit. mot de passe.", + "input_type": "checkbox", + "explanation": "ajoute la procédure de changement de mot de passe au mail d'accueil", + "labels": ("",), + "allowed_values": ("1",), + "default": "1", + "attributes": ["style='margin-left:20pt'"], }, ), ( @@ -444,18 +474,33 @@ def create_user_form(user_name=None, edit=0, all_roles=1): "identifiant invalide (pas d'accents ni de caractères spéciaux)" ) return "\n".join(H) + msg + "\n" + tf[1] + F + # Traitement initial (mode) : 3 cas + # A: envoi de welcome + procedure de reset + # B: envoi de welcome seulement (mot de passe saisie dans le formulaire) + # C: Aucun envoi (mot de pase saisi dans le formulaire) + if vals['welcome:list'] == '1': + if vals['reset_password:list'] == '1': + mode = 'A' + else: + mode = 'B' + else: + mode = 'C' + # check passwords - if vals["password"]: - if vals["password"] != vals["password2"]: - msg = tf_error_message( - """Les deux mots de passes ne correspondent pas !""" - ) - return "\n".join(H) + msg + "\n" + tf[1] + F - if not sco_users.is_valid_password(vals["password"]): - msg = tf_error_message( - """Mot de passe trop simple, recommencez !""" - ) - return "\n".join(H) + msg + "\n" + tf[1] + F + if mode == 'A': + vals['password'] = generate_password() + else: + if vals["password"]: + if vals["password"] != vals["password2"]: + msg = tf_error_message( + """Les deux mots de passes ne correspondent pas !""" + ) + return "\n".join(H) + msg + "\n" + tf[1] + F + if not sco_users.is_valid_password(vals["password"]): + msg = tf_error_message( + """Mot de passe trop simple, recommencez !""" + ) + return "\n".join(H) + msg + "\n" + tf[1] + F if not can_choose_dept: vals["dept"] = auth_dept # ok, go @@ -467,6 +512,20 @@ def create_user_form(user_name=None, edit=0, all_roles=1): u.from_dict(vals, new_user=True) db.session.add(u) db.session.commit() + # envoi éventuel d'un message + if mode == 'A' or mode == 'B': + if mode == 'A': + token = u.get_reset_password_token() + else: + token = None + send_email( + "[ScoDoc] Réinitialisation de votre mot de passe", + sender=current_app.config["ADMINS"][0], + recipients=[u.email], + text_body=render_template("email/welcome.txt", user=u, token=token), + html_body=render_template("email/welcome.html", user=u, token=token), + ) + return flask.redirect( url_for( "users.user_info_page", From c68633bf5bd47b927bef21e2ee0392e299d04860 Mon Sep 17 00:00:00 2001 From: Place Jean-Marie Date: Fri, 15 Oct 2021 15:34:10 +0200 Subject: [PATCH 2/2] typo --- app/views/users.py | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/app/views/users.py b/app/views/users.py index c4a7daa4..430633d5 100644 --- a/app/views/users.py +++ b/app/views/users.py @@ -102,10 +102,12 @@ def create_user_form(user_name=None, edit=0, all_roles=1): initvalues = {} edit = int(edit) all_roles = int(all_roles) - H = [html_sco_header.sco_header( - bodyOnLoad="init_tf_form('')", - javascripts=["js/user_form.js"], - )] + H = [ + html_sco_header.sco_header( + bodyOnLoad="init_tf_form('')", + javascripts=["js/user_form.js"], + ) + ] F = html_sco_header.sco_footer() if edit: if not user_name: @@ -220,7 +222,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1): "size": 20, "allow_null": False, "explanation": "nom utilisé pour la connexion. Doit être unique parmi tous les utilisateurs. " - "Lettres ou chiffres uniquement.", + "Lettres ou chiffres uniquement.", }, ), ("formsemestre_id", {"input_type": "hidden"}), @@ -229,7 +231,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1): { "title": "Message d'accueil", "input_type": "checkbox", - "explanation": "Envoie un mail d'accueil à l'utilsateur.", + "explanation": "Envoie un mail d'accueil à l'utilisateur.", "labels": ("",), "allowed_values": ("1",), "default": "1", @@ -417,7 +419,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1): nom=vals["nom"], prenom=vals["prenom"], email=vals["email"], - dept=vals["dept"], + dept=vals.get("dept", auth_dept), roles=vals["roles"], ) if not ok: @@ -478,17 +480,17 @@ def create_user_form(user_name=None, edit=0, all_roles=1): # A: envoi de welcome + procedure de reset # B: envoi de welcome seulement (mot de passe saisie dans le formulaire) # C: Aucun envoi (mot de pase saisi dans le formulaire) - if vals['welcome:list'] == '1': - if vals['reset_password:list'] == '1': - mode = 'A' + if vals["welcome:list"] == "1": + if vals["reset_password:list"] == "1": + mode = "A" else: - mode = 'B' + mode = "B" else: - mode = 'C' + mode = "C" # check passwords - if mode == 'A': - vals['password'] = generate_password() + if mode == "A": + vals["password"] = generate_password() else: if vals["password"]: if vals["password"] != vals["password2"]: @@ -513,8 +515,8 @@ def create_user_form(user_name=None, edit=0, all_roles=1): db.session.add(u) db.session.commit() # envoi éventuel d'un message - if mode == 'A' or mode == 'B': - if mode == 'A': + if mode == "A" or mode == "B": + if mode == "A": token = u.get_reset_password_token() else: token = None @@ -523,7 +525,9 @@ def create_user_form(user_name=None, edit=0, all_roles=1): sender=current_app.config["ADMINS"][0], recipients=[u.email], text_body=render_template("email/welcome.txt", user=u, token=token), - html_body=render_template("email/welcome.html", user=u, token=token), + html_body=render_template( + "email/welcome.html", user=u, token=token + ), ) return flask.redirect(