diff --git a/domo91.py b/domo91.py index 9b08b77..ba174d8 100644 --- a/domo91.py +++ b/domo91.py @@ -9,6 +9,7 @@ import os import random from dotenv import load_dotenv from datetime import datetime, date, time +import bcrypt # Charger les variables d'environnement load_dotenv() @@ -174,7 +175,9 @@ if not st.session_state.get("authenticated"): cursor = conn.cursor(dictionary=True) cursor.execute("SELECT * FROM MotsDePasse WHERE utilisateur = %s", (login,)) result = cursor.fetchone() - if result and result["mot_de_passe"] == password: + def verifier_password(mot_de_passe_saisi, hash_en_base): + return bcrypt.checkpw(mot_de_passe_saisi.encode('utf-8'), hash_en_base.encode('utf-8')) + if result and verifier_password(password, result["mot_de_passe"]): if result["Expiration"] and result["Expiration"] < date.today(): st.sidebar.error("⛔ Votre accès a expiré. Veuillez contacter un administrateur.") cursor.close() @@ -209,12 +212,36 @@ else: st.session_state["lieu_autorise"] = None st.rerun() +def hash_password(password): + return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') + +def ajouter_utilisateur(utilisateur, mot_de_passe, role, lieu, expiration): + try: + conn = mysql.connector.connect(**db_config) + cursor = conn.cursor() + cursor.execute("SELECT * FROM MotsDePasse WHERE utilisateur = %s", (utilisateur,)) + if cursor.fetchone(): + return False, "❌ Utilisateur déjà existant." + + hash_mdp = hash_password(mot_de_passe) + cursor.execute(""" + INSERT INTO MotsDePasse (utilisateur, mot_de_passe, role, Lieu, Expiration) + VALUES (%s, %s, %s, %s, %s) + """, (utilisateur, hash_mdp, role, lieu, expiration)) + conn.commit() + cursor.close() + conn.close() + return True, "✅ Utilisateur ajouté avec succès." + except Exception as e: + return False, f"⚠️ Erreur : {e}" + # 📄 Affichage bouton PDF si une date est choisie site_pdf = ( st.session_state.get("lieu_autorise") if st.session_state.get("role") != "superviseur" - else st.session_state.get("selected_site") -) + + else st.session_state.get("selected_site") + ) date_pdf = st.session_state.get("selected_date") if site_pdf and date_pdf: st.sidebar.markdown("---") @@ -354,7 +381,7 @@ if st.session_state["authenticated"]: if st.session_state.get("authenticated"): if st.session_state["role"] == "superviseur": - onglets_possibles = ["Accueil", "Statistiques", "Entretien", "Traffic"] + onglets_possibles = ["Accueil", "Statistiques", "Entretien", "Traffic", "Utilisateurs"] else: onglets_possibles = ["Accueil", "Entretien"] @@ -713,5 +740,52 @@ if st.session_state["authenticated"]: except Exception as e: st.error(f"Erreur chargement des connexions : {e}") - except Exception as er: - st.error(f"Erreur MySQL : {er}") + # --- ONGLET UTILISATEURS --- + elif onglet == "Utilisateurs" and st.session_state.get("role") == "superviseur": + st.title("👥 Gestion des utilisateurs") + + # --- Section Ajout --- + with st.expander("➕ Ajouter un nouvel utilisateur"): + new_user = st.text_input("Nom d'utilisateur") + new_pass = st.text_input("Mot de passe", type="password") + new_role = st.selectbox("Rôle", ["simple", "superviseur"]) + new_lieu = None + if new_role == "simple": + new_lieu = st.selectbox("Lieu autorisé", ["Saclay", "Meudon", "Roissy"]) + expiration = st.date_input("Date d'expiration (facultative)", value=None) + + if st.button("Créer l'utilisateur"): + if new_user and new_pass: + success, message = ajouter_utilisateur( + utilisateur=new_user, + mot_de_passe=new_pass, + role=new_role, + lieu=new_lieu if new_role == "simple" else None, + expiration=expiration if expiration else None + ) + if success: + st.success(message) + else: + st.error(message) + else: + st.warning("Tous les champs obligatoires doivent être remplis.") + + # --- Section Liste --- + st.markdown("### 📋 Utilisateurs existants") + try: + conn = mysql.connector.connect(**db_config) + cursor = conn.cursor(dictionary=True) + cursor.execute("SELECT utilisateur, role, Lieu, Expiration FROM MotsDePasse ORDER BY utilisateur") + users = cursor.fetchall() + cursor.close() + conn.close() + + if users: + import pandas as pd + + df_users = pd.DataFrame(users) + st.dataframe(df_users) + else: + st.info("Aucun utilisateur trouvé.") + except Exception as e: + st.error(f"Erreur lors du chargement des utilisateurs : {e}") \ No newline at end of file diff --git a/hash_passwords.py b/hash_passwords.py new file mode 100644 index 0000000..2cfe2be --- /dev/null +++ b/hash_passwords.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +import mysql.connector +import bcrypt +from dotenv import load_dotenv +import os + +# Charger les variables d'environnement depuis .env +load_dotenv() + +conn = mysql.connector.connect( + host=os.getenv("DB_HOST"), + user=os.getenv("DB_USER"), + password=os.getenv("DB_PASSWORD"), + database=os.getenv("DB_NAME") +) +cursor = conn.cursor() + +cursor.execute("SELECT utilisateur, mot_de_passe FROM MotsDePasse") +utilisateurs = cursor.fetchall() + +def hash_password(plain_text_password): + return bcrypt.hashpw(plain_text_password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') + +for utilisateur, mot_de_passe in utilisateurs: + if mot_de_passe.startswith('$2b$') or mot_de_passe.startswith('$2a$'): + print(f"{utilisateur} : déjà haché") + continue + + hashe = hash_password(mot_de_passe) + cursor.execute("UPDATE MotsDePasse SET mot_de_passe = %s WHERE utilisateur = %s", (hashe, utilisateur)) + print(f"{utilisateur} : mot de passe haché") + +conn.commit() +conn.close() +print("Mise à jour terminée.") + + + + diff --git a/requirements.txt b/requirements.txt index 14727e4..86c7db9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,5 @@ schedule~=1.2.2 paramiko~=3.5.1 dotenv fpdf -ovh \ No newline at end of file +ovh +bcrypt