Merge from Dev to LOAF Production #23

Merged
andika merged 4 commits from dev into loaf-prod 2026-01-07 08:43:15 +00:00
Showing only changes of commit d818d847bc - Show all commits

View File

@@ -60,11 +60,29 @@ async def lifespan(app: FastAPI):
# Shutdown
logger.info("Application shutdown")
# Environment detection
ENVIRONMENT = os.environ.get('ENVIRONMENT', 'development')
IS_PRODUCTION = ENVIRONMENT == 'production'
# Security: Disable API documentation in production
if IS_PRODUCTION:
print("🔒 Production mode: API documentation disabled")
app_config = {
"lifespan": lifespan,
"root_path": "/membership",
"docs_url": None, # Disable /docs
"redoc_url": None, # Disable /redoc
"openapi_url": None # Disable /openapi.json
}
else:
print("🔓 Development mode: API documentation enabled at /docs and /redoc")
app_config = {
"lifespan": lifespan,
"root_path": "/membership"
}
# Create the main app
app = FastAPI(
lifespan=lifespan,
root_path="/membership" # Configure for serving under /membership path
)
app = FastAPI(**app_config)
# Create a router with the /api prefix
api_router = APIRouter(prefix="/api")
@@ -6263,3 +6281,41 @@ app.add_middleware(
expose_headers=["*"],
max_age=600, # Cache preflight requests for 10 minutes
)
# Security Headers Middleware
@app.middleware("http")
async def add_security_headers(request: Request, call_next):
response = await call_next(request)
# Security headers to protect against common vulnerabilities
security_headers = {
# Prevent clickjacking attacks
"X-Frame-Options": "DENY",
# Prevent MIME type sniffing
"X-Content-Type-Options": "nosniff",
# Enable XSS protection in older browsers
"X-XSS-Protection": "1; mode=block",
# Control referrer information
"Referrer-Policy": "strict-origin-when-cross-origin",
# Permissions policy (formerly Feature-Policy)
"Permissions-Policy": "geolocation=(), microphone=(), camera=()",
}
# Add HSTS header in production (force HTTPS)
if IS_PRODUCTION:
security_headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
# Apply all security headers
for header, value in security_headers.items():
response.headers[header] = value
# Remove server identification headers
response.headers.pop("Server", None)
return response
print(f"✓ Security headers configured (Production: {IS_PRODUCTION})")