Ajout notification par mail à la création d'user
This commit is contained in:
@@ -130,14 +130,17 @@ def hash_password(plain: str, rounds: int = 12) -> str:
|
||||
salt = bcrypt.gensalt(rounds=rounds)
|
||||
return bcrypt.hashpw(plain.encode("utf-8"), salt).decode("utf-8")
|
||||
|
||||
def user_exists(cur, username: str, email: str) -> bool:
|
||||
cur.execute(
|
||||
"SELECT COUNT(*) FROM Utilisateurs WHERE NomUtilisateur=%s OR email=%s",
|
||||
(username, email),
|
||||
)
|
||||
def user_exists(cur, username: str) -> bool:
|
||||
cur.execute("SELECT COUNT(*) FROM Utilisateurs WHERE NomUtilisateur=%s", (username,))
|
||||
(count,) = cur.fetchone()
|
||||
return count > 0
|
||||
|
||||
def find_users_by_email(cnx, email: str):
|
||||
with cnx.cursor(dictionary=True) as cur:
|
||||
cur.execute(
|
||||
"SELECT NomUtilisateur, Site FROM Utilisateurs WHERE email=%s ORDER BY NomUtilisateur",
|
||||
(email,),
|
||||
)
|
||||
return cur.fetchall()
|
||||
def list_users(cnx, limit: int = 500, include_password=False):
|
||||
fields = [
|
||||
"NomUtilisateur", "Nom_complet", "Site", "DateExpiration",
|
||||
@@ -159,8 +162,10 @@ def insert_user(cnx, username, full_name, site, password, expires, phone, email,
|
||||
pwd_hash = hash_password(password)
|
||||
|
||||
with cnx.cursor() as cur:
|
||||
if user_exists(cur, username, email):
|
||||
raise RuntimeError("Nom d'utilisateur ou email déjà existant.")
|
||||
# ✅ vérif uniquement sur NomUtilisateur
|
||||
if user_exists(cur, username):
|
||||
raise RuntimeError("Nom d'utilisateur déjà existant.")
|
||||
|
||||
if store_plain:
|
||||
cur.execute(
|
||||
"""
|
||||
@@ -181,6 +186,7 @@ def insert_user(cnx, username, full_name, site, password, expires, phone, email,
|
||||
)
|
||||
return pwd_hash
|
||||
|
||||
|
||||
def get_user_details(cnx, username: str):
|
||||
with cnx.cursor(dictionary=True) as cur:
|
||||
cur.execute(
|
||||
@@ -362,8 +368,10 @@ with tab_list:
|
||||
except Exception as e:
|
||||
st.warning(f"Impossible de lister les utilisateurs : {e}")
|
||||
|
||||
# -----------------------
|
||||
# ONGLET CREER
|
||||
# -----------------------
|
||||
|
||||
# --- Onglet Créer ---
|
||||
with tab_create:
|
||||
with st.form("create_user_form", clear_on_submit=False):
|
||||
st.subheader("Nouveau compte")
|
||||
@@ -381,19 +389,33 @@ with tab_create:
|
||||
c7, c8 = st.columns(2)
|
||||
password = c7.text_input("Mot de passe", type="password")
|
||||
password2 = c8.text_input("Confirmer", type="password")
|
||||
store_plain = st.checkbox("Stocker le mot de passe en clair (déconseillé)", value=False)
|
||||
|
||||
col_cb1, col_cb2 = st.columns([1.2, 1])
|
||||
# si tu stockes encore le mot de passe en clair dans la table
|
||||
store_plain = col_cb1.checkbox("Stocker le mot de passe en clair (déconseillé)", value=False)
|
||||
# ✅ nouvelle case pour l'e-mail de bienvenue à la création
|
||||
notify_welcome = col_cb2.checkbox("Envoyer un e-mail de bienvenue", value=True,
|
||||
help="Enverra l'identifiant, le nom, le site et le mot de passe en clair")
|
||||
|
||||
submitted = st.form_submit_button("Créer l'utilisateur", use_container_width=True)
|
||||
|
||||
if submitted:
|
||||
if not username or not full_name or not site or not email:
|
||||
st.error("Champs requis manquants.")
|
||||
elif not EMAIL_RE.match(email):
|
||||
st.error("Format d’e-mail invalide.")
|
||||
elif password != password2:
|
||||
st.error("Les mots de passe ne correspondent pas.")
|
||||
else:
|
||||
try:
|
||||
cnx = pool.get_connection()
|
||||
try:
|
||||
# 🔎 avertir si l'e-mail existe déjà (mais on n'empêche pas)
|
||||
dup = find_users_by_email(cnx, email)
|
||||
if dup:
|
||||
liste = ", ".join(f"{u['NomUtilisateur']}@{u['Site']}" for u in dup)
|
||||
st.info(f"Cet e-mail est déjà utilisé par : {liste}")
|
||||
|
||||
pwd_hash = insert_user(
|
||||
cnx, username=username, full_name=full_name, site=site,
|
||||
password=password, expires=expires, phone=phone, email=email,
|
||||
@@ -401,9 +423,44 @@ with tab_create:
|
||||
)
|
||||
finally:
|
||||
cnx.close()
|
||||
|
||||
st.success("Utilisateur créé avec succès ✅")
|
||||
st.caption("Hash (MotDePasseHash) :")
|
||||
st.code(pwd_hash)
|
||||
|
||||
# ✉️ Mail de bienvenue (optionnel)
|
||||
if notify_welcome:
|
||||
try:
|
||||
subj = f"[Compte créé] Vos accès — {site}"
|
||||
body_txt = (
|
||||
"Bonjour,\n\n"
|
||||
"Votre compte a été créé.\n\n"
|
||||
f"Nom d’utilisateur : {username}\n"
|
||||
f"Nom complet : {full_name}\n"
|
||||
f"Site : {site}\n"
|
||||
f"Mot de passe : {password}\n"
|
||||
f"Date d'expiration: {expires.strftime('%Y-%m-%d')}\n\n"
|
||||
"Cordialement."
|
||||
)
|
||||
body_html = f"""
|
||||
<html><body>
|
||||
<p>Bonjour,</p>
|
||||
<p>Votre compte a été créé.</p>
|
||||
<table cellpadding="6" cellspacing="0" border="0" style="border-collapse:collapse">
|
||||
<tr><td><b>Nom d’utilisateur</b></td><td>{username}</td></tr>
|
||||
<tr><td><b>Nom complet</b></td><td>{full_name}</td></tr>
|
||||
<tr><td><b>Site</b></td><td>{site}</td></tr>
|
||||
<tr><td><b>Mot de passe</b></td><td style="font-family:monospace">{password}</td></tr>
|
||||
<tr><td><b>Date d'expiration</b></td><td>{expires.strftime('%Y-%m-%d')}</td></tr>
|
||||
</table>
|
||||
<p>Cordialement.</p>
|
||||
</body></html>
|
||||
"""
|
||||
send_mail(email, subj, body_txt, body_html)
|
||||
st.success(f"✉️ E-mail de bienvenue envoyé à {email}")
|
||||
except Exception as e_mail:
|
||||
st.warning(f"E-mail non envoyé : {e_mail}")
|
||||
|
||||
except mysql.connector.Error as db_err:
|
||||
if db_err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
|
||||
st.error("Identifiants MySQL invalides.")
|
||||
@@ -412,7 +469,10 @@ with tab_create:
|
||||
except Exception as e:
|
||||
st.error(f"Erreur : {e}")
|
||||
|
||||
# --- Onglet Modifier ---
|
||||
# -----------------------
|
||||
# ONGLET MODIFIER
|
||||
# -----------------------
|
||||
|
||||
with tab_edit:
|
||||
st.subheader("Modifier un utilisateur existant")
|
||||
try:
|
||||
@@ -495,8 +555,10 @@ with tab_edit:
|
||||
st.error(f"Erreur MySQL : {db_err}")
|
||||
except Exception as e:
|
||||
st.error(f"Erreur : {e}")
|
||||
# -----------------------
|
||||
# ONGLET SECURITE
|
||||
# -----------------------
|
||||
|
||||
# --- Onglet Sécurité ---
|
||||
with tab_security:
|
||||
st.subheader("Réinitialiser le mot de passe (bcrypt)")
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user