feat: add tenant-scoped rule and permission management
This commit is contained in:
@@ -40,7 +40,8 @@ class ContractTemplateController(BaseController):
|
||||
keyword: str | None = Query(None, description="关键词"),
|
||||
category_id: int | None = Query(None, description="分类ID"),
|
||||
category_name: str | None = Query(None, description="分类名称"),
|
||||
region: str | None = Query(None, description="地区"),
|
||||
region: str | None = Query(None, description="兼容保留字段:租户展示值/旧地区"),
|
||||
tenant_code: str | None = Query(None, description="租户编码"),
|
||||
file_format: str | None = Query(None, description="文件格式"),
|
||||
is_featured: bool | None = Query(None, description="是否推荐"),
|
||||
page: int = Query(1, ge=1, description="页码"),
|
||||
@@ -56,6 +57,7 @@ class ContractTemplateController(BaseController):
|
||||
category_id=category_id,
|
||||
category_name=category_name,
|
||||
region=region,
|
||||
tenant_code=tenant_code,
|
||||
file_format=file_format,
|
||||
is_featured=is_featured,
|
||||
page=page,
|
||||
@@ -72,6 +74,7 @@ class ContractTemplateController(BaseController):
|
||||
template_code: str = Form(...),
|
||||
category_id: int = Form(...),
|
||||
region: str | None = Form(default=None),
|
||||
tenant_code: str | None = Form(default=None),
|
||||
description: str | None = Form(default=None),
|
||||
is_featured: bool = Form(default=False),
|
||||
file: UploadFile = File(...),
|
||||
@@ -79,12 +82,13 @@ class ContractTemplateController(BaseController):
|
||||
payload: dict = Depends(verify_access_token),
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["contract_template:create:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前仅允许地区管理员上传合同模板", "data": None})
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前仅允许租户管理员上传合同模板", "data": None})
|
||||
body = ContractTemplateCreateDTO(
|
||||
title=title,
|
||||
template_code=template_code,
|
||||
category_id=category_id,
|
||||
region=region,
|
||||
tenant_code=tenant_code,
|
||||
description=description,
|
||||
is_featured=is_featured,
|
||||
)
|
||||
@@ -96,7 +100,8 @@ class ContractTemplateController(BaseController):
|
||||
q: str = Query(..., min_length=1, description="搜索关键词"),
|
||||
category_id: int | None = Query(None, description="分类ID"),
|
||||
category_name: str | None = Query(None, description="分类名称"),
|
||||
region: str | None = Query(None, description="地区"),
|
||||
region: str | None = Query(None, description="兼容保留字段:租户展示值/旧地区"),
|
||||
tenant_code: str | None = Query(None, description="租户编码"),
|
||||
page: int = Query(1, ge=1, description="页码"),
|
||||
page_size: int = Query(12, ge=1, le=200, description="分页大小"),
|
||||
sort_by: str = Query("updated_at", description="排序字段"),
|
||||
@@ -110,6 +115,7 @@ class ContractTemplateController(BaseController):
|
||||
category_id=category_id,
|
||||
category_name=category_name,
|
||||
region=region,
|
||||
tenant_code=tenant_code,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
sort_by=sort_by,
|
||||
|
||||
@@ -51,6 +51,13 @@ class ReviewPointAuditDTO(BaseModel):
|
||||
class DocumentController(BaseController):
|
||||
"""文档控制器。"""
|
||||
|
||||
@staticmethod
|
||||
def _tenant_context(payload: dict[str, Any]) -> dict[str, str | None]:
|
||||
return {
|
||||
"TenantCode": payload.get("tenant_code"),
|
||||
"TenantName": payload.get("tenant_name"),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(prefix="", tags=["文档"])
|
||||
self.DocumentService: IDocumentService = DocumentServiceImpl()
|
||||
@@ -62,7 +69,8 @@ class DocumentController(BaseController):
|
||||
typeId: int | None = Form(None, description="文档类型ID"),
|
||||
typeCode: str | None = Form(None, description="文档类型编码"),
|
||||
groupId: int | None = Form(None, description="二级分组ID"),
|
||||
region: str = Form("default", description="所属地区"),
|
||||
region: str | None = Form(None, description="所属租户/地区"),
|
||||
tenant_code: str | None = Form(None, description="租户编码"),
|
||||
fileRole: str = Form("primary", description="文件角色"),
|
||||
createdBy: int | None = Form(None, description="上传用户ID"),
|
||||
autoRun: bool = Form(False, description="是否上传后自动触发评查"),
|
||||
@@ -81,6 +89,7 @@ class DocumentController(BaseController):
|
||||
attachment.content_type,
|
||||
)
|
||||
)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
Data = await self.DocumentService.Upload(
|
||||
FileName=file.filename or "upload.bin",
|
||||
FileContent=Content,
|
||||
@@ -91,6 +100,8 @@ class DocumentController(BaseController):
|
||||
Region=region,
|
||||
FileRole=fileRole,
|
||||
CreatedBy=int(payload["user_id"]),
|
||||
TenantCode=tenant_code or tenant_context.get("TenantCode"),
|
||||
TenantName=tenant_context.get("TenantName"),
|
||||
Attachments=attachmentPayloads,
|
||||
AutoRun=autoRun,
|
||||
Speed=speed,
|
||||
@@ -133,7 +144,8 @@ class DocumentController(BaseController):
|
||||
typeCode: str | None = None,
|
||||
type_ids: str | None = Query(None, description="逗号分隔的文档类型ID列表"),
|
||||
entry_module_id: int | None = Query(None, description="按入口模块ID过滤文档"),
|
||||
region: str | None = None,
|
||||
region: str | None = Query(None, description="兼容保留字段:租户展示值/旧地区"),
|
||||
tenant_code: str | None = Query(None, description="租户编码"),
|
||||
processingStatus: str | None = None,
|
||||
resultStatus: str | None = None,
|
||||
auditStatus: int | None = Query(None, description="按人工审核状态过滤"),
|
||||
@@ -156,6 +168,7 @@ class DocumentController(BaseController):
|
||||
TypeIds=typeIdList,
|
||||
EntryModuleId=entry_module_id,
|
||||
Region=region,
|
||||
TenantCode=tenant_code,
|
||||
ProcessingStatus=processingStatus,
|
||||
ResultStatus=resultStatus,
|
||||
AuditStatus=auditStatus,
|
||||
|
||||
@@ -23,7 +23,8 @@ class EntryModuleController(BaseController):
|
||||
@self.router.get("")
|
||||
async def GetEntryModules(
|
||||
name: str | None = Query(None, description="模块名称模糊搜索"),
|
||||
area: str | None = Query(None, description="地区筛选"),
|
||||
area: str | None = Query(None, description="历史地区筛选(兼容参数,建议改用 tenant_code)"),
|
||||
tenant_code: str | None = Query(None, description="租户编码筛选"),
|
||||
page: int = Query(1, ge=1, description="页码"),
|
||||
page_size: int = Query(10, ge=1, le=200, description="每页数量"),
|
||||
payload: dict = Depends(verify_access_token),
|
||||
@@ -31,7 +32,13 @@ class EntryModuleController(BaseController):
|
||||
"""查询入口模块列表。"""
|
||||
if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "entry_module:list:read"):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有入口模块列表权限", "data": None})
|
||||
data = await self.EntryModuleService.ListModules(Name=name, Area=area, Page=page, PageSize=page_size)
|
||||
data = await self.EntryModuleService.ListModules(
|
||||
Name=name,
|
||||
Area=area,
|
||||
TenantCode=tenant_code,
|
||||
Page=page,
|
||||
PageSize=page_size,
|
||||
)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": data.model_dump()})
|
||||
|
||||
@self.router.get("/{ModuleId}")
|
||||
|
||||
@@ -26,6 +26,15 @@ class EvaluationPointController(BaseController):
|
||||
"delete": "evaluation_point:delete:delete",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _tenant_context(payload: dict) -> dict[str, str | None]:
|
||||
return {
|
||||
"UserArea": payload.get("area"),
|
||||
"UserRole": payload.get("user_role"),
|
||||
"TenantCode": payload.get("tenant_code"),
|
||||
"TenantName": payload.get("tenant_name"),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(prefix="/v3/evaluation-points", tags=["评查点"])
|
||||
self.PointService: IEvaluationPointService = EvaluationPointServiceImpl()
|
||||
@@ -40,14 +49,22 @@ class EvaluationPointController(BaseController):
|
||||
evaluation_point_groups_pid: int | None = Query(None, description="一级分组ID"),
|
||||
evaluation_point_groups_id: int | None = Query(None, description="二级分组ID"),
|
||||
document_attribute_type: str | None = Query(None, description="文档属性类型"),
|
||||
area: str | None = Query(None, description="地区"),
|
||||
area: str | None = Query(None, description="地区/兼容租户展示值"),
|
||||
tenant_code: str | None = Query(None, description="租户编码"),
|
||||
tenant_name: str | None = Query(None, description="租户名称(兼容筛选)"),
|
||||
page: int = Query(1, ge=1, description="页码"),
|
||||
page_size: int = Query(20, ge=1, le=500, description="分页大小"),
|
||||
payload: dict = Depends(verify_access_token),
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["list"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点查看权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.PointService.ListPoints(
|
||||
int(payload["user_id"]),
|
||||
tenant_context["UserArea"],
|
||||
tenant_context["UserRole"],
|
||||
tenant_context["TenantCode"],
|
||||
tenant_context["TenantName"],
|
||||
name,
|
||||
code,
|
||||
risk,
|
||||
@@ -56,6 +73,8 @@ class EvaluationPointController(BaseController):
|
||||
evaluation_point_groups_id,
|
||||
document_attribute_type,
|
||||
area,
|
||||
tenant_code,
|
||||
tenant_name,
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
@@ -72,28 +91,61 @@ class EvaluationPointController(BaseController):
|
||||
async def GetEvaluationPoint(PointId: int, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["detail"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点查看权限", "data": None})
|
||||
data = await self.PointService.GetPoint(PointId)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.PointService.GetPoint(
|
||||
int(payload["user_id"]),
|
||||
tenant_context["UserArea"],
|
||||
tenant_context["UserRole"],
|
||||
tenant_context["TenantCode"],
|
||||
tenant_context["TenantName"],
|
||||
PointId,
|
||||
)
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.post("")
|
||||
async def CreateEvaluationPoint(body: EvaluationPointCreateDTO, payload: dict = 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.PointService.CreatePoint(body)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.PointService.CreatePoint(
|
||||
int(payload["user_id"]),
|
||||
tenant_context["UserArea"],
|
||||
tenant_context["UserRole"],
|
||||
tenant_context["TenantCode"],
|
||||
tenant_context["TenantName"],
|
||||
body,
|
||||
)
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.put("/{PointId}")
|
||||
async def UpdateEvaluationPoint(PointId: int, body: EvaluationPointUpdateDTO, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["update"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新评查点权限", "data": None})
|
||||
data = await self.PointService.UpdatePoint(PointId, body)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.PointService.UpdatePoint(
|
||||
int(payload["user_id"]),
|
||||
tenant_context["UserArea"],
|
||||
tenant_context["UserRole"],
|
||||
tenant_context["TenantCode"],
|
||||
tenant_context["TenantName"],
|
||||
PointId,
|
||||
body,
|
||||
)
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.delete("/{PointId}")
|
||||
async def DeleteEvaluationPoint(PointId: int, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除评查点权限", "data": None})
|
||||
data = await self.PointService.DeletePoint(PointId)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.PointService.DeletePoint(
|
||||
int(payload["user_id"]),
|
||||
tenant_context["UserArea"],
|
||||
tenant_context["UserRole"],
|
||||
tenant_context["TenantCode"],
|
||||
tenant_context["TenantName"],
|
||||
PointId,
|
||||
)
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
async def _check_permission(self, user_id: int, permission_keys: list[str]) -> bool:
|
||||
|
||||
@@ -41,7 +41,7 @@ class EvaluationPointGroupController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None})
|
||||
data = await self.GroupService.ListGroups(name, code, is_enabled, pid, page, page_size)
|
||||
data = await self.GroupService.ListGroups(name, code, is_enabled, pid, page, page_size, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.get("/all")
|
||||
@@ -52,7 +52,7 @@ class EvaluationPointGroupController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None})
|
||||
data = await self.GroupService.ListAllGroups(include_disabled, with_rule_count)
|
||||
data = await self.GroupService.ListAllGroups(include_disabled, with_rule_count, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=[item.model_dump() for item in data])
|
||||
|
||||
@self.router.get("/by-document-types")
|
||||
@@ -65,14 +65,19 @@ class EvaluationPointGroupController(BaseController):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None})
|
||||
document_type_id_list = [int(item.strip()) for item in document_type_ids.split(",") if item.strip().isdigit()]
|
||||
data = await self.GroupService.ListGroupsByDocumentTypes(document_type_id_list, include_disabled, with_rule_count)
|
||||
data = await self.GroupService.ListGroupsByDocumentTypes(
|
||||
document_type_id_list,
|
||||
include_disabled,
|
||||
with_rule_count,
|
||||
int(payload["user_id"]),
|
||||
)
|
||||
return JSONResponse(status_code=200, content=[item.model_dump() for item in data])
|
||||
|
||||
@self.router.post("")
|
||||
async def CreateEvaluationPointGroup(body: EvaluationPointGroupCreateDTO, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:create:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建评查点分组权限", "data": None})
|
||||
data = await self.GroupService.CreateGroup(body)
|
||||
data = await self.GroupService.CreateGroup(body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.patch("/batch/status")
|
||||
@@ -82,7 +87,7 @@ class EvaluationPointGroupController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:batch:write", "evaluation_group:update:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有批量更新评查点分组权限", "data": None})
|
||||
data = await self.GroupService.BatchUpdateStatus(body)
|
||||
data = await self.GroupService.BatchUpdateStatus(body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.delete("/batch")
|
||||
@@ -92,7 +97,7 @@ class EvaluationPointGroupController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:batch:write", "evaluation_group:delete:delete"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有批量删除评查点分组权限", "data": None})
|
||||
data = await self.GroupService.BatchDelete(body)
|
||||
data = await self.GroupService.BatchDelete(body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.get("/{GroupId}")
|
||||
@@ -103,21 +108,21 @@ class EvaluationPointGroupController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None})
|
||||
data = await self.GroupService.GetGroup(GroupId, with_rule_count)
|
||||
data = await self.GroupService.GetGroup(GroupId, with_rule_count, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.put("/{GroupId}")
|
||||
async def UpdateEvaluationPointGroup(GroupId: int, body: EvaluationPointGroupUpdateDTO, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:batch:write", "evaluation_group:update:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新评查点分组权限", "data": None})
|
||||
data = await self.GroupService.UpdateGroup(GroupId, body)
|
||||
data = await self.GroupService.UpdateGroup(GroupId, body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.delete("/{GroupId}")
|
||||
async def DeleteEvaluationPointGroup(GroupId: int, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:batch:write", "evaluation_group:delete:delete"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除评查点分组权限", "data": None})
|
||||
data = await self.GroupService.DeleteGroup(GroupId)
|
||||
data = await self.GroupService.DeleteGroup(GroupId, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.get("/{GroupId}/children")
|
||||
@@ -130,42 +135,42 @@ class EvaluationPointGroupController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有评查点分组查看权限", "data": None})
|
||||
data = await self.GroupService.GetChildren(GroupId, is_enabled, page, page_size)
|
||||
data = await self.GroupService.GetChildren(GroupId, is_enabled, page, page_size, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.put("/{GroupId}/rebind")
|
||||
async def RebindEvaluationPointGroup(GroupId: int, body: EvaluationPointGroupRebindDTO, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:update:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有换绑评查点分组权限", "data": None})
|
||||
data = await self.GroupService.RebindGroup(GroupId, body)
|
||||
data = await self.GroupService.RebindGroup(GroupId, body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.post("/{GroupId}/bindings")
|
||||
async def CreateEvaluationPointGroupBinding(GroupId: int, body: EvaluationPointGroupBindingCreateDTO, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:update:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有绑定规则集权限", "data": None})
|
||||
data = await self.GroupService.CreateBinding(GroupId, body)
|
||||
data = await self.GroupService.CreateBinding(GroupId, body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.put("/bindings/{BindingId}")
|
||||
async def UpdateEvaluationPointGroupBinding(BindingId: int, body: EvaluationPointGroupBindingUpdateDTO, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:update:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新规则集绑定权限", "data": None})
|
||||
data = await self.GroupService.UpdateBinding(BindingId, body)
|
||||
data = await self.GroupService.UpdateBinding(BindingId, body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.delete("/bindings/{BindingId}")
|
||||
async def DeleteEvaluationPointGroupBinding(BindingId: int, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:update:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除规则集绑定权限", "data": None})
|
||||
await self.GroupService.DeleteBinding(BindingId)
|
||||
await self.GroupService.DeleteBinding(BindingId, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content={"success": True})
|
||||
|
||||
@self.router.get("/{GroupId}/rule-template")
|
||||
async def GetEvaluationPointGroupRuleTemplate(GroupId: int, payload: dict = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:list:read", "rules:list:read"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看规则模板权限", "data": None})
|
||||
data = await self.GroupService.GetRuleTemplate(GroupId)
|
||||
data = await self.GroupService.GetRuleTemplate(GroupId, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
@self.router.post("/{GroupId}/rule-drafts")
|
||||
@@ -177,7 +182,7 @@ class EvaluationPointGroupController(BaseController):
|
||||
if not await self._check_permission(int(payload["user_id"]), ["evaluation_group:update:write", "rules:create:write"]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有保存规则草稿权限", "data": None})
|
||||
effective_body = body.model_copy(update={"editor_user_id": body.editor_user_id or int(payload["user_id"])})
|
||||
data = await self.GroupService.CreateRuleDraft(GroupId, effective_body)
|
||||
data = await self.GroupService.CreateRuleDraft(GroupId, effective_body, int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content=data.model_dump())
|
||||
|
||||
async def _check_permission(self, user_id: int, permission_keys: list[str]) -> bool:
|
||||
|
||||
@@ -30,7 +30,8 @@ class GovdocController(BaseController):
|
||||
async def UploadDocument(
|
||||
file: UploadFile = File(...),
|
||||
typeId: int | None = Form(default=None),
|
||||
region: str = Form(default="default"),
|
||||
region: str | None = Form(default=None, description="兼容保留字段:租户展示值/旧地区"),
|
||||
tenant_code: str | None = Form(default=None, description="租户编码"),
|
||||
autoRun: bool = Form(default=True),
|
||||
speed: str = Form(default="normal"),
|
||||
ruleVersionId: int | None = Form(default=None),
|
||||
@@ -44,6 +45,7 @@ class GovdocController(BaseController):
|
||||
file=file,
|
||||
typeId=typeId,
|
||||
region=region,
|
||||
tenantCode=tenant_code,
|
||||
autoRun=autoRun,
|
||||
speed=speed,
|
||||
ruleVersionId=ruleVersionId,
|
||||
@@ -57,7 +59,8 @@ class GovdocController(BaseController):
|
||||
pageSize: int = Query(default=20, ge=1, le=100),
|
||||
keyword: str | None = Query(default=None),
|
||||
fileExt: str | None = Query(default=None),
|
||||
region: str | None = Query(default=None),
|
||||
region: str | None = Query(default=None, description="兼容保留字段:租户展示值/旧地区"),
|
||||
tenant_code: str | None = Query(default=None, description="租户编码"),
|
||||
status: str | None = Query(default=None),
|
||||
resultStatus: str | None = Query(default=None),
|
||||
createdBy: int | None = Query(default=None),
|
||||
@@ -75,6 +78,7 @@ class GovdocController(BaseController):
|
||||
keyword=keyword,
|
||||
fileExt=fileExt,
|
||||
region=region,
|
||||
tenantCode=tenant_code,
|
||||
status=status,
|
||||
resultStatus=resultStatus,
|
||||
createdBy=createdBy,
|
||||
@@ -151,7 +155,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""查询 run 状态、阶段、耗时、错误摘要。"""
|
||||
result = await self.GovdocService.GetRunStatus(runId=runId)
|
||||
result = await self.GovdocService.GetRunStatus(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
# ── 结果与报告 ────────────────────────────────────
|
||||
@@ -162,7 +166,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取审查结果摘要:summary + checked rules + findings 统计 + entities 摘要。"""
|
||||
result = await self.GovdocService.GetRunResult(runId=runId)
|
||||
result = await self.GovdocService.GetRunResult(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/findings")
|
||||
@@ -171,7 +175,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取段落级 findings 明细列表。"""
|
||||
result = await self.GovdocService.GetRunFindings(runId=runId)
|
||||
result = await self.GovdocService.GetRunFindings(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/entities")
|
||||
@@ -180,7 +184,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取识别出的标题、文号、署名等实体。"""
|
||||
result = await self.GovdocService.GetRunEntities(runId=runId)
|
||||
result = await self.GovdocService.GetRunEntities(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/structure")
|
||||
@@ -189,7 +193,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取文档结构统计(结构面板数据)。"""
|
||||
result = await self.GovdocService.GetRunStructure(runId=runId)
|
||||
result = await self.GovdocService.GetRunStructure(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/outline")
|
||||
@@ -198,7 +202,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取文档大纲树(大纲面板数据)。"""
|
||||
result = await self.GovdocService.GetRunOutline(runId=runId)
|
||||
result = await self.GovdocService.GetRunOutline(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/paragraphs")
|
||||
@@ -207,7 +211,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取前端文档联动视图所需的段落 HTML。"""
|
||||
result = await self.GovdocService.GetRunParagraphs(runId=runId)
|
||||
result = await self.GovdocService.GetRunParagraphs(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/report/html")
|
||||
@@ -216,7 +220,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取 HTML 报告内容或下载地址。"""
|
||||
result = await self.GovdocService.GetReportHtml(runId=runId)
|
||||
result = await self.GovdocService.GetReportHtml(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/runs/{runId}/report/docx")
|
||||
@@ -225,7 +229,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取批注 DOCX 下载地址。"""
|
||||
result = await self.GovdocService.GetReportDocx(runId=runId)
|
||||
result = await self.GovdocService.GetReportDocx(runId=runId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
@self.router.get("/documents/{documentId}/original")
|
||||
@@ -234,7 +238,7 @@ class GovdocController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取原始上传文档下载地址。"""
|
||||
result = await self.GovdocService.DownloadOriginal(documentId=documentId)
|
||||
result = await self.GovdocService.DownloadOriginal(documentId=documentId, userId=int(payload["user_id"]))
|
||||
return Result.success(data=result)
|
||||
|
||||
# ── 规则 ──────────────────────────────────────────
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
"""页级图片质量控制器。"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import Depends, Form
|
||||
|
||||
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
|
||||
from fastapi_modules.fastapi_leaudit.domian.vo.pageQualityVo import (
|
||||
PageQualityDetailVO,
|
||||
PageQualityRecheckVO,
|
||||
PageQualitySummaryVO,
|
||||
)
|
||||
from fastapi_modules.fastapi_leaudit.services.impl.pageQualityServiceImpl import PageQualityServiceImpl
|
||||
from fastapi_modules.fastapi_leaudit.services.pageQualityService import IPageQualityService
|
||||
|
||||
|
||||
class PageQualityController(BaseController):
|
||||
"""页级图片质量控制器。"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(prefix="", tags=["页级图片质量"])
|
||||
self.PageQualityService: IPageQualityService = PageQualityServiceImpl()
|
||||
|
||||
@self.router.get("/documents/{DocumentId}/page-quality/summary", response_model=Result[PageQualitySummaryVO])
|
||||
async def GetDocumentPageQualitySummary(
|
||||
DocumentId: int,
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取文档页级模糊检测摘要。"""
|
||||
data = await self.PageQualityService.GetDocumentSummary(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
DocumentId=DocumentId,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.get("/documents/{DocumentId}/page-quality", response_model=Result[PageQualityDetailVO])
|
||||
async def GetDocumentPageQualityDetail(
|
||||
DocumentId: int,
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""获取文档页级模糊检测详情。"""
|
||||
data = await self.PageQualityService.GetDocumentDetail(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
DocumentId=DocumentId,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.post("/documents/{DocumentId}/page-quality/recheck", response_model=Result[PageQualityRecheckVO])
|
||||
async def RecheckDocumentPageQuality(
|
||||
DocumentId: int,
|
||||
speed: str = Form("normal", description="执行速度档位:urgent/normal"),
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
"""手工重跑页级模糊检测。"""
|
||||
data = await self.PageQualityService.RecheckDocument(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
DocumentId=DocumentId,
|
||||
Speed=speed,
|
||||
)
|
||||
return Result.success(data=data, message="页级模糊检测任务已投递")
|
||||
@@ -64,6 +64,15 @@ class RagChatController(BaseController):
|
||||
"dataset_delete": "rag:dataset:delete",
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _tenant_context(payload: dict[str, Any]) -> dict[str, str | None]:
|
||||
return {
|
||||
"UserArea": payload.get("area"),
|
||||
"UserRole": payload.get("user_role"),
|
||||
"TenantCode": payload.get("tenant_code"),
|
||||
"TenantName": payload.get("tenant_name"),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(prefix="/v3/rag", tags=["RAG 聊天"])
|
||||
self.RagChatService: IRagChatService = RagChatServiceImpl()
|
||||
@@ -74,10 +83,10 @@ class RagChatController(BaseController):
|
||||
async def GetApps(payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["app_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天应用权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.GetApps(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@@ -85,10 +94,10 @@ class RagChatController(BaseController):
|
||||
async def GetDefaultApp(payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["app_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看默认聊天应用权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.GetDefaultApp(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@@ -96,16 +105,17 @@ class RagChatController(BaseController):
|
||||
async def GetMyDatasets(payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.GetMyDatasets(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.get("/datasets/admin", response_model=Result[RagDatasetPageVO])
|
||||
async def GetAdminDatasets(
|
||||
area: str | None = Query(None),
|
||||
tenant_code: str | None = Query(None, description="租户编码,支持逗号分隔"),
|
||||
onlyEnabled: bool | None = Query(None),
|
||||
page: int = Query(1, ge=1),
|
||||
pageSize: int = Query(20, ge=1, le=200),
|
||||
@@ -113,11 +123,12 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_manage"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有管理知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.GetAdminDatasets(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
Area=area,
|
||||
TenantFilterCode=tenant_code,
|
||||
OnlyEnabled=onlyEnabled,
|
||||
Page=page,
|
||||
PageSize=pageSize,
|
||||
@@ -128,10 +139,10 @@ class RagChatController(BaseController):
|
||||
async def CreateAdminDataset(Body: dict[str, Any], payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_create"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.CreateAdminDataset(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
Body=Body,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
@@ -140,10 +151,10 @@ class RagChatController(BaseController):
|
||||
async def UpdateAdminDataset(DatasetId: int, Body: dict[str, Any], payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.UpdateAdminDataset(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
Body=Body,
|
||||
)
|
||||
@@ -153,10 +164,10 @@ class RagChatController(BaseController):
|
||||
async def DeleteAdminDataset(DatasetId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.DeleteAdminDataset(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
@@ -165,10 +176,10 @@ class RagChatController(BaseController):
|
||||
async def GetDatasetDetail(DatasetId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.GetDatasetDetail(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
@@ -177,10 +188,10 @@ class RagChatController(BaseController):
|
||||
async def UpdateDataset(DatasetId: int, Body: RagDatasetUpdateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.UpdateDataset(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
Body=Body,
|
||||
)
|
||||
@@ -196,10 +207,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库文档权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.GetDatasetDocuments(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
Page=page,
|
||||
Limit=limit,
|
||||
@@ -215,10 +226,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库文档权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagDatasetService.GetDatasetDocumentDetail(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
)
|
||||
@@ -235,10 +246,10 @@ class RagChatController(BaseController):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有上传知识库文档权限", "data": None})
|
||||
process_config = json.loads(data) if data else None
|
||||
file_bytes = await file.read()
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.UploadDatasetDocument(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
FileName=file.filename or "document",
|
||||
ContentType=file.content_type,
|
||||
@@ -259,10 +270,10 @@ class RagChatController(BaseController):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有重处理知识库文档权限", "data": None})
|
||||
process_config = json.loads(data) if data else None
|
||||
file_bytes = await file.read()
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.UpdateDatasetDocumentByFile(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
FileName=file.filename or "document",
|
||||
@@ -280,10 +291,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库处理进度权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.GetDatasetDocumentIndexingStatus(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
)
|
||||
@@ -302,10 +313,10 @@ class RagChatController(BaseController):
|
||||
if Action not in {"enable", "disable"}:
|
||||
return JSONResponse(status_code=400, content={"code": 400, "msg": "当前仅支持启用和禁用", "data": None})
|
||||
document_ids = Body.get("document_ids") or []
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.BatchUpdateDatasetDocumentStatus(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentIds=[int(item) for item in document_ids],
|
||||
Enabled=enabled,
|
||||
@@ -323,10 +334,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库分段权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.GetDatasetDocumentSegments(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
Page=page,
|
||||
@@ -343,10 +354,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库文档权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.DeleteDatasetDocument(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
)
|
||||
@@ -360,10 +371,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库文档权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.BatchDeleteDatasetDocuments(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentIds=Body.document_ids,
|
||||
)
|
||||
@@ -377,10 +388,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有检索知识库权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.RetrieveDataset(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
Query=str(Body.get("query") or ""),
|
||||
RetrievalModel=Body.get("retrieval_model") if isinstance(Body.get("retrieval_model"), dict) else None,
|
||||
@@ -396,10 +407,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库分段权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.GetDatasetDocumentSegmentDetail(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
SegmentId=SegmentId,
|
||||
@@ -416,10 +427,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改知识库分段权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.UpdateDatasetDocumentSegment(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
SegmentId=SegmentId,
|
||||
@@ -436,10 +447,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库分段权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
result = await self.RagDatasetService.DeleteDatasetDocumentSegment(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
DatasetId=DatasetId,
|
||||
DocumentId=DocumentId,
|
||||
SegmentId=SegmentId,
|
||||
@@ -453,10 +464,10 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["chat_use"], self._PERMISSIONS["app_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天配置权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.GetAppParameters(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
AppId=appId,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
@@ -465,11 +476,11 @@ class RagChatController(BaseController):
|
||||
async def SendMessage(Body: RagChatSendMessageDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["chat_use"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有使用 RAG 对话权限", "data": None})
|
||||
tenant_context = self._tenant_context(payload)
|
||||
stream = self.RagChatService.SendMessage(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
UserName=payload.get("username") or str(payload.get("user_id")),
|
||||
UserArea=payload.get("area"),
|
||||
UserRole=payload.get("user_role"),
|
||||
**tenant_context,
|
||||
Query=Body.query,
|
||||
ConversationId=Body.conversationId,
|
||||
AppId=Body.appId,
|
||||
@@ -488,7 +499,13 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["chat_use"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有停止 RAG 对话权限", "data": None})
|
||||
data = await self.RagChatService.StopMessage(int(payload["user_id"]), MessageId, Body)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.StopMessage(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
**tenant_context,
|
||||
MessageId=MessageId,
|
||||
Body=Body,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.get("/chat/conversations", response_model=Result[RagConversationPageVO])
|
||||
@@ -500,7 +517,14 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天会话权限", "data": None})
|
||||
data = await self.RagChatService.GetConversations(int(payload["user_id"]), appId, page, pageSize)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.GetConversations(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
**tenant_context,
|
||||
AppId=appId,
|
||||
Page=page,
|
||||
PageSize=pageSize,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.get("/chat/conversations/{ConversationId}/messages", response_model=Result[RagMessagePageVO])
|
||||
@@ -512,7 +536,14 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_read"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天消息权限", "data": None})
|
||||
data = await self.RagChatService.GetConversationMessages(int(payload["user_id"]), ConversationId, page, pageSize)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.GetConversationMessages(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
**tenant_context,
|
||||
ConversationId=ConversationId,
|
||||
Page=page,
|
||||
PageSize=pageSize,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.patch("/chat/conversations/{ConversationId}", response_model=Result[RagConversationRenameVO])
|
||||
@@ -523,14 +554,25 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_update"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改聊天会话权限", "data": None})
|
||||
data = await self.RagChatService.RenameConversation(int(payload["user_id"]), ConversationId, Body)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.RenameConversation(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
**tenant_context,
|
||||
ConversationId=ConversationId,
|
||||
Body=Body,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.delete("/chat/conversations/{ConversationId}", response_model=Result[RagOperationResultVO])
|
||||
async def DeleteConversation(ConversationId: str, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_delete"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除聊天会话权限", "data": None})
|
||||
data = await self.RagChatService.DeleteConversation(int(payload["user_id"]), ConversationId)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.DeleteConversation(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
**tenant_context,
|
||||
ConversationId=ConversationId,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
@self.router.post("/chat/messages/{MessageId}/feedback", response_model=Result[RagOperationResultVO])
|
||||
@@ -541,7 +583,13 @@ class RagChatController(BaseController):
|
||||
):
|
||||
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["message_feedback"]]):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有反馈聊天消息权限", "data": None})
|
||||
data = await self.RagChatService.UpdateFeedback(int(payload["user_id"]), MessageId, Body)
|
||||
tenant_context = self._tenant_context(payload)
|
||||
data = await self.RagChatService.UpdateFeedback(
|
||||
CurrentUserId=int(payload["user_id"]),
|
||||
**tenant_context,
|
||||
MessageId=MessageId,
|
||||
Body=Body,
|
||||
)
|
||||
return Result.success(data=data)
|
||||
|
||||
async def _check_permission(self, user_id: int, permission_keys: list[str]) -> bool:
|
||||
|
||||
@@ -8,7 +8,7 @@ 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_modules.fastapi_leaudit.domian.Dto.rbacAdminDto import RoleAccessSaveDTO, RoleCreateDTO, RolePermissionsBatchDTO, RoleRoutesUpdateDTO, RoleUpdateDTO, UserRolesAssignDTO
|
||||
from fastapi_modules.fastapi_leaudit.domian.Dto.rbacAdminDto import RoleAccessSaveDTO, RoleCreateDTO, RolePermissionsBatchDTO, RoleRoutesUpdateDTO, RoleUpdateDTO, UserRolesAssignDTO, UserTenantUpdateDTO
|
||||
from fastapi_modules.fastapi_leaudit.services.impl.rbacAdminServiceImpl import RbacAdminServiceImpl
|
||||
from fastapi_modules.fastapi_leaudit.services.rbacAdminService import IRbacAdminService
|
||||
|
||||
@@ -56,11 +56,12 @@ class RbacAdminController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(50, ge=1, le=200),
|
||||
area: str | None = Query(None),
|
||||
area: str | None = Query(None, description="兼容租户展示值/旧地区"),
|
||||
tenant_code: str | None = Query(None, description="租户编码"),
|
||||
nick_name: str | None = Query(None),
|
||||
):
|
||||
"""查询用户列表。"""
|
||||
data = await self.RbacAdminService.ListUsers(int(payload["user_id"]), page, page_size, area, nick_name)
|
||||
data = await self.RbacAdminService.ListUsers(int(payload["user_id"]), page, page_size, area, tenant_code, nick_name)
|
||||
return JSONResponse(status_code=200, content={"code": 200, "message": "success", "data": data.model_dump()})
|
||||
|
||||
@self.router.get("/admin/users/organizations/tree")
|
||||
@@ -79,11 +80,12 @@ class RbacAdminController(BaseController):
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(50, ge=1, le=200),
|
||||
area: str | None = Query(None),
|
||||
area: str | None = Query(None, description="兼容租户展示值/旧地区"),
|
||||
tenant_code: str | None = Query(None, description="租户编码"),
|
||||
username: str | None = Query(None),
|
||||
):
|
||||
"""查询指定角色下的用户列表。"""
|
||||
data = await self.RbacAdminService.ListRoleUsers(int(payload["user_id"]), RoleId, page, page_size, area, username)
|
||||
data = await self.RbacAdminService.ListRoleUsers(int(payload["user_id"]), RoleId, page, page_size, area, tenant_code, username)
|
||||
return JSONResponse(status_code=200, content={"code": 200, "message": "success", "data": data.model_dump()})
|
||||
|
||||
@self.router.post("/v3/rbac/users/{UserId}/roles")
|
||||
@@ -92,6 +94,12 @@ class RbacAdminController(BaseController):
|
||||
data = await self.RbacAdminService.AssignUserRoles(int(payload["user_id"]), UserId, Body.role_ids)
|
||||
return JSONResponse(status_code=200, content={"code": 200, "message": "角色分配成功", "data": data.model_dump()})
|
||||
|
||||
@self.router.put("/v3/rbac/users/{UserId}/tenant")
|
||||
async def UpdateUserTenant(UserId: int, Body: UserTenantUpdateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""更新用户租户。"""
|
||||
data = await self.RbacAdminService.UpdateUserTenant(int(payload["user_id"]), UserId, Body)
|
||||
return JSONResponse(status_code=200, content={"code": 200, "message": "用户租户更新成功", "data": data.model_dump()})
|
||||
|
||||
@self.router.delete("/v3/rbac/users/{UserId}/roles/{RoleId}")
|
||||
async def RevokeUserRole(UserId: int, RoleId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
"""移除用户角色。"""
|
||||
|
||||
@@ -30,7 +30,12 @@ class RuleConfigController(BaseController):
|
||||
"""列出规则配置页 pack。"""
|
||||
if not await self._check_permission(int(payload["user_id"])):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则配置查看权限", "data": None})
|
||||
data = await (self.RuleConfigService.ListPackSummaries() if summaryOnly else self.RuleConfigService.ListPacks())
|
||||
current_user_id = int(payload["user_id"])
|
||||
data = await (
|
||||
self.RuleConfigService.ListPackSummaries(CurrentUserId=current_user_id)
|
||||
if summaryOnly
|
||||
else self.RuleConfigService.ListPacks(CurrentUserId=current_user_id)
|
||||
)
|
||||
return JSONResponse(status_code=200, content={"code": 200, "message": "success", "data": [item.model_dump() for item in data]})
|
||||
|
||||
@self.router.get("/{PackId}")
|
||||
@@ -38,7 +43,7 @@ class RuleConfigController(BaseController):
|
||||
"""获取单个规则配置 pack。"""
|
||||
if not await self._check_permission(int(payload["user_id"])):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有规则配置查看权限", "data": None})
|
||||
data = await self.RuleConfigService.GetPack(PackId)
|
||||
data = await self.RuleConfigService.GetPack(PackId, CurrentUserId=int(payload["user_id"]))
|
||||
return JSONResponse(status_code=200, content={"code": 200, "message": "success", "data": data.model_dump()})
|
||||
|
||||
async def _check_permission(self, user_id: int) -> bool:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
"""租户主数据控制器。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import Depends, Query
|
||||
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_modules.fastapi_leaudit.domian.Dto.tenantDto import (
|
||||
TenantCreateDTO,
|
||||
TenantStatusUpdateDTO,
|
||||
TenantUpdateDTO,
|
||||
)
|
||||
from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl
|
||||
from fastapi_modules.fastapi_leaudit.services.impl.tenantServiceImpl import TenantServiceImpl
|
||||
from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService
|
||||
from fastapi_modules.fastapi_leaudit.services.tenantService import ITenantService
|
||||
|
||||
|
||||
class TenantController(BaseController):
|
||||
"""租户主数据控制器。"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(prefix="/v3/tenants", tags=["租户主数据"])
|
||||
self.TenantService: ITenantService = TenantServiceImpl()
|
||||
self.PermissionService: IPermissionService = PermissionServiceImpl()
|
||||
|
||||
@self.router.get("")
|
||||
async def GetTenants(
|
||||
include_disabled: bool = Query(False, description="是否包含禁用租户"),
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "rbac:tenants:read"):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看租户主数据权限", "data": None})
|
||||
data = await self.TenantService.ListTenants(IncludeDisabled=include_disabled)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": {"items": data, "total": len(data)}})
|
||||
|
||||
@self.router.get("/options")
|
||||
async def GetTenantOptions(
|
||||
feature_key: str | None = Query(None, description="按功能键过滤租户"),
|
||||
payload: dict[str, Any] = Depends(verify_access_token),
|
||||
):
|
||||
data = await self.TenantService.ListTenantOptions(FeatureKey=feature_key)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": {"items": data, "total": len(data)}})
|
||||
|
||||
@self.router.get("/{TenantCode}")
|
||||
async def GetTenant(TenantCode: str, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "rbac:tenants:read"):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看租户详情权限", "data": None})
|
||||
data = await self.TenantService.GetTenant(TenantCode)
|
||||
if not data:
|
||||
return JSONResponse(status_code=404, content={"code": 404, "msg": "租户不存在", "data": None})
|
||||
features = await self.TenantService.GetTenantFeatures(TenantCode)
|
||||
aliases = await self.TenantService.GetTenantAliases(TenantCode)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": {**data, "feature_keys": features, "alias_values": aliases}})
|
||||
|
||||
@self.router.post("")
|
||||
async def CreateTenant(Body: TenantCreateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "rbac:tenants:create"):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建租户权限", "data": None})
|
||||
data = await self.TenantService.CreateTenant(int(payload["user_id"]), Body)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": data})
|
||||
|
||||
@self.router.put("/{TenantCode}")
|
||||
async def UpdateTenant(TenantCode: str, Body: TenantUpdateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "rbac:tenants:update"):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新租户权限", "data": None})
|
||||
data = await self.TenantService.UpdateTenant(int(payload["user_id"]), TenantCode, Body)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": data})
|
||||
|
||||
@self.router.patch("/{TenantCode}/status")
|
||||
async def UpdateTenantStatus(TenantCode: str, Body: TenantStatusUpdateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
||||
if not await self.PermissionService.CheckPermission(int(payload["user_id"]), "rbac:tenants:status"):
|
||||
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新租户状态权限", "data": None})
|
||||
data = await self.TenantService.UpdateTenantStatus(int(payload["user_id"]), TenantCode, Body)
|
||||
return JSONResponse(status_code=200, content={"code": 0, "msg": "success", "data": data})
|
||||
Reference in New Issue
Block a user