Files

300 lines
9.8 KiB
Python

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