Files
bakery-ia/services/tenant/app/api/tenants.py
2025-07-26 18:46:52 +02:00

158 lines
5.0 KiB
Python

# services/tenant/app/api/tenants.py
"""
Tenant API endpoints
"""
from fastapi import APIRouter, Depends, HTTPException, status, Path
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List, Dict, Any
import structlog
from uuid import UUID
from app.core.database import get_db
from app.schemas.tenants import (
BakeryRegistration, TenantResponse, TenantAccessResponse,
TenantUpdate, TenantMemberResponse
)
from app.services.tenant_service import TenantService
# Import unified authentication
from shared.auth.decorators import (
get_current_user_dep,
get_current_tenant_id_dep,
require_role
)
logger = structlog.get_logger()
router = APIRouter()
@router.post("/tenants/register", response_model=TenantResponse)
async def register_bakery(
bakery_data: BakeryRegistration,
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
try:
result = await TenantService.create_bakery(bakery_data, current_user["user_id"], db)
logger.info(f"Bakery registered: {bakery_data.name} by {current_user['email']}")
return result
except Exception as e:
logger.error(f"Bakery registration failed: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Bakery registration failed"
)
@router.get("/tenants/{tenant_id}/access/{user_id}", response_model=TenantAccessResponse)
async def verify_tenant_access(
user_id: str,
tenant_id: UUID = Path(..., description="Tenant ID"),
db: AsyncSession = Depends(get_db)
):
"""Verify if user has access to tenant - Called by Gateway"""
try:
access_info = await TenantService.verify_user_access(user_id, tenant_id, db)
return access_info
except Exception as e:
logger.error(f"Access verification failed: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Access verification failed"
)
@router.get("/tenants/users/{user_id}", response_model=List[TenantResponse])
async def get_user_tenants(
user_id: str,
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
# Users can only see their own tenants
if current_user["user_id"] != user_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied"
)
try:
tenants = await TenantService.get_user_tenants(user_id, db)
return tenants
except Exception as e:
logger.error(f"Failed to get user tenants: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve tenants"
)
@router.get("/tenants/{tenant_id}", response_model=TenantResponse)
async def get_tenant(
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
# Verify user has access to tenant
access = await TenantService.verify_user_access(current_user["user_id"], tenant_id, db)
if not access.has_access:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied to tenant"
)
tenant = await TenantService.get_tenant_by_id(tenant_id, db)
if not tenant:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Tenant not found"
)
return tenant
@router.put("/tenants/{tenant_id}", response_model=TenantResponse)
async def update_tenant(
update_data: TenantUpdate,
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
try:
result = await TenantService.update_tenant(tenant_id, update_data, current_user["user_id"], db)
return result
except HTTPException:
raise
except Exception as e:
logger.error(f"Tenant update failed: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Tenant update failed"
)
@router.post("/tenants/{tenant_id}/members", response_model=TenantMemberResponse)
async def add_team_member(
user_id: str,
role: str,
tenant_id: UUID = Path(..., description="Tenant ID"),
current_user: Dict[str, Any] = Depends(get_current_user_dep),
db: AsyncSession = Depends(get_db)
):
try:
result = await TenantService.add_team_member(
tenant_id, user_id, role, current_user["user_id"], db
)
return result
except HTTPException:
raise
except Exception as e:
logger.error(f"Add team member failed: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to add team member"
)