Files
taiji-AI-PAD/services/mcp-server/app/permissions.py
T
2026-01-05 10:09:07 +00:00

218 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
权限管理辅助模块
权限层级设计:
- super_admin(超级管理员): 全部权限,包括:
- 可创建渠道,也可创建渠道下的计费管理员、运维管理员和租户
- 拥有所有供应商管理权限(manage:providers),可创建、更新、删除供应商
- 可审批所有申请(包括资源申请和供应商申请)
- 可管理所有管理员
- 可查看和管理所有渠道、租户、资源、计费等信息
- billing_admin(计费管理员): 渠道下的计费管理员,完整写入权限,可管理该渠道下的租户、计费操作
- operations_admin(运维管理员): 渠道下的运维管理员,只读权限,仅查看和监控该渠道的数据
- channel_admin(渠道管理员): 管理自己渠道下的租户,可创建该渠道的计费管理员、运维管理员和租户
- provider_admin(供应商管理员): 管理模型供应商(仅供应商管理权限)
- user(用户): 普通用户权限
注意:
- 计费管理员和运维管理员必须关联到某个渠道(channel_id)
- 超级管理员可以创建渠道,也可以创建该渠道下的计费管理员、运维管理员和租户
- 渠道管理员可以创建该渠道的计费管理员、运维管理员和租户
- 超级管理员拥有所有权限,包括供应商管理权限,可以执行所有供应商相关操作
"""
from typing import List, Set
# 权限定义
PERMISSIONS = {
# 查看权限(只读)
"view:overview": "查看概览",
"view:channels": "查看渠道列表",
"view:tenants": "查看租户列表",
"view:resources": "查看资源",
"view:agents": "查看Agent",
"view:billing": "查看计费记录",
"view:monitoring": "查看监控",
"view:applications": "查看申请",
"view:admins": "查看管理员列表",
# 管理权限(写入)
"manage:channels": "管理渠道(增删改)",
"manage:tenants": "管理租户(增删改)",
"manage:resources": "管理资源分配",
"manage:agents": "管理Agent配置",
"manage:billing": "管理计费(充值、设置)",
"manage:settings": "管理系统设置",
"manage:providers": "管理供应商",
"manage:admins": "管理管理员(仅super_admin)",
# 审批权限
"approve:applications": "审批资源申请",
}
# 角色权限映射
ROLE_PERMISSIONS = {
# 租户用户 - 仅查看自己的数据
"user": [
"view:overview",
"view:billing",
],
# 渠道管理员 - 管理自己渠道下的租户,可创建该渠道的计费管理员、运维管理员和租户
"channel_admin": [
"view:overview",
"view:tenants",
"view:resources",
"view:agents",
"view:billing",
"view:monitoring",
"view:applications", # 可查看和发起申请
"view:admins", # 可查看该渠道下的管理员
"manage:tenants", # 可管理租户
"manage:resources",
"manage:agents",
"manage:billing",
"manage:admins", # 可创建该渠道下的计费管理员和运维管理员
],
# 计费管理员 - 渠道下的计费管理员,完整写入权限(管理该渠道下的租户、计费操作)
"billing_admin": [
"view:overview",
"view:tenants", # 仅查看自己渠道下的租户
"view:resources", # 仅查看自己渠道的资源
"view:agents",
"view:billing", # 仅查看自己渠道的计费
"view:monitoring",
"view:applications", # 仅查看自己渠道的申请
"manage:tenants", # 可管理自己渠道下的租户
"manage:resources", # 可管理自己渠道的资源分配
"manage:agents", # 可管理Agent配置
"manage:billing", # 可执行计费操作(充值等)
"approve:applications", # 可审批自己渠道的申请
],
# 运维管理员 - 渠道下的运维管理员,只读权限(仅查看和监控该渠道的数据)
"operations_admin": [
"view:overview",
"view:tenants", # 仅查看自己渠道下的租户
"view:resources", # 仅查看自己渠道的资源
"view:agents",
"view:billing", # 仅查看自己渠道的计费
"view:monitoring",
"view:applications", # 仅查看自己渠道的申请
# 无任何 manage: 权限,只能查看
],
# 超级管理员 - 全部权限
"super_admin": list(PERMISSIONS.keys()),
# 供应商管理员
"provider_admin": [
"view:overview",
"view:resources",
"manage:providers",
],
}
# 角色层级(用于判断角色大小)
ROLE_HIERARCHY = {
"super_admin": 100,
"billing_admin": 80,
"operations_admin": 70,
"channel_admin": 50,
"provider_admin": 40,
"user": 10,
}
def get_role_level(role: str) -> int:
"""获取角色层级"""
return ROLE_HIERARCHY.get(role, 0)
def get_role_permissions(role: str) -> List[str]:
"""
获取角色的权限列表
Args:
role: 角色名称
Returns:
权限列表
"""
return ROLE_PERMISSIONS.get(role, [])
def has_permission(role: str, permission: str) -> bool:
"""
检查角色是否拥有某个权限
Args:
role: 角色名称
permission: 权限名称
Returns:
是否拥有权限
"""
return permission in ROLE_PERMISSIONS.get(role, [])
def has_any_permission(role: str, permissions: List[str]) -> bool:
"""
检查角色是否拥有任意一个权限
Args:
role: 角色名称
permissions: 权限列表
Returns:
是否拥有任意一个权限
"""
role_perms = set(ROLE_PERMISSIONS.get(role, []))
return bool(role_perms.intersection(set(permissions)))
def has_all_permissions(role: str, permissions: List[str]) -> bool:
"""
检查角色是否拥有所有权限
Args:
role: 角色名称
permissions: 权限列表
Returns:
是否拥有所有权限
"""
role_perms = set(ROLE_PERMISSIONS.get(role, []))
return set(permissions).issubset(role_perms)
def require_permission(required_permission: str):
"""
权限装饰器(用于FastAPI路由)
Args:
required_permission: 需要的权限
Returns:
装饰器函数
"""
def decorator(func):
async def wrapper(*args, **kwargs):
# 从kwargs中获取principal
principal = kwargs.get("principal", {})
role = principal.get("claims", {}).get("role", "")
if not has_permission(role, required_permission):
from fastapi import HTTPException, status
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"需要权限: {required_permission}"
)
return await func(*args, **kwargs)
return wrapper
return decorator