from fastapi import APIRouter, Request, Response, HTTPException, Depends from datetime import datetime, timedelta from passlib.hash import bcrypt import secrets from bson.objectid import ObjectId from database import get_db router = APIRouter(prefix="/api", tags=["Authentification"]) @router.post("/register") async def register(request: Request): data = await request.json() db = get_db() required_fields = ["prenom", "nom", "email", "password"] for field in required_fields: if not data.get(field): raise HTTPException(status_code=400, detail=f"Le champ {field} est requis") existing_user = db.users.find_one({"email": data["email"]}) if existing_user: raise HTTPException(status_code=409, detail="Cet email est déjà utilisé") hashed_password = bcrypt.hash(data["password"]) user = { "prenom": data["prenom"], "nom": data["nom"], "email": data["email"], "password": hashed_password, "createdAt": datetime.utcnow(), "role": data.get("role", "user"), } result = db.users.insert_one(user) return {"message": "Utilisateur créé avec succès", "userId": str(result.inserted_id)} @router.post("/login") async def login(request: Request, response: Response): try: data = await request.json() db = get_db() email = data.get("email") password = data.get("password") user = db.users.find_one({"email": email}) if not user or not bcrypt.verify(password, user["password"]): raise HTTPException(status_code=401, detail="Email ou mot de passe incorrect") session_id = secrets.token_hex(16) user_id = str(user["_id"]) username = f"{user['prenom']} {user['nom']}" db.sessions.insert_one({ "session_id": session_id, "user_id": user_id, "created_at": datetime.utcnow(), "expires_at": datetime.utcnow() + timedelta(days=7) }) response.set_cookie( key="session_id", value=session_id, httponly=False, max_age=7*24*60*60, samesite="none", secure=True, path="/" ) print(f"Session : {session_id} pour {user_id}") return { "success": True, "username": username, "user_id": user_id, "session_id": session_id, "role": user.get("role", "user") } except Exception as e: print(f"Erreur login: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/logout") async def logout(request: Request, response: Response): db = get_db() session_id = request.cookies.get("session_id") if session_id: db.sessions.delete_one({"session_id": session_id}) response.delete_cookie(key="session_id") return {"success": True} async def get_current_user(request: Request): db = get_db() session_id = request.cookies.get("session_id") print(f"Cookie: {session_id[:5] if session_id else 'None'}") if not session_id: auth_header = request.headers.get("Authorization") if auth_header and auth_header.startswith("Bearer "): session_id = auth_header.replace("Bearer ", "") print(f"Session reçue: {session_id[:5]}...") if not session_id: session_id = request.query_params.get("session_id") if session_id: print(f"Session des paramètres de requête: {session_id[:5]}...") if not session_id: raise HTTPException(status_code=401, detail="Non authentifié - Aucune session trouvée") session = db.sessions.find_one({ "session_id": session_id, "expires_at": {"$gt": datetime.utcnow()} }) if not session: raise HTTPException(status_code=401, detail="Session expirée ou invalide") user = db.users.find_one({"_id": ObjectId(session["user_id"])}) if not user: raise HTTPException(status_code=401, detail="Utilisateur non trouvé") return user async def get_admin_user(request: Request): user = await get_current_user(request) if user["role"] != "Administrateur": raise HTTPException(status_code=403, detail="Droits d'administrateur requis") return user