diff --git a/api/controllers/console/datasets/datasets.py b/api/controllers/console/datasets/datasets.py index da39eb26b4e..8e3c24d19c3 100644 --- a/api/controllers/console/datasets/datasets.py +++ b/api/controllers/console/datasets/datasets.py @@ -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) diff --git a/api/controllers/console/datasets/datasets_document.py b/api/controllers/console/datasets/datasets_document.py index 8b793459c0f..4cd659acb09 100644 --- a/api/controllers/console/datasets/datasets_document.py +++ b/api/controllers/console/datasets/datasets_document.py @@ -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.""" diff --git a/api/tests/unit_tests/controllers/console/datasets/test_datasets.py b/api/tests/unit_tests/controllers/console/datasets/test_datasets.py index 794c8341add..1e6bcd66095 100644 --- a/api/tests/unit_tests/controllers/console/datasets/test_datasets.py +++ b/api/tests/unit_tests/controllers/console/datasets/test_datasets.py @@ -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", diff --git a/api/tests/unit_tests/controllers/console/datasets/test_datasets_document.py b/api/tests/unit_tests/controllers/console/datasets/test_datasets_document.py index e636a4634e1..3d6a7936592 100644 --- a/api/tests/unit_tests/controllers/console/datasets/test_datasets_document.py +++ b/api/tests/unit_tests/controllers/console/datasets/test_datasets_document.py @@ -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()