feat: 平台治理与权限体系完善,存储进度/GPU预留/审批中心与日志整合
- 平台治理: 租户用户权限层次、资源ACL、审批中心与审批模板、访问申请 - 存储: MinIO 存储进度迁移、对象存储安全加固与测试 - 计算: GPU 资源预留、compute 轮询与同步增强 - 权限: permission v2 迁移、权限安全验收测试 - 日志: 后端运行日志中文说明、操作日志整合 - 数据处理/评测: 数据转换与模型评测优化 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -29,12 +29,18 @@ from fastapi import (
|
||||
Header,
|
||||
HTTPException,
|
||||
Query,
|
||||
Request,
|
||||
UploadFile,
|
||||
)
|
||||
from fastapi.responses import StreamingResponse
|
||||
from psycopg.rows import dict_row
|
||||
|
||||
from app.core.auth import filter_accessible_resource_ids, get_current_user, is_admin
|
||||
from app.core.auth import (
|
||||
filter_accessible_resource_ids,
|
||||
get_current_user,
|
||||
has_resource_access,
|
||||
is_admin,
|
||||
)
|
||||
from app.core.config import get_settings
|
||||
from app.db.platform_store import get_platform_store
|
||||
from app.modules.data_process.algorithms import (
|
||||
@@ -110,7 +116,6 @@ from app.schemas.data_process import (
|
||||
ResultUpdate,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/data-process")
|
||||
logger = logging.getLogger(__name__)
|
||||
MAX_SOURCE_FILE_BYTES = 200 * 1024 * 1024
|
||||
MAX_SOURCE_FILE_COUNT = 20
|
||||
@@ -163,6 +168,27 @@ def fail(status_code: int, message: str) -> HTTPException:
|
||||
)
|
||||
|
||||
|
||||
def _authorize_data_process_request(
|
||||
request: Request,
|
||||
task_id: str | None = None,
|
||||
current_user: dict[str, Any] = Depends(get_current_user),
|
||||
) -> None:
|
||||
"""Apply resource ACL and tenant checks to every task-scoped endpoint."""
|
||||
if not task_id or is_admin(current_user):
|
||||
return
|
||||
permission = "read" if request.method in {"GET", "HEAD"} else "write"
|
||||
if any(marker in request.url.path for marker in ("/start", "/generate", "/regenerate", "/repeat", "/publish", "/external/")):
|
||||
permission = "execute"
|
||||
if not has_resource_access("data_process", task_id, current_user, permission):
|
||||
raise fail(403, "no permission to access this data process task")
|
||||
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/data-process",
|
||||
dependencies=[Depends(_authorize_data_process_request)],
|
||||
)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def api_errors() -> Iterator[None]:
|
||||
try:
|
||||
@@ -887,7 +913,7 @@ def list_tasks(
|
||||
keyword=keyword,
|
||||
status=status,
|
||||
process_type=process_type,
|
||||
tenant_id=tenant_id,
|
||||
tenant_id=tenant_id if is_admin(current_user) else (current_user.get("tenant_id") or "default"),
|
||||
project_id=project_id,
|
||||
)
|
||||
# #4 资源 ACL 过滤:admin 放行,普通用户只看到自己被授权的数据处理任务
|
||||
@@ -908,9 +934,15 @@ def list_tasks(
|
||||
def create_task(
|
||||
payload: DataProcessTaskCreate,
|
||||
store: DataProcessStore = Depends(get_data_process_store),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
) -> dict[str, Any]:
|
||||
with api_errors():
|
||||
task = store.create_task(payload.model_dump(mode="json"))
|
||||
values = payload.model_dump(mode="json")
|
||||
values["created_by"] = current_user.get("id")
|
||||
values["owner_id"] = current_user.get("id")
|
||||
values["tenant_id"] = current_user.get("tenant_id") or "default"
|
||||
get_platform_store().assert_active_tenant(values["tenant_id"])
|
||||
task = store.create_task(values)
|
||||
return ok(task, "data process task created")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user