Arreglos de seguridad e historial

This commit is contained in:
Mireya Cueto Garrido
2026-03-27 12:46:45 +01:00
parent e19e971cd6
commit 111acc632e
4 changed files with 69 additions and 24 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ class DoCMFRequest(BaseModel):
core = info.data.get("core") core = info.data.get("core")
if core: if core:
a, b = 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.") raise ValueError("El núcleo debe estar dentro del soporte.")
return v return v
+27
View File
@@ -3,6 +3,13 @@ from api.database.mongodb import users_collection
from api.models.user_models import UserCreate, UserLogin from api.models.user_models import UserCreate, UserLogin
from api.utils.security import hash_password, verify_password, generate_token from api.utils.security import hash_password, verify_password, generate_token
from bson import ObjectId 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"]) router = APIRouter(prefix="/auth", tags=["auth"])
@@ -87,3 +94,23 @@ async def logout_user(user_id: str):
) )
return {"message": "Sesión cerrada correctamente"} 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"],
}
+17 -23
View File
@@ -1,34 +1,31 @@
from fastapi import APIRouter, HTTPException, status from fastapi import APIRouter, HTTPException, status, Depends
from typing import List
from datetime import datetime from datetime import datetime
from bson import ObjectId from bson import ObjectId
from api.database.mongodb import users_collection from api.database.mongodb import users_collection
from api.models.user_models import FuzzyTerm, HistoryCreateRequest from api.models.user_models import FuzzyTerm, HistoryCreateRequest
from api.utils.security import get_current_user
router = APIRouter(prefix="/history", tags=["history"]) router = APIRouter(prefix="/history", tags=["history"])
@router.post("/{user_id}/add") @router.post("/add")
async def add_history_item(user_id: str, data: HistoryCreateRequest): async def add_history_item(
user = await users_collection.find_one({"_id": ObjectId(user_id)}) data: HistoryCreateRequest,
if not user: current_user: dict = Depends(get_current_user),
raise HTTPException( ):
status_code=status.HTTP_404_NOT_FOUND, user_id = current_user["_id"]
detail="Usuario no encontrado",
)
history_item_id = ObjectId() history_item_id = ObjectId()
history_item = { history_item = {
"_id": history_item_id, "_id": history_item_id,
"name": data.name, # ← nuevo campo "name": data.name,
"created_at": datetime.utcnow(), "created_at": datetime.utcnow(),
"results": [r.dict() for r in data.results], "results": [r.dict() for r in data.results],
} }
await users_collection.update_one( await users_collection.update_one(
{"_id": ObjectId(user_id)}, {"_id": user_id},
{"$push": {"history": history_item}}, {"$push": {"history": history_item}},
) )
@@ -38,18 +35,15 @@ async def add_history_item(user_id: str, data: HistoryCreateRequest):
} }
@router.delete("/delete/{history_item_id}")
@router.delete("/{user_id}/delete/{history_item_id}") async def delete_history_item(
async def delete_history_item(user_id: str, history_item_id: str): history_item_id: str,
user = await users_collection.find_one({"_id": ObjectId(user_id)}) current_user: dict = Depends(get_current_user),
if not user: ):
raise HTTPException( user_id = current_user["_id"]
status_code=status.HTTP_404_NOT_FOUND,
detail="Usuario no encontrado",
)
result = await users_collection.update_one( result = await users_collection.update_one(
{"_id": ObjectId(user_id)}, {"_id": user_id},
{"$pull": {"history": {"_id": ObjectId(history_item_id)}}}, {"$pull": {"history": {"_id": ObjectId(history_item_id)}}},
) )
+24
View File
@@ -1,5 +1,9 @@
import secrets import secrets
from passlib.context import CryptContext 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") 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: def generate_token() -> str:
return secrets.token_hex(32) # 64 caracteres seguros 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