
- Implemented comprehensive multi-tenant data isolation using database-level security - Built JWT authentication system with role-based access control (Super Admin, Org Admin, User, Viewer) - Created RESTful API endpoints for user and organization operations - Added complete audit logging for all data modifications with IP tracking - Implemented API rate limiting and input validation with security middleware - Built webhook processing engine with async event handling and retry logic - Created external API call handlers with circuit breaker pattern and error handling - Implemented data synchronization between external services and internal data - Added integration health monitoring and status tracking - Created three mock external services (User Management, Payment, Communication) - Implemented idempotency for webhook processing to handle duplicates gracefully - Added comprehensive security headers and XSS/CSRF protection - Set up Alembic database migrations with proper SQLite configuration - Included extensive documentation and API examples Architecture features: - Multi-tenant isolation at database level - Circuit breaker pattern for external API resilience - Async background task processing - Complete audit trail with user context - Role-based permission system - Webhook signature verification - Request validation and sanitization - Health monitoring endpoints Co-Authored-By: Claude <noreply@anthropic.com>
110 lines
3.4 KiB
Python
110 lines
3.4 KiB
Python
from fastapi import FastAPI, Request
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
from slowapi.middleware import SlowAPIMiddleware
|
|
from slowapi.errors import RateLimitExceeded
|
|
import logging
|
|
from app.api.v1.api import api_router
|
|
from app.core.config import settings
|
|
from app.middleware.rate_limit import limiter, custom_rate_limit_exceeded_handler
|
|
from app.middleware.validation import validation_middleware, validate_request_size
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
app = FastAPI(
|
|
title=settings.PROJECT_NAME,
|
|
version=settings.PROJECT_VERSION,
|
|
openapi_url="/openapi.json",
|
|
docs_url="/docs",
|
|
redoc_url="/redoc"
|
|
)
|
|
|
|
# Add rate limiting middleware
|
|
app.state.limiter = limiter
|
|
app.add_middleware(SlowAPIMiddleware)
|
|
app.add_exception_handler(RateLimitExceeded, custom_rate_limit_exceeded_handler)
|
|
|
|
# Add CORS middleware
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Request validation middleware
|
|
@app.middleware("http")
|
|
async def security_middleware(request: Request, call_next):
|
|
# Validate request size
|
|
if not validate_request_size(request):
|
|
return JSONResponse(
|
|
status_code=413,
|
|
content={"error": "Request payload too large"}
|
|
)
|
|
|
|
# Validate headers
|
|
if not validation_middleware.sanitize_headers(dict(request.headers)):
|
|
return JSONResponse(
|
|
status_code=400,
|
|
content={"error": "Invalid request headers"}
|
|
)
|
|
|
|
response = await call_next(request)
|
|
|
|
# Add security headers
|
|
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
response.headers["X-Frame-Options"] = "DENY"
|
|
response.headers["X-XSS-Protection"] = "1; mode=block"
|
|
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
|
|
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
|
|
|
|
return response
|
|
|
|
# Include API routes
|
|
app.include_router(api_router, prefix=settings.API_V1_STR)
|
|
|
|
# Root endpoint
|
|
@app.get("/")
|
|
async def root():
|
|
"""Root endpoint with service information"""
|
|
return {
|
|
"service": settings.PROJECT_NAME,
|
|
"version": settings.PROJECT_VERSION,
|
|
"documentation": "/docs",
|
|
"health_check": "/api/v1/health",
|
|
"api_version": settings.API_V1_STR,
|
|
"description": "Multi-Tenant SaaS Platform with External Integrations",
|
|
"features": [
|
|
"Multi-tenant data isolation",
|
|
"JWT authentication with role management",
|
|
"RESTful API endpoints",
|
|
"Audit logging",
|
|
"API rate limiting",
|
|
"Webhook processing",
|
|
"External API integration",
|
|
"Circuit breaker pattern",
|
|
"Health monitoring"
|
|
]
|
|
}
|
|
|
|
# Global exception handler
|
|
@app.exception_handler(Exception)
|
|
async def global_exception_handler(request: Request, exc: Exception):
|
|
logger.error(f"Global exception: {str(exc)}", exc_info=True)
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"error": "Internal server error", "detail": "An unexpected error occurred"}
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(
|
|
"main:app",
|
|
host="0.0.0.0",
|
|
port=8000,
|
|
reload=True,
|
|
log_level="info"
|
|
) |