diff --git a/app/auth/models.py b/app/auth/models.py index 8ff8e885..8743850d 100644 --- a/app/auth/models.py +++ b/app/auth/models.py @@ -32,7 +32,7 @@ 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): +def is_valid_password(cleartxt) -> bool: """Check password. returns True if OK. """ @@ -49,6 +49,15 @@ def is_valid_password(cleartxt): return False +def invalid_user_name(user_name: str) -> bool: + "Check that user_name (aka login) is invalid" + return ( + (len(user_name) < 2) + or (len(user_name) >= USERNAME_STR_LEN) + or not VALID_LOGIN_EXP.match(user_name) + ) + + class User(UserMixin, db.Model): """ScoDoc users, handled by Flask / SQLAlchemy""" @@ -108,7 +117,7 @@ class User(UserMixin, db.Model): self.roles = [] self.user_roles = [] # check login: - if kwargs.get("user_name") and not VALID_LOGIN_EXP.match(kwargs["user_name"]): + if kwargs.get("user_name") and invalid_user_name(kwargs["user_name"]): raise ValueError(f"invalid user_name: {kwargs['user_name']}") super(User, self).__init__(**kwargs) # Ajoute roles: @@ -287,7 +296,7 @@ class User(UserMixin, db.Model): self.user_name = data["user_name"] if "password" in data: self.set_password(data["password"]) - if not VALID_LOGIN_EXP.match(self.user_name): + if not invalid_user_name(self.user_name): raise ValueError(f"invalid user_name: {self.user_name}") # Roles: roles_string is "Ens_RT, Secr_RT, ..." if "roles_string" in data: diff --git a/app/auth/routes.py b/app/auth/routes.py index eb279acb..c3b4f717 100644 --- a/app/auth/routes.py +++ b/app/auth/routes.py @@ -19,8 +19,7 @@ from app.auth.forms import ( ResetPasswordRequestForm, UserCreationForm, ) -from app.auth.models import Role -from app.auth.models import User +from app.auth.models import Role, User, invalid_user_name from app.auth.email import send_password_reset_email from app.decorators import admin_required from app.models.config import ScoDocSiteConfig @@ -34,7 +33,11 @@ def _login_form(): """le formulaire de login, avec un lien CAS s'il est configuré.""" form = LoginForm() if form.validate_on_submit(): - user = User.query.filter_by(user_name=form.user_name.data).first() + # note: ceci est la première requête SQL déclenchée par un utilisateur arrivant + if invalid_user_name(form.user_name.data): + user = None + else: + user = User.query.filter_by(user_name=form.user_name.data).first() if user is None or not user.check_password(form.password.data): current_app.logger.info("login: invalid (%s)", form.user_name.data) flash(_("Nom ou mot de passe invalide"))