Add subcription feature
This commit is contained in:
@@ -11,7 +11,8 @@ from app.schemas.tenants import (
|
||||
ChildTenantCreate,
|
||||
BulkChildTenantsCreate,
|
||||
BulkChildTenantsResponse,
|
||||
ChildTenantResponse
|
||||
ChildTenantResponse,
|
||||
TenantHierarchyResponse
|
||||
)
|
||||
from app.services.tenant_service import EnhancedTenantService
|
||||
from app.repositories.tenant_repository import TenantRepository
|
||||
@@ -219,6 +220,115 @@ async def get_tenant_children_count(
|
||||
)
|
||||
|
||||
|
||||
@router.get(route_builder.build_base_route("{tenant_id}/hierarchy", include_tenant_prefix=False), response_model=TenantHierarchyResponse)
|
||||
@track_endpoint_metrics("tenant_hierarchy")
|
||||
async def get_tenant_hierarchy(
|
||||
tenant_id: UUID = Path(..., description="Tenant ID"),
|
||||
current_user: Dict[str, Any] = Depends(get_current_user_dep),
|
||||
tenant_service: EnhancedTenantService = Depends(get_enhanced_tenant_service)
|
||||
):
|
||||
"""
|
||||
Get tenant hierarchy information.
|
||||
|
||||
Returns hierarchy metadata for a tenant including:
|
||||
- Tenant type (standalone, parent, child)
|
||||
- Parent tenant ID (if this is a child)
|
||||
- Hierarchy path (materialized path)
|
||||
- Number of child tenants (for parent tenants)
|
||||
- Hierarchy level (depth in the tree)
|
||||
|
||||
This endpoint is used by the authentication layer for hierarchical access control
|
||||
and by enterprise features for network management.
|
||||
"""
|
||||
try:
|
||||
logger.info(
|
||||
"Get tenant hierarchy request received",
|
||||
tenant_id=str(tenant_id),
|
||||
user_id=current_user.get("user_id"),
|
||||
user_type=current_user.get("type", "user"),
|
||||
is_service=current_user.get("type") == "service"
|
||||
)
|
||||
|
||||
# Get tenant from database
|
||||
from app.models.tenants import Tenant
|
||||
async with tenant_service.database_manager.get_session() as session:
|
||||
tenant_repo = TenantRepository(Tenant, session)
|
||||
|
||||
# Get the tenant
|
||||
tenant = await tenant_repo.get(str(tenant_id))
|
||||
if not tenant:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Tenant {tenant_id} not found"
|
||||
)
|
||||
|
||||
# Skip access check for service-to-service calls
|
||||
is_service_call = current_user.get("type") == "service"
|
||||
if not is_service_call:
|
||||
# Verify user has access to this tenant
|
||||
access_info = await tenant_service.verify_user_access(current_user["user_id"], str(tenant_id))
|
||||
if not access_info.has_access:
|
||||
logger.warning(
|
||||
"Access denied to tenant for hierarchy query",
|
||||
tenant_id=str(tenant_id),
|
||||
user_id=current_user.get("user_id")
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Access denied to tenant"
|
||||
)
|
||||
else:
|
||||
logger.debug(
|
||||
"Service-to-service call - bypassing access check",
|
||||
service=current_user.get("service"),
|
||||
tenant_id=str(tenant_id)
|
||||
)
|
||||
|
||||
# Get child count if this is a parent tenant
|
||||
child_count = 0
|
||||
if tenant.tenant_type in ["parent", "standalone"]:
|
||||
child_count = await tenant_repo.get_child_tenant_count(str(tenant_id))
|
||||
|
||||
# Calculate hierarchy level from hierarchy_path
|
||||
hierarchy_level = 0
|
||||
if tenant.hierarchy_path:
|
||||
# hierarchy_path format: "parent_id" or "parent_id.child_id" or "parent_id.child_id.grandchild_id"
|
||||
hierarchy_level = tenant.hierarchy_path.count('.')
|
||||
|
||||
# Build response
|
||||
hierarchy_info = TenantHierarchyResponse(
|
||||
tenant_id=str(tenant.id),
|
||||
tenant_type=tenant.tenant_type or "standalone",
|
||||
parent_tenant_id=str(tenant.parent_tenant_id) if tenant.parent_tenant_id else None,
|
||||
hierarchy_path=tenant.hierarchy_path,
|
||||
child_count=child_count,
|
||||
hierarchy_level=hierarchy_level
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"Get tenant hierarchy successful",
|
||||
tenant_id=str(tenant_id),
|
||||
tenant_type=tenant.tenant_type,
|
||||
parent_tenant_id=str(tenant.parent_tenant_id) if tenant.parent_tenant_id else None,
|
||||
child_count=child_count,
|
||||
hierarchy_level=hierarchy_level
|
||||
)
|
||||
|
||||
return hierarchy_info
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error("Get tenant hierarchy failed",
|
||||
tenant_id=str(tenant_id),
|
||||
user_id=current_user.get("user_id"),
|
||||
error=str(e))
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Get tenant hierarchy failed"
|
||||
)
|
||||
|
||||
|
||||
@router.post("/api/v1/tenants/{tenant_id}/bulk-children", response_model=BulkChildTenantsResponse)
|
||||
@track_endpoint_metrics("bulk_create_child_tenants")
|
||||
async def bulk_create_child_tenants(
|
||||
|
||||
Reference in New Issue
Block a user