amélioration formulaires creation/edition utilisateurs

This commit is contained in:
Emmanuel Viennet 2021-10-15 19:17:40 +02:00
parent c2de33f7f5
commit 9c50b58d5f
8 changed files with 85 additions and 61 deletions

View File

@ -8,7 +8,7 @@ TODO: à revoir complètement pour reprendre ZScoUsers et les pages d'authentifi
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
from app.auth.models import User
from app.auth.models import User, is_valid_password
_ = lambda x: x # sans babel
@ -44,7 +44,7 @@ class UserCreationForm(FlaskForm):
class ResetPasswordRequestForm(FlaskForm):
email = StringField(_l("Email"), validators=[DataRequired(), Email()])
submit = SubmitField(_l("Request Password Reset"))
submit = SubmitField(_l("Valider ce mot de passe"))
class ResetPasswordForm(FlaskForm):
@ -52,7 +52,11 @@ class ResetPasswordForm(FlaskForm):
password2 = PasswordField(
_l("Répéter"), validators=[DataRequired(), EqualTo("password")]
)
submit = SubmitField(_l("Request Password Reset"))
submit = SubmitField(_l("Valider ce mot de passe"))
def validate_password(self, password):
if not is_valid_password(password.data):
raise ValidationError(f"Mot de passe trop simple, recommencez")
class DeactivateUserForm(FlaskForm):

View File

@ -10,6 +10,7 @@ import re
from time import time
from typing import Optional
import cracklib # pylint: disable=import-error
from flask import current_app, url_for, g
from flask_login import UserMixin, AnonymousUserMixin
@ -28,6 +29,23 @@ from app.scodoc import sco_etud # a deplacer dans scu
VALID_LOGIN_EXP = re.compile(r"^[a-zA-Z0-9@\\\-_\.]+$")
def is_valid_password(cleartxt):
"""Check password.
returns True if OK.
"""
if (
hasattr(scu.CONFIG, "MIN_PASSWORD_LENGTH")
and scu.CONFIG.MIN_PASSWORD_LENGTH > 0
and len(cleartxt) < scu.CONFIG.MIN_PASSWORD_LENGTH
):
return False # invalid: too short
try:
_ = cracklib.FascistCheck(cleartxt)
return True
except ValueError:
return False
class User(UserMixin, db.Model):
"""ScoDoc users, handled by Flask / SQLAlchemy"""

View File

@ -116,6 +116,6 @@ def reset_password(token):
if form.validate_on_submit():
user.set_password(form.password.data)
db.session.commit()
flash(_("Your password has been reset."))
flash(_("Votre mot de passe a été changé."))
return redirect(url_for("auth.login"))
return render_template("auth/reset_password.html", form=form)
return render_template("auth/reset_password.html", form=form, user=user)

View File

@ -34,7 +34,6 @@ import re
from flask import url_for, g, request
from flask_login import current_user
import cracklib # pylint: disable=import-error
from app import db, Departement
@ -56,23 +55,6 @@ from app.scodoc.sco_exceptions import (
)
def is_valid_password(cleartxt):
"""Check password.
returns True if OK.
"""
if (
hasattr(scu.CONFIG, "MIN_PASSWORD_LENGTH")
and scu.CONFIG.MIN_PASSWORD_LENGTH > 0
and len(cleartxt) < scu.CONFIG.MIN_PASSWORD_LENGTH
):
return False # invalid: too short
try:
_ = cracklib.FascistCheck(cleartxt)
return True
except ValueError:
return False
# ---------------
# ---------------
@ -439,6 +421,15 @@ def check_modif_user(
return False, "département '%s' inexistant" % dept + MSG_OPT
if enforce_optionals and not roles:
return False, "aucun rôle sélectionné, êtes vous sûr ?" + MSG_OPT
# Unicité du mail
users_with_this_mail = User.query.filter_by(email=email).all()
if edit: # modification
if email != user["email"] and len(users_with_this_mail) > 0:
return False, "un autre utilisateur existe déjà avec cette adresse mail"
else: # création utilisateur
if len(users_with_this_mail) > 0:
return False, "un autre utilisateur existe déjà avec cette adresse mail"
# ok
# Des noms/prénoms semblables existent ?
nom = nom.lower().strip()

View File

@ -6,7 +6,7 @@ function refresh() {
$("#tf_password").closest('tr').css("display", "none");
$("#tf_password2").closest('tr').css("display", "none");
} else {
// Le mot de passe doit être saisi
// Le mot de passe doit être saisi
$("#tf_password").closest('tr').css("display", "table-row");
$("#tf_password2").closest('tr').css("display", "table-row");
}
@ -18,11 +18,11 @@ function refresh() {
}
}
$(function() {
$("input[name='welcome:list']").click(function() {
$(function () {
$("input[name='welcome:list']").click(function () {
refresh();
})
$("input[name='reset_password:list']").click(function() {
$("input[name='reset_password:list']").click(function () {
refresh();
})
refresh();

View File

@ -2,8 +2,13 @@
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Reset Your Password</h1>
<div class="row">
<h1>Changez votre mot de passe ScoDoc</h1>
<div class="row" style="margin-top: 30px;">
<div class="col-md-4">Votre identifiant: <b>{{user.user_name}}</b></div>
</div>
<div class="row" style="margin-top: 30px;">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>

View File

@ -1,16 +1,18 @@
<p>Bienvenue {{ user.prenom }} {{ user.nom }},</p>
<p>
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,
</p>
<p>
Votre identifiant de connexion est: <b>{{ user.user_name }}</b>
</p>
{% if token %}
<p>Pour initialiser votre mot de passe ScoDoc,
<a href="{{ url_for('auth.reset_password', token=token, _external=True) }}">
cliquez sur ce lien
</a>.
</p>
<p>Vous pouvez aussi copier ce lien dans votre navigateur Web:</p>
<p>{{ url_for('auth.reset_password', token=token, _external=True) }}</p>
{% endif %}
{% endif %}
<p>A bientôt !</p>

View File

@ -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.auth.models import is_valid_password
from app.email import send_email
from app.models import Departement
@ -226,29 +227,6 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
},
),
("formsemestre_id", {"input_type": "hidden"}),
(
"welcome",
{
"title": "Message d'accueil",
"input_type": "checkbox",
"explanation": "Envoie un mail d'accueil à l'utilisateur.",
"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'"],
},
),
(
"password",
{
@ -289,6 +267,32 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
},
)
]
if not edit: # options création utilisateur
descr += [
(
"welcome",
{
"title": "Message d'accueil",
"input_type": "checkbox",
"explanation": "Envoie un mail d'accueil à l'utilisateur.",
"labels": ("",),
"allowed_values": ("1",),
"default": "1",
},
),
(
"reset_password",
{
"title": "",
"input_type": "checkbox",
"explanation": "indiquer par mail de changer le mot de passe initial",
"labels": ("",),
"allowed_values": ("1",),
"default": "1",
# "attributes": ["style='margin-left:20pt'"],
},
),
]
if not auth_dept:
# si auth n'a pas de departement (admin global)
@ -479,7 +483,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
# 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)
# C: Aucun envoi (mot de passe saisi dans le formulaire)
if vals["welcome:list"] == "1":
if vals["reset_password:list"] == "1":
mode = "A"
@ -498,7 +502,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
"""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"]):
if not is_valid_password(vals["password"]):
msg = tf_error_message(
"""Mot de passe trop simple, recommencez !"""
)
@ -521,7 +525,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
else:
token = None
send_email(
"[ScoDoc] Réinitialisation de votre mot de passe",
"[ScoDoc] Création de votre compte",
sender=current_app.config["ADMINS"][0],
recipients=[u.email],
text_body=render_template("email/welcome.txt", user=u, token=token),
@ -735,7 +739,7 @@ def change_password(user_name, password, password2):
% user_name
)
else:
if not sco_users.is_valid_password(password):
if not is_valid_password(password):
H.append(
"""<p><b>ce mot de passe n\'est pas assez compliqué !</b><br/>(oui, il faut un mot de passe vraiment compliqué !)</p>
<p><a href="form_change_password?user_name=%s" class="stdlink">Recommencer</a></p>