Code/components/connexion.py
2025-05-13 16:31:53 +02:00

113 lines
4.7 KiB
Python

import streamlit as st
import requests
import logging
import os
from utils.translations import _
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():
if "logged_in" not in st.session_state or not st.session_state.logged_in:
auth_title = str(_("auth.title", "Authentification"))
st.html(f"""
<section role="region" aria-label="region-authentification">
<div role="region" aria-labelledby="Authentification">
<p id="Authentification" class="decorative-heading">{auth_title}</p>
""")
GITEA_URL = "https://fabnum-git.peccini.fr/api/v1"
ORGANISATION = "FabNum"
EQUIPE_CIBLE = "Administrateurs"
logger = initialiser_logger()
if "logged_in" not in st.session_state:
st.session_state.logged_in = False
st.session_state.username = ""
st.session_state.token = ""
if not st.session_state.logged_in:
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
identifiant = st.text_input(str(_("auth.username", "Identifiant_token")), value="fabnum-connexion", key="nom_utilisateur")
token = st.text_input(str(_("auth.token", "Token d'accès personnel Gitea")), type="password")
submitted = st.form_submit_button(str(_("auth.login", "Se connecter")))
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:
st.session_state.logged_in = True
st.session_state.username = username
st.session_state.token = token
erreur = False
logger.info(f"Connexion réussie pour {username} depuis IP {ip}")
st.rerun()
except requests.RequestException:
st.error(str(_("auth.gitea_error", "❌ Impossible de vérifier l'utilisateur auprès de Gitea.")))
if erreur:
logger.warning(f"Accès refusé pour tentative avec token depuis IP {ip}")
st.error(str(_("auth.error", "❌ Accès refusé.")))
st.html("""
</div>
</section>
""")
def bouton_deconnexion():
if st.session_state.get("logged_in", False):
auth_title = str(_("auth.title", "Authentification"))
st.html(f"""
<section role="region" aria-label="region-authentification">
<div role="region" aria-labelledby="Authentification">
<p id="Authentification" class="decorative-heading">{auth_title}</p>
""")
st.sidebar.markdown(f"{str(_('auth.logged_as', 'Connecté en tant que'))} `{st.session_state.username}`")
if st.sidebar.button(str(_("auth.logout", "Se déconnecter"))):
st.session_state.logged_in = False
st.session_state.username = ""
st.session_state.token = ""
st.success(str(_("auth.success", "Déconnecté avec succès.")))
st.rerun()
st.html("""
</div>
</section>
""")