fix(api): enforce dataset operation permissions (#42758)

This commit is contained in:
XiaoBa authored and GitHub committed 2026-09-23 09:03:16 +00:00
1 parent 486bcb0b08
commit f6561d8cc0
4 files changed
+29 -5

No files matched your search

+1 -1
View File
@@ -806,7 +806,7 @@ class DatasetApi(Resource):
@cloud_edition_billing_rate_limit_check("knowledge")
@console_ns.response(204, "Dataset deleted successfully")
@with_current_user
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_EDIT, DatasetId()))
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_DELETE, DatasetId()))
@with_session
def delete(self, session: Session, current_user: Account, dataset_id: UUID):
dataset_id_str = str(dataset_id)
@@ -544,7 +544,7 @@ class DatasetDocumentListApi(Resource):
@console_ns.expect(console_ns.models[KnowledgeConfig.__name__])
@console_ns.response(200, "Documents created successfully", console_ns.models[DatasetAndDocumentResponse.__name__])
@with_current_user
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_EDIT, DatasetId()))
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_USE, DatasetId()))
@with_session
def post(self, session: Session, current_user: Account, dataset_id: UUID):
dataset_id_str = str(dataset_id)
@@ -595,7 +595,7 @@ class DatasetDocumentListApi(Resource):
@console_ns.response(204, "Documents deleted successfully")
@with_current_user
@with_current_tenant_id
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_EDIT, DatasetId()))
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_DELETE_FILE, DatasetId()))
@with_session
def delete(
self,
@@ -1125,7 +1125,7 @@ class DocumentApi(DocumentResource):
@console_ns.response(204, "Document deleted successfully")
@with_current_user
@with_current_tenant_id
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_EDIT, DatasetId()))
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_DELETE_FILE, DatasetId()))
@with_session
def delete(
self, session: Session, current_tenant_id: str, current_user: Account, dataset_id: UUID, document_id: UUID
@@ -1185,7 +1185,7 @@ class DocumentBatchDownloadZipApi(DocumentResource):
@console_ns.expect(console_ns.models[DocumentBatchDownloadZipPayload.__name__])
@with_current_user
@with_current_tenant_id
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_EDIT, DatasetId()))
@rbac_permission_required(RBACCheck(RBACPermission.DATASET_DOCUMENT_DOWNLOAD, DatasetId()))
@with_session(write=False)
def post(self, session: Session, current_tenant_id: str, current_user: Account, dataset_id: UUID):
"""Stream a ZIP archive containing the requested uploaded documents."""
@@ -58,6 +58,7 @@ from models.model import ApiToken, App, AppMode, DatasetApiTokenBinding, IconTyp
from services.dataset_ref_service import DatasetRef
from services.dataset_service import DatasetPermissionService, DatasetService
from services.enterprise import rbac_service as enterprise_rbac_service
from tests.unit_tests.controllers.rbac_introspection import rbac_checks
@pytest.fixture(autouse=True)
@@ -151,6 +152,13 @@ def make_related_app(**overrides) -> App:
return App(**base)
def test_dataset_delete_requires_dataset_delete_permission() -> None:
[check] = rbac_checks(DatasetApi.delete)
assert check.scene is RBACPermission.DATASET_DELETE
assert isinstance(check.locator, DatasetId)
def make_document_status(**overrides) -> Document:
base = {
"id": "doc-1",
@@ -256,6 +256,22 @@ def test_document_indexing_estimates_require_dataset_use_permission(method) -> N
assert isinstance(check.locator, DatasetId)
@pytest.mark.parametrize(
("method", "expected_scene"),
[
(DatasetDocumentListApi.post, RBACPermission.DATASET_USE),
(DatasetDocumentListApi.delete, RBACPermission.DATASET_DELETE_FILE),
(DocumentApi.delete, RBACPermission.DATASET_DELETE_FILE),
(DocumentBatchDownloadZipApi.post, RBACPermission.DATASET_DOCUMENT_DOWNLOAD),
],
)
def test_document_mutation_routes_require_operation_specific_permissions(method, expected_scene) -> None:
[check] = rbac_checks(method)
assert check.scene is expected_scene
assert isinstance(check.locator, DatasetId)
class TestGetProcessRuleApi(_UsesSQLiteSession):
def test_get_default_success(self, app: Flask, patch_tenant):
api = GetProcessRuleApi()