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 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.") 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