300 lines
9.8 KiB
Python
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
|