|
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 |