Harden backend security: IDOR fix, error sanitization, rate limiter fallback, security headers

- Fix task status IDOR by adding ownership check; suppress traceback/error in production
- Passkey routes: return generic error messages for internal exceptions, keep ValueError for user-facing
- JWT_SECRET and OIDC_CLIENT_ID: raise RuntimeError in production when using defaults
- Rate limiter: add in-memory fallback counter when Redis is unavailable
- Fix X-Forwarded-For IP spoofing with trusted_proxy_depth (rightmost-N selection)
- Add SecurityHeadersMiddleware (X-Content-Type-Options, X-Frame-Options, CSP, conditional HSTS)
- CORS: add PUT/DELETE methods for POI routes
- POI input validation: field length and coordinate range constraints
- QueryParameters: add min_sqm <= max_sqm validation
This commit is contained in:
Viktor Barzin 2026-02-08 19:42:30 +00:00
parent e431eaf2aa
commit 0a9a83507e
No known key found for this signature in database
GPG key ID: 0EB088298288D958
8 changed files with 133 additions and 32 deletions

View file

@ -2,7 +2,7 @@ import logging
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from pydantic import BaseModel, Field
from api.auth import User, get_current_user
from database import engine
@ -17,17 +17,17 @@ poi_router = APIRouter(prefix="/api/poi", tags=["poi"])
class CreatePOIRequest(BaseModel):
name: str
address: str
latitude: float
longitude: float
name: str = Field(max_length=200)
address: str = Field(max_length=500)
latitude: float = Field(ge=-90, le=90)
longitude: float = Field(ge=-180, le=180)
class UpdatePOIRequest(BaseModel):
name: str | None = None
address: str | None = None
latitude: float | None = None
longitude: float | None = None
name: str | None = Field(default=None, max_length=200)
address: str | None = Field(default=None, max_length=500)
latitude: float | None = Field(default=None, ge=-90, le=90)
longitude: float | None = Field(default=None, ge=-180, le=180)
class POIResponse(BaseModel):