feat: restore source parity and harden agent runtime
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.base_schema import ResponseModel
|
||||
from zq_smart_table.permission.schema import (
|
||||
SmartTableRoleCreate, SmartTableRoleUpdate, SmartTableRoleResponse,
|
||||
CollaboratorCreate, CollaboratorUpdate, CollaboratorResponse,
|
||||
FieldPermBatchUpdate, FieldPermMatrix, FieldPermItem,
|
||||
RowRuleUpdate, RowRuleResponse,
|
||||
MyPermissionResponse,
|
||||
)
|
||||
from zq_smart_table.permission.service import PermissionService
|
||||
from zq_smart_table.permission.model import SmartTableRole
|
||||
|
||||
router = APIRouter(tags=["多维表格-权限"])
|
||||
|
||||
|
||||
# ==================== My Permission ====================
|
||||
|
||||
@router.get(
|
||||
"/tables/{table_id}/my-permission",
|
||||
response_model=MyPermissionResponse,
|
||||
summary="获取当前用户对该表的有效权限",
|
||||
)
|
||||
async def get_my_permission(table_id: str, db: AsyncSession = Depends(get_db)):
|
||||
perm = await PermissionService.get_my_permission(db, table_id)
|
||||
return MyPermissionResponse(**perm)
|
||||
|
||||
|
||||
# ==================== Role ====================
|
||||
|
||||
@router.get(
|
||||
"/tables/{table_id}/roles",
|
||||
response_model=List[SmartTableRoleResponse],
|
||||
summary="获取表角色列表",
|
||||
)
|
||||
async def get_roles(table_id: str, db: AsyncSession = Depends(get_db)):
|
||||
await PermissionService.ensure_system_roles(db, table_id)
|
||||
roles = await PermissionService.get_roles(db, table_id)
|
||||
return roles
|
||||
|
||||
|
||||
@router.post(
|
||||
"/tables/{table_id}/roles",
|
||||
response_model=SmartTableRoleResponse,
|
||||
summary="创建自定义角色",
|
||||
)
|
||||
async def create_role(
|
||||
table_id: str,
|
||||
data: SmartTableRoleCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
role = await PermissionService.create_custom_role(
|
||||
db, table_id, data.name, data.capabilities
|
||||
)
|
||||
return role
|
||||
|
||||
|
||||
@router.put(
|
||||
"/tables/{table_id}/roles/{role_id}",
|
||||
response_model=SmartTableRoleResponse,
|
||||
summary="更新角色",
|
||||
)
|
||||
async def update_role(
|
||||
table_id: str, role_id: str,
|
||||
data: SmartTableRoleUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
role = await PermissionService.update_role(
|
||||
db, role_id, name=data.name, capabilities=data.capabilities
|
||||
)
|
||||
if not role:
|
||||
raise HTTPException(status_code=404, detail="角色不存在")
|
||||
return role
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/tables/{table_id}/roles/{role_id}",
|
||||
response_model=ResponseModel,
|
||||
summary="删除自定义角色",
|
||||
)
|
||||
async def delete_role(
|
||||
table_id: str, role_id: str,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
success = await PermissionService.delete_role(db, role_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="角色不存在或为系统预置角色")
|
||||
return ResponseModel(message="删除成功")
|
||||
|
||||
|
||||
# ==================== Collaborator ====================
|
||||
|
||||
@router.get(
|
||||
"/tables/{table_id}/collaborators",
|
||||
response_model=List[CollaboratorResponse],
|
||||
summary="获取协作者列表",
|
||||
)
|
||||
async def get_collaborators(table_id: str, db: AsyncSession = Depends(get_db)):
|
||||
await PermissionService.require_table_access(db, table_id)
|
||||
collabs = await PermissionService.get_collaborators(db, table_id)
|
||||
|
||||
role_cache: dict = {}
|
||||
results = []
|
||||
for c in collabs:
|
||||
if c.role_id not in role_cache:
|
||||
from sqlalchemy import select
|
||||
r = await db.execute(
|
||||
select(SmartTableRole).where(SmartTableRole.id == c.role_id)
|
||||
)
|
||||
role_cache[c.role_id] = r.scalar_one_or_none()
|
||||
|
||||
role = role_cache.get(c.role_id)
|
||||
subject_name = None
|
||||
subject_avatar = None
|
||||
|
||||
if c.subject_type == "user":
|
||||
from core.user.model import User
|
||||
from sqlalchemy import select as sel
|
||||
u = await db.execute(sel(User).where(User.id == c.subject_id))
|
||||
user = u.scalar_one_or_none()
|
||||
if user:
|
||||
subject_name = user.name or user.username
|
||||
subject_avatar = user.avatar
|
||||
elif c.subject_type == "dept":
|
||||
from core.dept.model import Dept
|
||||
from sqlalchemy import select as sel2
|
||||
d = await db.execute(sel2(Dept).where(Dept.id == c.subject_id))
|
||||
dept = d.scalar_one_or_none()
|
||||
if dept:
|
||||
subject_name = dept.name
|
||||
|
||||
results.append(CollaboratorResponse(
|
||||
id=c.id,
|
||||
table_id=c.table_id,
|
||||
subject_type=c.subject_type,
|
||||
subject_id=c.subject_id,
|
||||
role_id=c.role_id,
|
||||
role_name=role.name if role else None,
|
||||
role_type=role.role_type if role else None,
|
||||
subject_name=subject_name,
|
||||
subject_avatar=subject_avatar,
|
||||
sys_create_datetime=c.sys_create_datetime,
|
||||
))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
@router.post(
|
||||
"/tables/{table_id}/collaborators",
|
||||
response_model=CollaboratorResponse,
|
||||
summary="添加协作者",
|
||||
)
|
||||
async def add_collaborator(
|
||||
table_id: str,
|
||||
data: CollaboratorCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
collab = await PermissionService.add_collaborator(
|
||||
db, table_id, data.subject_type, data.subject_id, data.role_id,
|
||||
)
|
||||
return CollaboratorResponse(
|
||||
id=collab.id,
|
||||
table_id=collab.table_id,
|
||||
subject_type=collab.subject_type,
|
||||
subject_id=collab.subject_id,
|
||||
role_id=collab.role_id,
|
||||
sys_create_datetime=collab.sys_create_datetime,
|
||||
)
|
||||
|
||||
|
||||
@router.put(
|
||||
"/tables/{table_id}/collaborators/{collab_id}",
|
||||
response_model=CollaboratorResponse,
|
||||
summary="更新协作者角色",
|
||||
)
|
||||
async def update_collaborator(
|
||||
table_id: str, collab_id: str,
|
||||
data: CollaboratorUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
collab = await PermissionService.update_collaborator_role(db, collab_id, data.role_id)
|
||||
if not collab:
|
||||
raise HTTPException(status_code=404, detail="协作者不存在")
|
||||
return CollaboratorResponse(
|
||||
id=collab.id,
|
||||
table_id=collab.table_id,
|
||||
subject_type=collab.subject_type,
|
||||
subject_id=collab.subject_id,
|
||||
role_id=collab.role_id,
|
||||
sys_create_datetime=collab.sys_create_datetime,
|
||||
)
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/tables/{table_id}/collaborators/{collab_id}",
|
||||
response_model=ResponseModel,
|
||||
summary="移除协作者",
|
||||
)
|
||||
async def remove_collaborator(
|
||||
table_id: str, collab_id: str,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
success = await PermissionService.remove_collaborator(db, collab_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="协作者不存在")
|
||||
return ResponseModel(message="移除成功")
|
||||
|
||||
|
||||
# ==================== Field Permission ====================
|
||||
|
||||
@router.get(
|
||||
"/tables/{table_id}/field-permissions",
|
||||
response_model=List[FieldPermMatrix],
|
||||
summary="获取列权限矩阵",
|
||||
)
|
||||
async def get_field_permissions(table_id: str, db: AsyncSession = Depends(get_db)):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
await PermissionService.require_multidimensional_table(db, table_id)
|
||||
roles = await PermissionService.get_roles(db, table_id)
|
||||
|
||||
result = []
|
||||
for role in roles:
|
||||
perms = await PermissionService.get_field_permissions(db, table_id, role.id)
|
||||
fields = [FieldPermItem(field_id=fid, access=acc) for fid, acc in perms.items()]
|
||||
result.append(FieldPermMatrix(
|
||||
role_id=role.id,
|
||||
role_name=role.name,
|
||||
role_type=role.role_type,
|
||||
fields=fields,
|
||||
))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@router.put(
|
||||
"/tables/{table_id}/field-permissions",
|
||||
response_model=ResponseModel,
|
||||
summary="批量更新列权限",
|
||||
)
|
||||
async def update_field_permissions(
|
||||
table_id: str,
|
||||
data: FieldPermBatchUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
await PermissionService.require_multidimensional_table(db, table_id)
|
||||
permissions = [{"field_id": p.field_id, "access": p.access} for p in data.permissions]
|
||||
await PermissionService.batch_set_field_permissions(db, table_id, data.role_id, permissions)
|
||||
return ResponseModel(message="更新成功")
|
||||
|
||||
|
||||
# ==================== Row Rule ====================
|
||||
|
||||
@router.get(
|
||||
"/tables/{table_id}/row-rules",
|
||||
response_model=List[RowRuleResponse],
|
||||
summary="获取行权限规则",
|
||||
)
|
||||
async def get_row_rules(table_id: str, db: AsyncSession = Depends(get_db)):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
await PermissionService.require_multidimensional_table(db, table_id)
|
||||
|
||||
from sqlalchemy import select
|
||||
from zq_smart_table.permission.model import SmartTableRowRule
|
||||
result = await db.execute(
|
||||
select(SmartTableRowRule).where(
|
||||
SmartTableRowRule.table_id == table_id,
|
||||
SmartTableRowRule.is_deleted == False, # noqa: E712
|
||||
)
|
||||
)
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
@router.put(
|
||||
"/tables/{table_id}/row-rules",
|
||||
response_model=RowRuleResponse,
|
||||
summary="更新行权限规则",
|
||||
)
|
||||
async def update_row_rule(
|
||||
table_id: str,
|
||||
data: RowRuleUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await PermissionService.require_capability(db, table_id, "manage_permission")
|
||||
await PermissionService.require_multidimensional_table(db, table_id)
|
||||
rule = await PermissionService.upsert_row_rule(
|
||||
db, table_id, data.role_id, data.rule_type, data.mode, data.conditions,
|
||||
)
|
||||
return rule
|
||||
Reference in New Issue
Block a user