From 9205c17b7e37409cf39b4d47e5d424cdc0aa67a3 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Tue, 26 Nov 2024 15:17:32 +0100
Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation/=C3=A9dition=20d'utilisateurs:=20?=
=?UTF-8?q?renforce=20warnings=20(mail=20inst.,=20cas=5Fid).?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/auth/models.py | 51 +++++++++++++++++++++++-----
app/templates/auth/user_info_page.j2 | 2 +-
2 files changed, 44 insertions(+), 9 deletions(-)
diff --git a/app/auth/models.py b/app/auth/models.py
index c9cfa137..b79ce703 100644
--- a/app/auth/models.py
+++ b/app/auth/models.py
@@ -12,7 +12,7 @@ from typing import Optional
import cracklib # pylint: disable=import-error
-from flask import current_app, g
+from flask import current_app, flash, g
from flask_login import UserMixin, AnonymousUserMixin
from sqlalchemy.exc import (
IntegrityError,
@@ -67,6 +67,14 @@ def is_valid_user_name(user_name: str) -> bool:
)
+def is_new_cas_id(cas_id: str) -> bool:
+ "Check that cas_id is a valid new id (uniqueness, allow nulls)"
+ if not cas_id:
+ return True
+ nb_with_this_id = db.session.query(User).filter_by(cas_id=cas_id).count()
+ return nb_with_this_id == 0
+
+
class User(UserMixin, ScoDocModel):
"""ScoDoc users, handled by Flask / SQLAlchemy"""
@@ -178,13 +186,16 @@ class User(UserMixin, ScoDocModel):
raise ValueError("invalid user_id")
return query.first_or_404() if not accept_none else query.first()
- def set_password(self, password):
+ def set_password(self, password: str):
"Set password"
log(f"set_password({self})")
+ previous_hash = self.password_hash
if password:
self.password_hash = generate_password_hash(password)
else:
self.password_hash = None
+ if self.password_hash != previous_hash:
+ self.date_modif_passwd = datetime.now()
# La création d'un mot de passe efface l'éventuel mot de passe historique
self.password_scodoc7 = None
self.passwd_temp = False
@@ -350,9 +361,7 @@ class User(UserMixin, ScoDocModel):
date_expiration = args.get("date_expiration")
if isinstance(date_expiration, str):
args["date_expiration"] = (
- datetime.fromisoformat(date_expiration)
- if date_expiration
- else None
+ datetime.fromisoformat(date_expiration) if date_expiration else None
)
# booléens:
for field in ("active", "cas_allow_login", "cas_allow_scodoc_login"):
@@ -394,17 +403,43 @@ class User(UserMixin, ScoDocModel):
role, dept = UserRole.role_dept_from_string(r_d)
self.add_role(role, dept)
- super().from_dict(args, excluded={"user_name", "roles_string", "roles"})
+ # email_institutionnel may not be unique, but check and warns user
+ email_institutionnel = args.get("email_institutionnel")
+ if email_institutionnel and email_institutionnel != self.email_institutionnel:
+ nb_with_this_mail = (
+ db.session.query(User)
+ .filter_by(email_institutionnel=email_institutionnel)
+ .count()
+ )
+ if nb_with_this_mail > 0:
+ log(
+ "User.from_dict: plusieurs utilisateurs avec ce mail institutionnel"
+ )
+ flash(
+ "Attention: plusieurs utilisateurs avec ce mail institutionnel",
+ "warning",
+ )
+
+ super().from_dict(
+ args, excluded={"cas_id", "user_name", "roles_string", "roles"}
+ )
+ new_cas_id = args.get("cas_id")
if ScoDocSiteConfig.cas_uid_use_scodoc():
- self.cas_id = self.user_name
+ new_cas_id = self.user_name
else:
# Set cas_id using regexp if configured:
exp = ScoDocSiteConfig.get("cas_uid_from_mail_regexp")
if exp and self.email_institutionnel:
cas_id = ScoDocSiteConfig.extract_cas_id(self.email_institutionnel)
if cas_id:
- self.cas_id = cas_id
+ new_cas_id = cas_id
+ if new_cas_id != self.cas_id:
+ if is_new_cas_id(new_cas_id):
+ self.cas_id = new_cas_id
+ else:
+ log(f"User.from_dict: CAS id invalide pour {self.user_name}")
+ raise ScoValueError(f"CAS id invalide pour {self.user_name}")
def get_token(self, expires_in=3600):
"Un jeton pour cet user. Stocké en base, non commité."
diff --git a/app/templates/auth/user_info_page.j2 b/app/templates/auth/user_info_page.j2
index 6b36704a..882b5370 100644
--- a/app/templates/auth/user_info_page.j2
+++ b/app/templates/auth/user_info_page.j2
@@ -39,7 +39,7 @@
{% endif %}
<div class="user_basics">
<b>Dernière modif mot de passe:</b>
- {{user.date_modif_passwd.strftime(scu.DATE_FMT) if user.date_modif_passwd else ""}}<br>
+ {{user.date_modif_passwd.strftime(scu.DATEATIME_FMT) if user.date_modif_passwd else ""}}<br>
<b>Date d'expiration:</b>
{{user.date_expiration.strftime(scu.DATE_FMT) if user.date_expiration else "(sans limite)"}}
</div>
--
GitLab