🐐 Several security fixes

This commit is contained in:
2026-07-29 16:30:14 +02:00
parent b42abe5f5e
commit c56498239f
21 changed files with 660 additions and 204 deletions
+11 -19
View File
@@ -6,9 +6,8 @@ from pydantic import BaseModel
from sqlalchemy.orm import Session
from services import notification_manager
from core.auth import decode_access_token
from core.database import get_db
from core.dependencies import get_current_user, get_user_id_from_request, limiter
from core.dependencies import accept_and_authenticate_ws, get_current_user, limiter, parse_uuid
from core.models import Card as CardModel
from core.models import Notification as NotificationModel
from core.models import TradeProposal as TradeProposalModel
@@ -64,12 +63,8 @@ def _serialize_proposal(p: TradeProposalModel, current_user_id: uuid.UUID, card_
@router.websocket("/ws/trade/queue")
async def trade_queue_endpoint(websocket: WebSocket, db: Session = Depends(get_db)):
await websocket.accept()
token = await websocket.receive_text()
user_id = decode_access_token(token)
user_id = await accept_and_authenticate_ws(websocket)
if not user_id:
await websocket.close(code=1008)
return
user = db.query(UserModel).filter(UserModel.id == uuid.UUID(user_id)).first()
@@ -99,12 +94,8 @@ async def trade_queue_endpoint(websocket: WebSocket, db: Session = Depends(get_d
@router.websocket("/ws/trade/{trade_id}")
async def trade_endpoint(websocket: WebSocket, trade_id: str, db: Session = Depends(get_db)):
await websocket.accept()
token = await websocket.receive_text()
user_id = decode_access_token(token)
user_id = await accept_and_authenticate_ws(websocket)
if not user_id:
await websocket.close(code=1008)
return
session = active_trades.get(trade_id)
@@ -138,7 +129,7 @@ class CreateTradeProposalRequest(BaseModel):
@router.post("/trade-proposals")
@limiter.limit("10/minute", key_func=get_user_id_from_request)
@limiter.limit("10/minute")
async def create_trade_proposal(
request: Request,
req: CreateTradeProposalRequest,
@@ -222,10 +213,7 @@ def get_trade_proposal(
user: UserModel = Depends(get_current_user),
db: Session = Depends(get_db),
):
try:
pid = uuid.UUID(proposal_id)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid proposal ID")
pid = parse_uuid(proposal_id, "proposal_id")
proposal = db.query(TradeProposalModel).filter(TradeProposalModel.id == pid).first()
if not proposal:
raise HTTPException(status_code=404, detail="Proposal not found")
@@ -241,12 +229,14 @@ def get_trade_proposal(
@router.post("/trade-proposals/{proposal_id}/accept")
@limiter.limit("30/minute")
async def accept_trade_proposal(
request: Request,
proposal_id: str,
user: UserModel = Depends(get_current_user),
db: Session = Depends(get_db),
):
proposal = db.query(TradeProposalModel).filter(TradeProposalModel.id == uuid.UUID(proposal_id)).with_for_update().first()
proposal = db.query(TradeProposalModel).filter(TradeProposalModel.id == parse_uuid(proposal_id, "proposal_id")).with_for_update().first()
if not proposal:
raise HTTPException(status_code=404, detail="Proposal not found")
if proposal.recipient_id != user.id:
@@ -339,12 +329,14 @@ async def accept_trade_proposal(
@router.post("/trade-proposals/{proposal_id}/decline")
@limiter.limit("30/minute")
async def decline_trade_proposal(
request: Request,
proposal_id: str,
user: UserModel = Depends(get_current_user),
db: Session = Depends(get_db),
):
proposal = db.query(TradeProposalModel).filter(TradeProposalModel.id == uuid.UUID(proposal_id)).first()
proposal = db.query(TradeProposalModel).filter(TradeProposalModel.id == parse_uuid(proposal_id, "proposal_id")).first()
if not proposal:
raise HTTPException(status_code=404, detail="Proposal not found")
if proposal.proposer_id != user.id and proposal.recipient_id != user.id: