Skip to content

fix(dataset): stop the legacy permission gate from shadowing RBAC - #39569

Open
BenjaminX wants to merge 1 commit into
langgenius:mainfrom
BenjaminX:fix/rbac-dataset-legacy-permission-gate
Open

fix(dataset): stop the legacy permission gate from shadowing RBAC#39569
BenjaminX wants to merge 1 commit into
langgenius:mainfrom
BenjaminX:fix/rbac-dataset-legacy-permission-gate

Conversation

@BenjaminX

Copy link
Copy Markdown
Contributor

When RBAC_ENABLED is true, per-dataset access is owned by the RBAC whitelist and the @rbac_permission_required decorators. get_datasets already reflects that: its RBAC branch skips the legacy visibility filter and documents that "permission control is enforced via permission_keys on each item and @rbac_permission_required decorators".

check_dataset_permission and check_dataset_operator_permission never got the same treatment, so they keep applying the legacy only_me / partial_team rules on every read and write path. The RBAC access config UI only writes the RBAC whitelist and never touches dataset.permission, so the two models cannot agree: after granting a member access from the RBAC UI, the legacy gate still rejects them with "You do not have permission to access this dataset." before the whitelist is ever consulted. Only the creator gets through, via the maintainer short-circuit.

Skip the legacy rules when RBAC is enabled, keeping the tenant check in front of the guard so cross-tenant access is still rejected. Behaviour without RBAC is unchanged.

GetProcessRuleApi resolves its dataset from a query-string document id and therefore cannot use the rbac_permission_required decorator; it was relying on the legacy gate alone. Enforce RBAC explicitly there once the dataset is known, following the existing enforce_rbac_access pattern, so neutralising the legacy gate does not widen access on that route.

Audited every caller of both helpers: the console routes all carry rbac_permission_required, the service_api routes authenticate as the tenant owner (the legacy rules were already skipped for them), and the remaining call sites are helpers reached from decorated routes.

When RBAC_ENABLED is true, per-dataset access is owned by the RBAC
whitelist and the @rbac_permission_required decorators. get_datasets
already reflects that: its RBAC branch skips the legacy visibility
filter and documents that "permission control is enforced via
permission_keys on each item and @rbac_permission_required decorators".

check_dataset_permission and check_dataset_operator_permission never got
the same treatment, so they keep applying the legacy only_me /
partial_team rules on every read and write path. The RBAC access config
UI only writes the RBAC whitelist and never touches dataset.permission,
so the two models cannot agree: after granting a member access from the
RBAC UI, the legacy gate still rejects them with "You do not have
permission to access this dataset." before the whitelist is ever
consulted. Only the creator gets through, via the maintainer
short-circuit.

Skip the legacy rules when RBAC is enabled, keeping the tenant check in
front of the guard so cross-tenant access is still rejected. Behaviour
without RBAC is unchanged.

GetProcessRuleApi resolves its dataset from a query-string document id
and therefore cannot use the rbac_permission_required decorator; it was
relying on the legacy gate alone. Enforce RBAC explicitly there once the
dataset is known, following the existing enforce_rbac_access pattern, so
neutralising the legacy gate does not widen access on that route.

Audited every caller of both helpers: the console routes all carry
rbac_permission_required, the service_api routes authenticate as the
tenant owner (the legacy rules were already skipped for them), and the
remaining call sites are helpers reached from decorated routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jul 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-07-25 08:43:10.611934916 +0000
+++ /tmp/pyrefly_pr.txt	2026-07-25 08:42:58.419823393 +0000
@@ -7789,9 +7789,17 @@
 ERROR Object of class `FakeAccount` has no attribute `current_tenant_id` [missing-attribute]
     --> tests/unit_tests/services/test_dataset_service_dataset.py:1124:9
 ERROR Argument `SimpleNamespace` is not assignable to parameter `user` with type `Account | None` in function `services.dataset_service.DatasetService.check_dataset_operator_permission` [bad-argument-type]
-    --> tests/unit_tests/services/test_dataset_service_dataset.py:1422:22
+    --> tests/unit_tests/services/test_dataset_service_dataset.py:1454:22
 ERROR Argument `SimpleNamespace` is not assignable to parameter `dataset` with type `Dataset | None` in function `services.dataset_service.DatasetService.check_dataset_operator_permission` [bad-argument-type]
-    --> tests/unit_tests/services/test_dataset_service_dataset.py:1430:25
+    --> tests/unit_tests/services/test_dataset_service_dataset.py:1454:46
+ERROR Argument `SimpleNamespace` is not assignable to parameter `user` with type `Account | None` in function `services.dataset_service.DatasetService.check_dataset_operator_permission` [bad-argument-type]
+    --> tests/unit_tests/services/test_dataset_service_dataset.py:1463:22
+ERROR Argument `SimpleNamespace` is not assignable to parameter `dataset` with type `Dataset | None` in function `services.dataset_service.DatasetService.check_dataset_operator_permission` [bad-argument-type]
+    --> tests/unit_tests/services/test_dataset_service_dataset.py:1463:46
+ERROR Argument `SimpleNamespace` is not assignable to parameter `user` with type `Account | None` in function `services.dataset_service.DatasetService.check_dataset_operator_permission` [bad-argument-type]
+    --> tests/unit_tests/services/test_dataset_service_dataset.py:1471:22
+ERROR Argument `SimpleNamespace` is not assignable to parameter `dataset` with type `Dataset | None` in function `services.dataset_service.DatasetService.check_dataset_operator_permission` [bad-argument-type]
+    --> tests/unit_tests/services/test_dataset_service_dataset.py:1479:25
 ERROR Object of class `FakeAccount` has no attribute `id` [missing-attribute]
    --> tests/unit_tests/services/test_dataset_service_document.py:106:9
 ERROR Object of class `FakeAccount` has no attribute `current_tenant_id` [missing-attribute]

@github-actions

Copy link
Copy Markdown
Contributor

Pyrefly Type Coverage

Metric Base PR Delta
Type coverage 54.90% 54.90% -0.01%
Strict coverage 54.40% 54.39% -0.01%
Typed symbols 35,583 35,584 +1
Untyped symbols 29,501 29,508 +7
Modules 3068 3068 0

@BenjaminX

Copy link
Copy Markdown
Contributor Author

Ref issue link
#39379

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant