import streamlit as st import requests import logging import os from utils.translations import _ from utils.persistance import get_champ_statut, maj_champ_statut def initialiser_logger(): LOG_FILE_PATH = "/var/log/fabnum-auth.log" if not os.path.exists(os.path.dirname(LOG_FILE_PATH)): os.makedirs(os.path.dirname(LOG_FILE_PATH), exist_ok=True) logger = logging.getLogger("auth_logger") logger.setLevel(logging.INFO) if not logger.hasHandlers(): fh = logging.FileHandler(LOG_FILE_PATH) formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) return logger def connexion(): login = get_champ_statut("login") if login == "": auth_title = str(_("auth.title")) st.html(f"""

{auth_title}

""") GITEA_URL = "https://fabnum-git.peccini.fr/api/v1" ORGANISATION = "FabNum" EQUIPE_CIBLE = "Administrateurs" logger = initialiser_logger() if get_champ_statut("login") == "": with st.form("auth_form"): # Ajout d'un champ identifiant fictif pour activer l'autocomplétion navigateur # et permettre de stocker le token comme un mot de passe par le navigateur # L'identifiant n'est donc pas utilisé par la suite ; il est caché en CSS identifiant = st.text_input(str(_("auth.username")), value="fabnum-connexion", key="nom_utilisateur") token = st.text_input(str(_("auth.token")), type="password") submitted = st.form_submit_button(str(_("auth.login")), icon=":material/login:") if submitted and token: erreur = True headers = {"Authorization": f"token {token}"} ip = os.environ.get("REMOTE_ADDR", "inconnu") username = "inconnu" try: user_response = requests.get(f"{GITEA_URL}/user", headers=headers, timeout=5) user_response.raise_for_status() utilisateur = user_response.json() username = utilisateur.get("login", "inconnu") logger.info(f"Tentative par {username} depuis IP {ip}") teams_url = f"{GITEA_URL}/orgs/{ORGANISATION}/teams" teams_response = requests.get(teams_url, headers=headers, timeout=5) teams_response.raise_for_status() equipes = teams_response.json() equipe_admin = next((e for e in equipes if e["name"] == EQUIPE_CIBLE), None) if equipe_admin: team_id = equipe_admin["id"] check_url = f"{GITEA_URL}/teams/{team_id}/members/{username}" check_response = requests.get(check_url, headers=headers, timeout=5) if check_response.status_code == 200: erreur = False maj_champ_statut("login", username) logger.info(f"Connexion réussie pour {username} depuis IP {ip}") st.rerun() except requests.RequestException: st.error(str(_("auth.gitea_error"))) if erreur: logger.warning(f"Accès refusé pour tentative avec token depuis IP {ip}") st.error(str(_("auth.error"))) st.html("""
""") def bouton_deconnexion(): login = get_champ_statut("login") if not login == "": auth_title = str(_("auth.title")) st.html(f"""

{auth_title}

""") st.sidebar.markdown(f"{str(_('auth.logged_as'))} `{login}`") if st.sidebar.button(str(_("auth.logout")), icon=":material/logout:"): maj_champ_statut("login", "") st.success(str(_("auth.success"))) st.rerun() st.html("""
""")