feat: add tenant-scoped rule and permission management
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
"""规则管理控制器。"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import Depends
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from fastapi_common.fastapi_common_security.security import verify_access_token
|
||||
from fastapi_common.fastapi_common_web.controller import BaseController
|
||||
from fastapi_common.fastapi_common_web.domain.responses import Result
|
||||
|
||||
@@ -18,7 +24,9 @@ from fastapi_modules.fastapi_leaudit.domian.vo.ruleVo import (
|
||||
RuleVersionVO,
|
||||
)
|
||||
from fastapi_modules.fastapi_leaudit.services import IRuleService
|
||||
from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl
|
||||
from fastapi_modules.fastapi_leaudit.services.impl.ruleServiceImpl import GetRuleServiceSingleton
|
||||
from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService
|
||||
|
||||
|
||||
class RuleController(BaseController):
|
||||
@@ -27,28 +35,50 @@ class RuleController(BaseController):
|
||||
def __init__(self):
|
||||
super().__init__(prefix="/rule-sets", tags=["规则管理"])
|
||||
self.RuleService: IRuleService = GetRuleServiceSingleton()
|
||||
self.PermissionService: IPermissionService = PermissionServiceImpl()
|
||||
self._PERMISSIONS = {
|
||||
"list": "rules:list:read",
|
||||
"version_list": "rules:version_list:read",
|
||||
"content": "rules:content:read",
|
||||
"validate": "rules:validate:execute",
|
||||
"create": "rules:version_create:write",
|
||||
"publish": "rules:publish:write",
|
||||
"rollback": "rules:rollback:write",
|
||||
"binding_read": "rules:binding_list:read",
|
||||
"binding_create": "rules:binding_create:write",
|
||||
"binding_update": "rules:binding_update:write",
|
||||
"binding_delete": "rules:binding_delete:delete",
|
||||
}
|
||||
|
||||
@self.router.get("", response_model=Result[list[RuleSetVO]])
|
||||
async def ListRuleSets():
|
||||
async def ListRuleSets(payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""列出规则集。"""
|
||||
Data = await self.RuleService.ListSets()
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["list"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则集查看权限", "data": None})
|
||||
Data = await self.RuleService.ListSets(CurrentUserId=int(payload["user_id"]))
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.get("/{RuleType}/versions", response_model=Result[list[RuleVersionVO]])
|
||||
async def GetVersions(RuleType: str):
|
||||
async def GetVersions(RuleType: str, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""列出规则集的所有版本。"""
|
||||
Data = await self.RuleService.GetVersions(RuleType=RuleType)
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["version_list"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则版本查看权限", "data": None})
|
||||
Data = await self.RuleService.GetVersions(RuleType=RuleType, CurrentUserId=int(payload["user_id"]))
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.get("/versions/{VersionId}/content", response_model=Result[RuleContentVO])
|
||||
async def GetVersionContent(VersionId: int):
|
||||
async def GetVersionContent(VersionId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""获取规则版本正文。"""
|
||||
Data = await self.RuleService.GetContent(VersionId=VersionId)
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["content"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则正文查看权限", "data": None})
|
||||
Data = await self.RuleService.GetContent(VersionId=VersionId, CurrentUserId=int(payload["user_id"]))
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.post("/{RuleType}/validate", response_model=Result[RuleValidationVO])
|
||||
async def ValidateRuleYaml(RuleType: str, body: RuleValidateDTO):
|
||||
async def ValidateRuleYaml(RuleType: str, body: RuleValidateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""校验规则 YAML。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["validate"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则校验权限", "data": None})
|
||||
Data = await self.RuleService.Validate(
|
||||
RuleType=RuleType,
|
||||
YamlText=body.yamlText,
|
||||
@@ -56,47 +86,68 @@ class RuleController(BaseController):
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.post("/{RuleType}/versions", response_model=Result[RuleVersionVO])
|
||||
async def CreateRuleVersion(RuleType: str, body: RuleVersionCreateDTO):
|
||||
async def CreateRuleVersion(RuleType: str, body: RuleVersionCreateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""创建规则版本。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["create"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建规则版本权限", "data": None})
|
||||
Data = await self.RuleService.CreateVersion(
|
||||
RuleType=RuleType,
|
||||
YamlText=body.yamlText,
|
||||
ChangeNote=body.changeNote,
|
||||
EditorUserId=body.editorUserId,
|
||||
EditorUserId=int(payload["user_id"]),
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
)
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.post("/{RuleType}/publish", response_model=Result[RuleVersionVO])
|
||||
async def PublishRuleVersion(RuleType: str, body: RulePublishDTO):
|
||||
async def PublishRuleVersion(RuleType: str, body: RulePublishDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""发布规则版本。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["publish"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有发布规则权限", "data": None})
|
||||
Data = await self.RuleService.Publish(
|
||||
RuleType=RuleType,
|
||||
VersionId=body.versionId,
|
||||
OperatorUserId=body.operatorUserId,
|
||||
OperatorUserId=int(payload["user_id"]),
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
)
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.post("/{RuleType}/rollback", response_model=Result[RuleVersionVO])
|
||||
async def RollbackRuleVersion(RuleType: str, body: RulePublishDTO):
|
||||
async def RollbackRuleVersion(RuleType: str, body: RulePublishDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""回滚到指定规则版本。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["rollback"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有回滚规则权限", "data": None})
|
||||
Data = await self.RuleService.Rollback(
|
||||
RuleType=RuleType,
|
||||
VersionId=body.versionId,
|
||||
OperatorUserId=body.operatorUserId,
|
||||
OperatorUserId=int(payload["user_id"]),
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
)
|
||||
return Result.success(data=Data)
|
||||
|
||||
# ── 规则类型绑定 ──────────────────────────────────────────
|
||||
|
||||
@self.router.get("/bindings", response_model=Result[list[RuleBindingVO]])
|
||||
async def ListBindings(ruleType: str | None = None, region: str | None = None):
|
||||
"""列出规则类型绑定。可按规则类型/地区过滤。"""
|
||||
Data = await self.RuleService.ListBindings(RuleType=ruleType, Region=region)
|
||||
async def ListBindings(
|
||||
ruleType: str | None = None,
|
||||
region: str | None = None,
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""列出规则类型绑定。当前主要按规则类型过滤,region 仅兼容保留。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["binding_read"], self._PERMISSIONS["list"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则绑定查看权限", "data": None})
|
||||
Data = await self.RuleService.ListBindings(
|
||||
RuleType=ruleType,
|
||||
Region=region,
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
)
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.post("/{RuleType}/bindings", response_model=Result[RuleBindingVO])
|
||||
async def CreateBinding(RuleType: str, body: RuleBindingCreateDTO):
|
||||
async def CreateBinding(RuleType: str, body: RuleBindingCreateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""创建规则类型绑定。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["binding_create"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建规则绑定权限", "data": None})
|
||||
Data = await self.RuleService.CreateBinding(
|
||||
DocTypeId=body.docTypeId,
|
||||
RuleSetId=body.ruleSetId,
|
||||
@@ -105,23 +156,32 @@ class RuleController(BaseController):
|
||||
Priority=body.priority,
|
||||
DocTypeCode=body.docTypeCode,
|
||||
Note=body.note,
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
)
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.put("/bindings/{BindingId}", response_model=Result[RuleBindingVO])
|
||||
async def UpdateBinding(BindingId: int, body: RuleBindingUpdateDTO):
|
||||
async def UpdateBinding(BindingId: int, body: RuleBindingUpdateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""更新规则类型绑定。"""
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["binding_update"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新规则绑定权限", "data": None})
|
||||
Data = await self.RuleService.UpdateBinding(
|
||||
BindingId=BindingId,
|
||||
IsActive=body.isActive,
|
||||
Priority=body.priority,
|
||||
BindingMode=body.bindingMode,
|
||||
Note=body.note,
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
)
|
||||
return Result.success(data=Data)
|
||||
|
||||
@self.router.delete("/bindings/{BindingId}", response_model=Result[None])
|
||||
async def DeleteBinding(BindingId: int):
|
||||
async def DeleteBinding(BindingId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""删除规则类型绑定。"""
|
||||
await self.RuleService.DeleteBinding(BindingId=BindingId)
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["binding_delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除规则绑定权限", "data": None})
|
||||
await self.RuleService.DeleteBinding(BindingId=BindingId, CurrentUserId=int(payload["user_id"]))
|
||||
return Result.success()
|
||||
|
||||
async def _check_permission(self, user_id: int, permission_keys: list[str]) -> bool:
|
||||
return await self.PermissionService.HasAnyPermission(UserId=user_id, PermissionKeys=permission_keys)
|
||||
|
||||
Reference in New Issue
Block a user