ppt-tool/backend/api/middlewares/request_size_middleware.py
Vadym Samoilenko c431d4ab45 Implement critical security fixes and modern design system (Pre-launch P0 tasks)
Security Improvements (P0.0-P0.4):
- P0.0: Migrate to Gemini-only AI stack (simplified, single billing)
- P0.1: Fix CORS to restrict allowed origins from env (was *)
- P0.2: Remove hardcoded dev password, require env var
- P0.3: Add rate limiting (slowapi) - 3-10 req/min on sensitive endpoints
- P0.4: Add request size limits (100MB default via middleware)

New Features:
- Unified LLM service with Google Gemini priority
- OXML geometry extractor for layout parsing
- TSX validator for generated React components
- Client ID support in presentation requests with access control
- Configurable LLM/image timeouts via env vars

Modern Design System (P0.9 - partial):
- Enhanced CSS design tokens (primary, semantic colors, shadows)
- Typography scale (h1-h4, body variants, caption)
- Modern animations (fadeIn, slideIn, scaleIn)
- Updated Button component with better variants and hover effects
- Created unified Card and StatusBadge components
- Applied design system to Dashboard and Settings pages

Backend Improvements:
- Master deck parser simplification
- Slide-to-HTML endpoint cleanup (325 lines removed)
- Better error handling in prompts endpoint

Frontend Improvements:
- Settings UI simplified to show only Google/Gemini
- Dashboard uses CSS variables instead of hardcoded colors
- Improved button transitions and hover states

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-02-27 18:28:24 +00:00

38 lines
1.4 KiB
Python

"""
Request size limit middleware.
Rejects requests with Content-Length exceeding the configured maximum size.
Prevents memory exhaustion from uploading huge files.
"""
from fastapi import Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
class RequestSizeLimitMiddleware(BaseHTTPMiddleware):
"""Middleware to limit request body size."""
def __init__(self, app, max_size: int = 100 * 1024 * 1024): # 100MB default
super().__init__(app)
self.max_size = max_size
async def dispatch(self, request: Request, call_next):
"""Check Content-Length header and reject if too large."""
if request.method in ["POST", "PUT", "PATCH"]:
content_length = request.headers.get("content-length")
if content_length:
try:
size = int(content_length)
if size > self.max_size:
return JSONResponse(
status_code=413,
content={
"detail": f"Request body too large. Maximum size: {self.max_size / (1024 * 1024):.0f}MB"
},
)
except ValueError:
# Invalid Content-Length header, let the request proceed
pass
return await call_next(request)