126 lines
3.9 KiB
Python
126 lines
3.9 KiB
Python
from flask_login import current_user
|
|
from wtforms.validators import ValidationError
|
|
from app.models.users import Member
|
|
from app.utils.valid_name import valid_name
|
|
from app.utils.unicode_names import normalize
|
|
import app.utils.ldap as ldap
|
|
from config import V5Config
|
|
|
|
|
|
def name_valid(form, name):
|
|
valid = valid_name(name.data)
|
|
default = "Nom d'utilisateur invalide (erreur interne)"
|
|
msg = {
|
|
"too-short":
|
|
"Le nom d'utilisateur doit faire au moins "
|
|
f"{V5Config.USER_NAME_MINLEN} caractères.",
|
|
"too-long":
|
|
"Le nom d'utilisateur doit faire au plus "
|
|
f"{V5Config.USER_NAME_MAXLEN} caractères.",
|
|
"cant-normalize":
|
|
"Ce nom d'utilisateur contient des caractères interdits. Les "
|
|
"caractères autorisés sont les lettres, lettres accentuées, "
|
|
'chiffres ainsi que "-" (tiret), "." (point), "~" (tilde) et '
|
|
'"_" (underscore).',
|
|
"no-letter":
|
|
"Le nom d'utilisateur doit contenir au moins une lettre.",
|
|
"forbidden":
|
|
"Ce nom d'utilisateur est interdit."
|
|
}
|
|
if valid is not True:
|
|
err = ' '.join(msg.get(code, default) for code in valid)
|
|
raise ValidationError(err)
|
|
|
|
|
|
def name_available(form, name):
|
|
# If the name is invalid, name_valid() will return a meaningful message
|
|
try:
|
|
norm = normalize(name.data)
|
|
except ValueError:
|
|
return
|
|
|
|
member = Member.query.filter_by(norm=norm).first()
|
|
if member is not None:
|
|
raise ValidationError("Ce nom d'utilisateur est indisponible.")
|
|
|
|
# Double check with LDAP if needed
|
|
if V5Config.USE_LDAP:
|
|
member = ldap.get_member(norm)
|
|
if member is not None:
|
|
raise ValidationError("Ce nom d'utilisateur est indisponible.")
|
|
|
|
|
|
|
|
def email(form, email):
|
|
member = Member.query.filter_by(email=email.data).first()
|
|
if member is not None:
|
|
raise ValidationError('Adresse email déjà utilisée.')
|
|
|
|
|
|
def password(form, password):
|
|
# To avoid errors in forms where password is optionnal
|
|
if len(password.data) == 0:
|
|
return
|
|
|
|
errors = []
|
|
if len(password.data) < V5Config.PASSWORD_MINLEN:
|
|
errors.append('Le mot de passe doit faire au moins '
|
|
f'{V5Config.PASSWORD_MINLEN} caractères.')
|
|
|
|
checks = set()
|
|
for c in password.data:
|
|
if c in "abcdefghijklmnopqrstuvwxyz":
|
|
checks.add('lower')
|
|
elif c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
|
|
checks.add('upper')
|
|
elif c in "0123456789":
|
|
checks.add('numeric')
|
|
else:
|
|
checks.add('other')
|
|
|
|
missing = []
|
|
if 'lower' not in checks:
|
|
missing.append('une minuscule')
|
|
if 'upper' not in checks:
|
|
missing.append('une majuscule')
|
|
if 'numeric' not in checks:
|
|
missing.append('un chiffre')
|
|
if 'other' not in checks:
|
|
missing.append('un caractère spécial')
|
|
|
|
if missing != []:
|
|
errors.append('Le mot de passe doit aussi contenir ' + ', '.join(missing) + '.')
|
|
|
|
if errors != []:
|
|
raise ValidationError(' '.join(errors))
|
|
|
|
|
|
def avatar(form, avatar):
|
|
pass
|
|
|
|
|
|
def old_password(form, field):
|
|
if field.data:
|
|
if not form.old_password.data:
|
|
raise ValidationError('Votre ancien mot de passe est requis pour cette modification.')
|
|
if not current_user.check_password(form.old_password.data):
|
|
raise ValidationError('Mot de passe actuel erroné.')
|
|
|
|
|
|
def id_exists(object):
|
|
"""Check if an id exists in a table"""
|
|
def _id_exists(form, id):
|
|
try:
|
|
id = int(id.data)
|
|
except ValueError:
|
|
raise ValidationError('L\'id n\'est pas un entier valide')
|
|
r = object.query.filter_by(id=id)
|
|
if not r:
|
|
raise ValidationError('L\'id n\'existe pas dans la BDD')
|
|
return _id_exists
|
|
|
|
|
|
def css(form, css):
|
|
"""Check if input is valid and sane CSS"""
|
|
pass
|