You've already forked DataMate
feat(auth): 为数据管理和RAG服务增加资源访问控制
- 在DatasetApplicationService中注入ResourceAccessService并添加所有权验证 - 在KnowledgeSetApplicationService中注入ResourceAccessService并添加所有权验证 - 修改DatasetRepository接口和实现类,增加按创建者过滤的方法 - 修改KnowledgeSetRepository接口和实现类,增加按创建者过滤的方法 - 在RAG索引器服务中添加知识库访问权限检查和作用域过滤 - 更新实体元对象处理器以使用请求用户上下文获取当前用户 - 在前端设置页面添加用户权限管理功能和角色权限控制 - 为Python标注服务增加用户上下文和数据集访问权限验证
This commit is contained in:
@@ -12,6 +12,11 @@ from app.module.shared.schema import StandardResponse, PaginatedData
|
||||
from app.module.dataset import DatasetManagementService
|
||||
from app.core.logging import get_logger
|
||||
|
||||
from ..security import (
|
||||
RequestUserContext,
|
||||
assert_dataset_access,
|
||||
get_request_user_context,
|
||||
)
|
||||
from ..service.mapping import DatasetMappingService
|
||||
from ..service.template import AnnotationTemplateService
|
||||
from ..service.knowledge_sync import KnowledgeSyncService
|
||||
@@ -42,7 +47,9 @@ async def login_label_studio(mapping_id: str, db: AsyncSession = Depends(get_db)
|
||||
"", response_model=StandardResponse[DatasetMappingCreateResponse], status_code=201
|
||||
)
|
||||
async def create_mapping(
|
||||
request: DatasetMappingCreateRequest, db: AsyncSession = Depends(get_db)
|
||||
request: DatasetMappingCreateRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_context: RequestUserContext = Depends(get_request_user_context),
|
||||
):
|
||||
"""
|
||||
创建数据集映射
|
||||
@@ -58,6 +65,8 @@ async def create_mapping(
|
||||
mapping_service = DatasetMappingService(db)
|
||||
template_service = AnnotationTemplateService()
|
||||
|
||||
await assert_dataset_access(db, request.dataset_id, user_context)
|
||||
|
||||
logger.info(f"Create dataset mapping request: {request.dataset_id}")
|
||||
|
||||
# 从DM服务获取数据集信息
|
||||
@@ -163,7 +172,7 @@ async def create_mapping(
|
||||
try:
|
||||
from ..service.editor import AnnotationEditorService
|
||||
|
||||
editor_service = AnnotationEditorService(db)
|
||||
editor_service = AnnotationEditorService(db, user_context)
|
||||
# 异步预计算切片(不阻塞创建响应)
|
||||
segmentation_result = (
|
||||
await editor_service.precompute_segmentation_for_project(
|
||||
@@ -202,6 +211,7 @@ async def list_mappings(
|
||||
False, description="是否包含模板详情", alias="includeTemplate"
|
||||
),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_context: RequestUserContext = Depends(get_request_user_context),
|
||||
):
|
||||
"""
|
||||
查询所有映射关系(分页)
|
||||
@@ -230,6 +240,8 @@ async def list_mappings(
|
||||
limit=size,
|
||||
include_deleted=False,
|
||||
include_template=include_template,
|
||||
current_user_id=user_context.user_id,
|
||||
is_admin=user_context.is_admin,
|
||||
)
|
||||
|
||||
# 计算总页数
|
||||
@@ -256,7 +268,11 @@ async def list_mappings(
|
||||
|
||||
|
||||
@router.get("/{mapping_id}", response_model=StandardResponse[DatasetMappingResponse])
|
||||
async def get_mapping(mapping_id: str, db: AsyncSession = Depends(get_db)):
|
||||
async def get_mapping(
|
||||
mapping_id: str,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_context: RequestUserContext = Depends(get_request_user_context),
|
||||
):
|
||||
"""
|
||||
根据 UUID 查询单个映射关系(包含关联的标注模板详情)
|
||||
|
||||
@@ -278,6 +294,7 @@ async def get_mapping(mapping_id: str, db: AsyncSession = Depends(get_db)):
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Mapping not found: {mapping_id}"
|
||||
)
|
||||
await assert_dataset_access(db, mapping.dataset_id, user_context)
|
||||
|
||||
logger.info(
|
||||
f"Found mapping: {mapping.id}, template_included: {mapping.template is not None}"
|
||||
@@ -304,6 +321,7 @@ async def get_mappings_by_source(
|
||||
True, description="是否包含模板详情", alias="includeTemplate"
|
||||
),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_context: RequestUserContext = Depends(get_request_user_context),
|
||||
):
|
||||
"""
|
||||
根据源数据集 ID 查询所有映射关系(分页,包含模板详情)
|
||||
@@ -319,6 +337,7 @@ async def get_mappings_by_source(
|
||||
"""
|
||||
try:
|
||||
service = DatasetMappingService(db)
|
||||
await assert_dataset_access(db, dataset_id, user_context)
|
||||
|
||||
# 计算 skip
|
||||
skip = (page - 1) * size
|
||||
@@ -333,6 +352,8 @@ async def get_mappings_by_source(
|
||||
skip=skip,
|
||||
limit=size,
|
||||
include_template=include_template,
|
||||
current_user_id=user_context.user_id,
|
||||
is_admin=user_context.is_admin,
|
||||
)
|
||||
|
||||
# 计算总页数
|
||||
@@ -364,6 +385,7 @@ async def get_mappings_by_source(
|
||||
async def delete_mapping(
|
||||
project_id: str = Path(..., description="映射UUID(path param)"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_context: RequestUserContext = Depends(get_request_user_context),
|
||||
):
|
||||
"""
|
||||
删除映射关系(软删除)
|
||||
@@ -387,6 +409,7 @@ async def delete_mapping(
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Mapping either not found or not specified."
|
||||
)
|
||||
await assert_dataset_access(db, mapping.dataset_id, user_context)
|
||||
|
||||
id = mapping.id
|
||||
dataset_id = mapping.dataset_id
|
||||
@@ -428,6 +451,7 @@ async def update_mapping(
|
||||
project_id: str = Path(..., description="映射UUID(path param)"),
|
||||
request: DatasetMappingUpdateRequest = None,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_context: RequestUserContext = Depends(get_request_user_context),
|
||||
):
|
||||
"""
|
||||
更新标注项目信息
|
||||
@@ -456,6 +480,7 @@ async def update_mapping(
|
||||
raise HTTPException(
|
||||
status_code=404, detail=f"Mapping not found: {project_id}"
|
||||
)
|
||||
await assert_dataset_access(db, mapping_orm.dataset_id, user_context)
|
||||
|
||||
# 构建更新数据
|
||||
update_values = {}
|
||||
|
||||
Reference in New Issue
Block a user