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