
- 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>
33 lines
1.2 KiB
Python
33 lines
1.2 KiB
Python
from fastapi import Request, status
|
|
from fastapi.responses import JSONResponse
|
|
from slowapi import Limiter
|
|
from slowapi.util import get_remote_address
|
|
from slowapi.errors import RateLimitExceeded
|
|
from app.core.config import settings
|
|
import redis
|
|
|
|
# Initialize Redis connection for rate limiting
|
|
try:
|
|
redis_client = redis.from_url(settings.REDIS_URL)
|
|
redis_client.ping() # Test connection
|
|
except Exception:
|
|
# Fallback to in-memory storage if Redis is not available
|
|
redis_client = None
|
|
|
|
limiter = Limiter(
|
|
key_func=get_remote_address,
|
|
storage_uri=settings.REDIS_URL if redis_client else "memory://",
|
|
default_limits=[f"{settings.RATE_LIMIT_REQUESTS}/{settings.RATE_LIMIT_WINDOW}second"]
|
|
)
|
|
|
|
def custom_rate_limit_exceeded_handler(request: Request, exc: RateLimitExceeded):
|
|
response = JSONResponse(
|
|
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
|
content={
|
|
"error": "Rate limit exceeded",
|
|
"message": f"Rate limit exceeded: {exc.detail}",
|
|
"retry_after": str(exc.retry_after) if exc.retry_after else None
|
|
}
|
|
)
|
|
response.headers["Retry-After"] = str(exc.retry_after) if exc.retry_after else "60"
|
|
return response |