Automated Action 2adbcd0535 Complete multi-tenant SaaS platform with external integrations
- 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>
2025-06-27 21:14:30 +00:00

109 lines
3.4 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy.orm import Session
from typing import List
from app.core.deps import get_db, get_current_active_user, require_roles
from app.models.user import User, UserRole
from app.schemas.user import UserResponse, UserCreate, UserUpdate
from app.services.user import UserService
router = APIRouter()
@router.get("/", response_model=List[UserResponse])
async def get_users(
skip: int = 0,
limit: int = 100,
current_user: User = Depends(require_roles([UserRole.ORG_ADMIN, UserRole.SUPER_ADMIN])),
db: Session = Depends(get_db)
):
user_service = UserService(db)
users = user_service.get_users(
organization_id=current_user.organization_id,
skip=skip,
limit=limit
)
return users
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
user_service = UserService(db)
# Users can view their own profile, admins can view any user in org
if (user_id != current_user.id and
current_user.role not in [UserRole.ORG_ADMIN, UserRole.SUPER_ADMIN]):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions"
)
user = user_service.get_user(user_id, current_user.organization_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return user
@router.post("/", response_model=UserResponse)
async def create_user(
request: Request,
user_data: UserCreate,
current_user: User = Depends(require_roles([UserRole.ORG_ADMIN, UserRole.SUPER_ADMIN])),
db: Session = Depends(get_db)
):
user_service = UserService(db)
return user_service.create_user(
user_data=user_data,
current_user=current_user,
ip_address=request.client.host,
user_agent=request.headers.get("user-agent", "")
)
@router.put("/{user_id}", response_model=UserResponse)
async def update_user(
request: Request,
user_id: int,
user_update: UserUpdate,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
# Users can update their own profile, admins can update any user in org
if (user_id != current_user.id and
current_user.role not in [UserRole.ORG_ADMIN, UserRole.SUPER_ADMIN]):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough permissions"
)
user_service = UserService(db)
return user_service.update_user(
user_id=user_id,
user_update=user_update,
current_user=current_user,
ip_address=request.client.host,
user_agent=request.headers.get("user-agent", "")
)
@router.delete("/{user_id}")
async def delete_user(
request: Request,
user_id: int,
current_user: User = Depends(require_roles([UserRole.ORG_ADMIN, UserRole.SUPER_ADMIN])),
db: Session = Depends(get_db)
):
user_service = UserService(db)
user_service.delete_user(
user_id=user_id,
current_user=current_user,
ip_address=request.client.host,
user_agent=request.headers.get("user-agent", "")
)
return {"message": "User deleted successfully"}