diff --git a/backend/api/models/docmf_models.py b/backend/api/models/docmf_models.py index 0cf9342..f96e2e9 100644 --- a/backend/api/models/docmf_models.py +++ b/backend/api/models/docmf_models.py @@ -32,7 +32,7 @@ class DoCMFRequest(BaseModel): core = info.data.get("core") if core: a, b = core - if not (c <= a < b <= d): + if not (c <= a <= b <= d): raise ValueError("El núcleo debe estar dentro del soporte.") return v diff --git a/backend/api/routers/auth.py b/backend/api/routers/auth.py index 2287379..e0d6c68 100644 --- a/backend/api/routers/auth.py +++ b/backend/api/routers/auth.py @@ -3,6 +3,13 @@ from api.database.mongodb import users_collection from api.models.user_models import UserCreate, UserLogin from api.utils.security import hash_password, verify_password, generate_token from bson import ObjectId +from fastapi import APIRouter, HTTPException, status, Depends +from api.utils.security import ( + hash_password, + verify_password, + generate_token, + get_current_user, +) router = APIRouter(prefix="/auth", tags=["auth"]) @@ -87,3 +94,23 @@ async def logout_user(user_id: str): ) return {"message": "Sesión cerrada correctamente"} + + +@router.post("/logout") +async def logout_user(current_user: dict = Depends(get_current_user)): + user_id = current_user["_id"] + + await users_collection.update_one( + {"_id": user_id}, + {"$set": {"token": None}}, + ) + + return {"message": "Sesión cerrada correctamente"} + +@router.get("/me") +async def get_me(current_user: dict = Depends(get_current_user)): + return { + "user_id": str(current_user["_id"]), + "username": current_user["username"], + "email": current_user["email"], + } diff --git a/backend/api/routers/history.py b/backend/api/routers/history.py index fadd769..43a260a 100644 --- a/backend/api/routers/history.py +++ b/backend/api/routers/history.py @@ -1,34 +1,31 @@ -from fastapi import APIRouter, HTTPException, status -from typing import List +from fastapi import APIRouter, HTTPException, status, Depends from datetime import datetime from bson import ObjectId from api.database.mongodb import users_collection from api.models.user_models import FuzzyTerm, HistoryCreateRequest +from api.utils.security import get_current_user router = APIRouter(prefix="/history", tags=["history"]) -@router.post("/{user_id}/add") -async def add_history_item(user_id: str, data: HistoryCreateRequest): - user = await users_collection.find_one({"_id": ObjectId(user_id)}) - if not user: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Usuario no encontrado", - ) +@router.post("/add") +async def add_history_item( + data: HistoryCreateRequest, + current_user: dict = Depends(get_current_user), +): + user_id = current_user["_id"] history_item_id = ObjectId() - history_item = { "_id": history_item_id, - "name": data.name, # ← nuevo campo + "name": data.name, "created_at": datetime.utcnow(), "results": [r.dict() for r in data.results], } await users_collection.update_one( - {"_id": ObjectId(user_id)}, + {"_id": user_id}, {"$push": {"history": history_item}}, ) @@ -38,18 +35,15 @@ async def add_history_item(user_id: str, data: HistoryCreateRequest): } - -@router.delete("/{user_id}/delete/{history_item_id}") -async def delete_history_item(user_id: str, history_item_id: str): - user = await users_collection.find_one({"_id": ObjectId(user_id)}) - if not user: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Usuario no encontrado", - ) +@router.delete("/delete/{history_item_id}") +async def delete_history_item( + history_item_id: str, + current_user: dict = Depends(get_current_user), +): + user_id = current_user["_id"] result = await users_collection.update_one( - {"_id": ObjectId(user_id)}, + {"_id": user_id}, {"$pull": {"history": {"_id": ObjectId(history_item_id)}}}, ) diff --git a/backend/api/utils/security.py b/backend/api/utils/security.py index 6dd73c5..5826361 100644 --- a/backend/api/utils/security.py +++ b/backend/api/utils/security.py @@ -1,5 +1,9 @@ import secrets from passlib.context import CryptContext +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer +from api.database.mongodb import users_collection +from bson import ObjectId pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -14,3 +18,23 @@ def verify_password(plain_password: str, hashed_password: str) -> bool: def generate_token() -> str: return secrets.token_hex(32) # 64 caracteres seguros + + +security_scheme = HTTPBearer() + + +async def get_current_user( + credentials: HTTPAuthorizationCredentials = Depends(security_scheme), +): + token = credentials.credentials + + user = await users_collection.find_one({"token": token}) + if not user: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Token inválido o usuario no autenticado", + ) + + # devolvemos el documento tal cual (dict) + user["id"] = str(user["_id"]) + return user \ No newline at end of file