from typing import Dict, List, Optional, Tuple from datetime import datetime import pytz from supabase import Client, create_client import os from dotenv import load_dotenv import logging # gardez l'import de logging même si nous n'utilisons plus directement ses fonctions de log, car nous avons toujours besoin de ses constantes de niveau (level=logging.INFO/ERROR/WARNING) from utils.logging_utils import log_to_file # logging définis et importés depuis le fichier dédié: logging_utils.py """ le fichier utils/admin.py gère : La gestion des utilisateurs Les permissions des assistants Les statistiques utilisateurs Les mises à jour des informations utilisateur Pour tester les modifications après, nous pourrons : Nous connecter en tant qu'administrateur Effectuer des opérations dans le dashboard admin (modifier un utilisateur, changer des permissions, etc.) """ # Charger les variables d'environnement load_dotenv() supabase: Client = create_client(os.getenv("SUPABASE_URL"), os.getenv("SUPABASE_KEY")) def get_all_users() -> List[Dict]: """ Récupère la liste de tous les utilisateurs (fonction admin). Returns: List[Dict]: Liste des utilisateurs avec leurs informations """ try: response = supabase.table("users").select("*").execute() return response.data if response.data else [] except Exception as e: log_to_file(f"Erreur lors de la récupération des utilisateurs : {str(e)}", level=logging.ERROR) return [] def toggle_user_status(user_id: int, is_active: bool) -> Tuple[bool, str]: """ Active ou désactive un compte utilisateur (fonction admin). Args: user_id (int): ID de l'utilisateur is_active (bool): Nouvel état du compte Returns: Tuple[bool, str]: (Succès, Message) """ try: supabase.table("users").update({"is_active": is_active}).eq("id", user_id).execute() status = "activé" if is_active else "désactivé" return True, f"Compte utilisateur {status} avec succès" except Exception as e: log_to_file(f"Erreur lors de la modification du statut utilisateur : {str(e)}", level=logging.ERROR) return False, f"Erreur lors de la modification du statut : {str(e)}" def change_user_role(user_id: int, new_role: str) -> Tuple[bool, str]: """ Modifie le rôle d'un utilisateur (fonction admin). Args: user_id (int): ID de l'utilisateur new_role (str): Nouveau rôle ('admin' ou 'user') Returns: Tuple[bool, str]: (Succès, Message) """ if new_role not in ['admin', 'user']: return False, "Rôle invalide" try: supabase.table("users").update({"role": new_role}).eq("id", user_id).execute() return True, f"Rôle modifié avec succès en {new_role}" except Exception as e: log_to_file(f"Erreur lors de la modification du rôle : {str(e)}", level=logging.ERROR) return False, f"Erreur lors de la modification du rôle : {str(e)}" def get_user_stats() -> Dict: """ Récupère des statistiques sur les utilisateurs (fonction admin). Returns: Dict: Statistiques des utilisateurs """ try: total = supabase.table("users").select("count", count="exact").execute() active = supabase.table("users").select("count", count="exact").eq("is_active", True).execute() admins = supabase.table("users").select("count", count="exact").eq("role", "admin").execute() return { "total_users": total.count if hasattr(total, 'count') else 0, "active_users": active.count if hasattr(active, 'count') else 0, "admin_users": admins.count if hasattr(admins, 'count') else 0, "last_updated": datetime.now(pytz.UTC).isoformat() } except Exception as e: log_to_file(f"Erreur lors de la récupération des statistiques : {str(e)}", level=logging.ERROR) return { "total_users": 0, "active_users": 0, "admin_users": 0, "error": str(e) } def update_user_info(user_id: int, updates: Dict) -> Tuple[bool, str]: """ Met à jour les informations d'un utilisateur (fonction admin). Args: user_id (int): ID de l'utilisateur updates (Dict): Dictionnaire contenant les champs à mettre à jour Returns: Tuple[bool, str]: (Succès, Message) """ allowed_fields = {'nom', 'prenom', 'email', 'professional_info', 'is_active', 'role'} update_data = {k: v for k, v in updates.items() if k in allowed_fields} if not update_data: return False, "Aucun champ valide à mettre à jour" try: supabase.table("users").update(update_data).eq("id", user_id).execute() return True, "Informations utilisateur mises à jour avec succès" except Exception as e: log_to_file(f"Erreur lors de la mise à jour des informations utilisateur : {str(e)}", level=logging.ERROR) return False, f"Erreur lors de la mise à jour : {str(e)}" def get_user_permissions(user_id: int) -> Dict[str, bool]: """ Récupère les autorisations d'accès aux assistants pour un utilisateur. """ try: response = supabase.table("user_assistant_permissions").select( "assistant_type", "is_authorized" ).eq("user_id", user_id).execute() # Convertir la réponse en dictionnaire permissions = { 'insuranceSANTE': False, 'insuranceCAR': False, 'insuranceBTP': False, 'RH': False, 'Pilotage': False } if response.data: for perm in response.data: permissions[perm['assistant_type']] = perm['is_authorized'] return permissions except Exception as e: log_to_file(f"Erreur lors de la récupération des permissions : {str(e)}", level=logging.ERROR) return { 'insuranceSANTE': False, 'insuranceCAR': False, 'insuranceBTP': False, 'RH': False, 'Pilotage': False } def update_user_permissions(user_id: int, assistant_type: str, is_authorized: bool) -> Tuple[bool, str]: """ Met à jour les autorisations d'accès d'un utilisateur pour un assistant spécifique. """ try: # Convertir user_id en int standard Python user_id = int(user_id) # Ajoutez cette ligne # Vérifier si une permission existe déjà existing = supabase.table("user_assistant_permissions").select("*").eq( "user_id", user_id ).eq("assistant_type", assistant_type).execute() if existing.data: # Mettre à jour la permission existante supabase.table("user_assistant_permissions").update({ "is_authorized": is_authorized, "modified_at": datetime.now(pytz.UTC).isoformat() }).eq("user_id", user_id).eq("assistant_type", assistant_type).execute() else: # Créer une nouvelle permission supabase.table("user_assistant_permissions").insert({ "user_id": user_id, "assistant_type": assistant_type, "is_authorized": is_authorized }).execute() return True, f"Autorisation {'accordée' if is_authorized else 'retirée'} avec succès" except Exception as e: log_to_file(f"Erreur lors de la mise à jour des permissions : {str(e)}", level=logging.ERROR) return False, str(e) def initialize_user_permissions(user_id: int) -> bool: """ Initialise les permissions par défaut pour un nouvel utilisateur. """ try: default_permissions = [ {"user_id": user_id, "assistant_type": "insuranceSANTE", "is_authorized": False}, {"user_id": user_id, "assistant_type": "insuranceCAR", "is_authorized": False}, {"user_id": user_id, "assistant_type": "insuranceBTP", "is_authorized": False}, {"user_id": user_id, "assistant_type": "Pilotage", "is_authorized": False}, {"user_id": user_id, "assistant_type": "RH", "is_authorized": False}, ] supabase.table("user_assistant_permissions").insert(default_permissions).execute() return True except Exception as e: log_to_file(f"Erreur lors de l'initialisation des permissions : {str(e)}", level=logging.ERROR) return False