- Relajado Content-Security-Policy para permitir CDN e iframes - Eliminado X-Frame-Options que podia bloquear extensiones - Verificado: no hay iframes en el frontend
73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
from fastapi import FastAPI
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.responses import FileResponse
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
from app.database import engine, Base
|
|
from app.routers import models
|
|
from app.migrate import run_migrations
|
|
import os
|
|
|
|
# Create tables and run migrations
|
|
Base.metadata.create_all(bind=engine)
|
|
run_migrations()
|
|
|
|
app = FastAPI(title="PrintForge", version="2.2.0")
|
|
|
|
# CORS — allow production domain and local development
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=[
|
|
"https://3d.consultoria-as.com",
|
|
"http://localhost:8000",
|
|
"http://127.0.0.1:8000",
|
|
],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Security headers middleware
|
|
class SecurityHeadersMiddleware(BaseHTTPMiddleware):
|
|
async def dispatch(self, request, call_next):
|
|
response = await call_next(request)
|
|
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
|
|
# Permissive CSP: allow same-origin, CDN scripts, inline styles, images from anywhere
|
|
response.headers["Content-Security-Policy"] = (
|
|
"default-src * 'self' data: blob: 'unsafe-inline' 'unsafe-eval'; "
|
|
"script-src * 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.tailwindcss.com https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; "
|
|
"style-src * 'self' 'unsafe-inline'; "
|
|
"img-src * 'self' data: blob:; "
|
|
"font-src * 'self' data:; "
|
|
"connect-src * 'self';"
|
|
)
|
|
return response
|
|
|
|
app.add_middleware(SecurityHeadersMiddleware)
|
|
|
|
app.include_router(models.router)
|
|
|
|
# Serve static files
|
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
|
|
# Serve uploads, thumbnails and images directly
|
|
app.mount("/uploads", StaticFiles(directory="uploads"), name="uploads")
|
|
app.mount("/thumbnails", StaticFiles(directory="thumbnails"), name="thumbnails")
|
|
app.mount("/images", StaticFiles(directory="images"), name="images")
|
|
|
|
|
|
@app.get("/")
|
|
def root():
|
|
return FileResponse("static/index.html")
|
|
|
|
|
|
@app.get("/upload")
|
|
def upload_page():
|
|
return FileResponse("static/upload.html")
|
|
|
|
|
|
@app.get("/model/{model_id}")
|
|
def detail_page(model_id: int):
|
|
return FileResponse("static/detail.html")
|