236 lines
7.3 KiB
Python
236 lines
7.3 KiB
Python
"""内部公文权限控制测试。"""
|
|
|
|
import pytest
|
|
from starlette.responses import JSONResponse
|
|
|
|
from fastapi_modules.fastapi_leaudit.controllers.govdocController import GovdocController
|
|
from fastapi_modules.fastapi_leaudit.domian.vo.rbacVo import RbacRouteVO
|
|
from fastapi_modules.fastapi_leaudit.services.impl.rbacServiceImpl import RbacServiceImpl
|
|
|
|
|
|
class _DenyPermissionService:
|
|
"""拒绝所有权限的测试权限服务。"""
|
|
|
|
async def CheckPermission(self, user_id: int, permission_key: str) -> bool:
|
|
"""检查权限。"""
|
|
return False
|
|
|
|
|
|
class _AllowPermissionService:
|
|
"""允许所有权限的测试权限服务。"""
|
|
|
|
async def CheckPermission(self, user_id: int, permission_key: str) -> bool:
|
|
"""检查权限。"""
|
|
return True
|
|
|
|
|
|
class _FakeGovdocService:
|
|
"""记录调用的测试公文服务。"""
|
|
|
|
def __init__(self) -> None:
|
|
self.list_called = False
|
|
self.upload_called = False
|
|
|
|
async def ListDocuments(self, **kwargs):
|
|
"""记录列表调用。"""
|
|
self.list_called = True
|
|
return {"items": [], "total": 0, "page": kwargs["page"], "pageSize": kwargs["pageSize"]}
|
|
|
|
async def UploadDocument(self, **kwargs):
|
|
"""记录上传调用。"""
|
|
self.upload_called = True
|
|
return {"documentId": 1}
|
|
|
|
|
|
def _find_endpoint(controller: GovdocController, path: str, method: str):
|
|
"""根据路径和方法查找路由 endpoint。"""
|
|
full_path = f"{controller.router.prefix}{path}"
|
|
for route in controller.router.routes:
|
|
if getattr(route, "path", "") == full_path and method in getattr(route, "methods", set()):
|
|
return route.endpoint
|
|
raise AssertionError(f"未找到路由 {method} {full_path}")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_govdoc_list_requires_document_read_permission():
|
|
"""公文列表无查看权限时返回 403,且不调用业务服务。"""
|
|
controller = GovdocController()
|
|
service = _FakeGovdocService()
|
|
controller.GovdocService = service
|
|
controller.PermissionService = _DenyPermissionService()
|
|
endpoint = _find_endpoint(controller, "/documents", "GET")
|
|
|
|
response = await endpoint(
|
|
page=1,
|
|
pageSize=20,
|
|
keyword=None,
|
|
fileExt=None,
|
|
region=None,
|
|
tenant_code=None,
|
|
entry_module_id=None,
|
|
type_ids=None,
|
|
document_type_id=None,
|
|
status=None,
|
|
resultStatus=None,
|
|
createdBy=None,
|
|
dateFrom=None,
|
|
dateTo=None,
|
|
payload={"user_id": 7},
|
|
)
|
|
|
|
assert isinstance(response, JSONResponse)
|
|
assert response.status_code == 403
|
|
assert service.list_called is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_govdoc_upload_requires_document_create_permission():
|
|
"""公文上传无创建权限时返回 403,且不调用业务服务。"""
|
|
controller = GovdocController()
|
|
service = _FakeGovdocService()
|
|
controller.GovdocService = service
|
|
controller.PermissionService = _DenyPermissionService()
|
|
endpoint = _find_endpoint(controller, "/documents", "POST")
|
|
|
|
response = await endpoint(file=object(), payload={"user_id": 7})
|
|
|
|
assert isinstance(response, JSONResponse)
|
|
assert response.status_code == 403
|
|
assert service.upload_called is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_govdoc_list_calls_service_when_permission_granted():
|
|
"""公文列表有查看权限时正常调用业务服务。"""
|
|
controller = GovdocController()
|
|
service = _FakeGovdocService()
|
|
controller.GovdocService = service
|
|
controller.PermissionService = _AllowPermissionService()
|
|
endpoint = _find_endpoint(controller, "/documents", "GET")
|
|
|
|
response = await endpoint(
|
|
page=1,
|
|
pageSize=20,
|
|
keyword=None,
|
|
fileExt=None,
|
|
region=None,
|
|
tenant_code=None,
|
|
entry_module_id=None,
|
|
type_ids=None,
|
|
document_type_id=None,
|
|
status=None,
|
|
resultStatus=None,
|
|
createdBy=None,
|
|
dateFrom=None,
|
|
dateTo=None,
|
|
payload={"user_id": 7},
|
|
)
|
|
|
|
assert response.data["total"] == 0
|
|
assert service.list_called is True
|
|
|
|
|
|
def test_govdoc_root_route_marks_frontend_route_set_ready():
|
|
"""只有内部公文模块路由时也视为新版路由,避免兼容菜单补出列表和上传。"""
|
|
service = RbacServiceImpl()
|
|
routes = [
|
|
RbacRouteVO(
|
|
id=1,
|
|
route_path="/govdoc",
|
|
route_name="govdoc",
|
|
component="govdoc",
|
|
parent_id=None,
|
|
route_title="内部公文处理",
|
|
)
|
|
]
|
|
|
|
assert service._isFrontendRouteSetReady(routes) is True
|
|
|
|
|
|
def test_govdoc_parent_route_does_not_expose_ungranted_child_routes():
|
|
"""只有内部公文父路由和接口权限时,不应补出未勾选的列表/上传子路由。"""
|
|
service = RbacServiceImpl()
|
|
routes = [
|
|
RbacRouteVO(
|
|
id=1,
|
|
route_path="/govdoc",
|
|
route_name="govdoc",
|
|
component="govdoc",
|
|
parent_id=None,
|
|
route_title="内部公文处理",
|
|
children=[
|
|
RbacRouteVO(
|
|
id=2,
|
|
route_path="/govdoc/audits",
|
|
route_name="govdoc-audits",
|
|
component="govdoc.audits",
|
|
parent_id=1,
|
|
route_title="公文列表",
|
|
),
|
|
RbacRouteVO(
|
|
id=3,
|
|
route_path="/govdoc/upload",
|
|
route_name="govdoc-upload",
|
|
component="govdoc.upload",
|
|
parent_id=1,
|
|
route_title="公文上传",
|
|
),
|
|
],
|
|
)
|
|
]
|
|
|
|
filtered = service._filterRoutesByRouteAndPermissionScope(
|
|
routes,
|
|
{"/govdoc"},
|
|
{"govdoc:document:read", "govdoc:document:create"},
|
|
)
|
|
paths = service._collectRoutePaths(filtered)
|
|
|
|
assert "/govdoc" in paths
|
|
assert "/govdoc/audits" not in paths
|
|
assert "/govdoc/upload" not in paths
|
|
|
|
|
|
def test_legacy_govdoc_audit_route_does_not_grant_current_govdoc_child_route():
|
|
"""旧 /govdoc-audit 残留授权不应继续放行当前 /govdoc 子路由。"""
|
|
service = RbacServiceImpl()
|
|
routes = [
|
|
RbacRouteVO(
|
|
id=1,
|
|
route_path="/govdoc",
|
|
route_name="govdoc",
|
|
component="govdoc",
|
|
parent_id=None,
|
|
route_title="内部公文处理",
|
|
),
|
|
RbacRouteVO(
|
|
id=2,
|
|
route_path="/govdoc-audit/audits",
|
|
route_name="legacy-govdoc-audits",
|
|
component="govdoc-audit.audits",
|
|
parent_id=None,
|
|
route_title="旧公文列表",
|
|
),
|
|
RbacRouteVO(
|
|
id=3,
|
|
route_path="/govdoc-audit/upload",
|
|
route_name="legacy-govdoc-upload",
|
|
component="govdoc-audit.upload",
|
|
parent_id=None,
|
|
route_title="旧公文上传",
|
|
),
|
|
]
|
|
|
|
filtered = service._filterRoutesByRouteAndPermissionScope(
|
|
routes,
|
|
service._collectCurrentFrontendRoutePaths(routes),
|
|
{"govdoc:document:read", "govdoc:document:create"},
|
|
)
|
|
paths = service._collectRoutePaths(filtered)
|
|
|
|
assert "/govdoc" in paths
|
|
assert "/govdoc-audit/audits" not in paths
|
|
assert "/govdoc-audit/upload" not in paths
|
|
assert "/govdoc/audits" not in paths
|
|
assert "/govdoc/upload" not in paths
|