mirror of
https://github.com/langgenius/dify.git
synced 2026-11-11 05:41:09 +08:00
feat(rbac): agent RBAC/ACL scenes and resource-locator check bundles (#41768)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
60e983c493
commit
86134ea99e
152 files changed
+5360
-3405
No files matched your search
@@ -1,7 +1,8 @@
|
||||
import uuid
|
||||
|
||||
from controllers.common.rbac import PlainApp, RBACCheck
|
||||
from controllers.openapi.auth.composition import account_pipeline, auth_router, external_sso_pipeline
|
||||
from controllers.openapi.auth.data import RBACRequirement, RequestContext
|
||||
from controllers.openapi.auth.data import RequestContext
|
||||
from controllers.openapi.auth.flow import When
|
||||
from controllers.openapi.auth.pipeline import AuthPipeline, PipelineRoute, PipelineRouter
|
||||
from controllers.openapi.auth.verify import (
|
||||
@@ -12,7 +13,7 @@ from controllers.openapi.auth.verify import (
|
||||
check_workspace_mismatch,
|
||||
check_workspace_role,
|
||||
)
|
||||
from core.rbac import RBACPermission, RBACResourceScope
|
||||
from core.rbac import RBACPermission
|
||||
from enums import DeploymentEdition
|
||||
from libs.oauth_bearer import Scope, TokenType
|
||||
from models.account import TenantAccountRole
|
||||
@@ -206,7 +207,7 @@ def _selected_auth_steps_with_rbac(rbac):
|
||||
|
||||
|
||||
def test_account_pipeline_selects_rbac_step_when_required():
|
||||
rbac = RBACRequirement(resource_type=RBACResourceScope.APP, scene=RBACPermission.APP_VIEW_LAYOUT)
|
||||
rbac = RBACCheck(RBACPermission.APP_VIEW_LAYOUT, PlainApp())
|
||||
assert check_rbac_permission in _selected_auth_steps_with_rbac(rbac)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from controllers.common.rbac import PlainApp, RBACCheck
|
||||
from controllers.openapi.auth.conditions import (
|
||||
EDITION_CLOUD,
|
||||
EDITION_COMMUNITY,
|
||||
@@ -18,8 +19,8 @@ from controllers.openapi.auth.conditions import (
|
||||
data_cond,
|
||||
request_cond,
|
||||
)
|
||||
from controllers.openapi.auth.data import AuthData, RBACRequirement, RequestContext
|
||||
from core.rbac import RBACPermission, RBACResourceScope
|
||||
from controllers.openapi.auth.data import AuthData, RequestContext
|
||||
from core.rbac import RBACPermission
|
||||
from enums import DeploymentEdition
|
||||
from libs.oauth_bearer import Scope, TokenType
|
||||
from models.account import TenantAccountRole
|
||||
@@ -153,7 +154,7 @@ def test_webapp_run_scoped_false_when_scope_none():
|
||||
|
||||
|
||||
def _rbac_req():
|
||||
return RBACRequirement(resource_type=RBACResourceScope.APP, scene=RBACPermission.APP_TEST_AND_RUN)
|
||||
return RBACCheck(RBACPermission.APP_TEST_AND_RUN, PlainApp())
|
||||
|
||||
|
||||
def test_has_rbac_true():
|
||||
|
||||
@@ -6,7 +6,8 @@ import pytest
|
||||
from flask import Flask
|
||||
from werkzeug.exceptions import Forbidden, NotFound
|
||||
|
||||
from controllers.openapi.auth.data import AuthData, RBACRequirement
|
||||
from controllers.common.rbac import PlainApp, RBACCheck
|
||||
from controllers.openapi.auth.data import AuthData
|
||||
from controllers.openapi.auth.verify import (
|
||||
check_acl,
|
||||
check_app_access,
|
||||
@@ -18,7 +19,7 @@ from controllers.openapi.auth.verify import (
|
||||
check_workspace_mismatch,
|
||||
check_workspace_role,
|
||||
)
|
||||
from core.rbac import RBACPermission, RBACResourceScope
|
||||
from core.rbac import RBACPermission
|
||||
from libs.oauth_bearer import Scope, TokenType
|
||||
from models.account import Tenant, TenantAccountRole
|
||||
from models.model import App
|
||||
@@ -85,25 +86,25 @@ def test_check_app_access_raises_when_not_member():
|
||||
|
||||
# --- check_rbac_permission ---
|
||||
|
||||
_RBAC_REQ = RBACRequirement(resource_type=RBACResourceScope.APP, scene=RBACPermission.APP_VIEW_LAYOUT)
|
||||
_RBAC_REQ = RBACCheck(RBACPermission.APP_VIEW_LAYOUT, PlainApp())
|
||||
|
||||
|
||||
def test_check_rbac_noop_when_no_requirement():
|
||||
with patch("controllers.openapi.auth.verify.enforce_rbac_access") as mock_enforce:
|
||||
with patch("controllers.openapi.auth.verify.enforce_rbac_checks") as mock_enforce:
|
||||
check_rbac_permission(_data(rbac=None, caller_kind="account"))
|
||||
mock_enforce.assert_not_called()
|
||||
|
||||
|
||||
def test_check_rbac_noop_when_rbac_disabled(config_overrides: Callable[..., None]):
|
||||
config_overrides(RBAC_ENABLED=False)
|
||||
with patch("controllers.openapi.auth.verify.enforce_rbac_access") as mock_enforce:
|
||||
with patch("controllers.openapi.auth.verify.enforce_rbac_checks") as mock_enforce:
|
||||
check_rbac_permission(_data(rbac=_RBAC_REQ, caller_kind="account"))
|
||||
mock_enforce.assert_not_called()
|
||||
|
||||
|
||||
def test_check_rbac_skips_end_user_caller():
|
||||
with (
|
||||
patch("controllers.openapi.auth.verify.enforce_rbac_access") as mock_enforce,
|
||||
patch("controllers.openapi.auth.verify.enforce_rbac_checks") as mock_enforce,
|
||||
):
|
||||
check_rbac_permission(_data(rbac=_RBAC_REQ, caller_kind="end_user"))
|
||||
mock_enforce.assert_not_called()
|
||||
@@ -126,17 +127,18 @@ def test_check_rbac_enforces_for_account_caller():
|
||||
path_params={"app_id": "app-1"},
|
||||
)
|
||||
with (
|
||||
patch("controllers.openapi.auth.verify.enforce_rbac_access") as mock_enforce,
|
||||
patch("controllers.openapi.auth.verify.enforce_rbac_checks") as mock_enforce,
|
||||
):
|
||||
check_rbac_permission(data)
|
||||
mock_enforce.assert_called_once_with(
|
||||
tenant_id="t1",
|
||||
account_id=str(account_id),
|
||||
resource_type=RBACResourceScope.APP,
|
||||
scene=RBACPermission.APP_VIEW_LAYOUT,
|
||||
resource_required=True,
|
||||
path_args={"app_id": "app-1"},
|
||||
)
|
||||
mock_enforce.assert_called_once()
|
||||
call_kwargs = mock_enforce.call_args.kwargs
|
||||
assert call_kwargs["tenant_id"] == "t1"
|
||||
assert call_kwargs["account_id"] == str(account_id)
|
||||
assert call_kwargs["path_args"] == {"app_id": "app-1"}
|
||||
(check,) = call_kwargs["checks"]
|
||||
assert isinstance(check, RBACCheck)
|
||||
assert check.scene is RBACPermission.APP_VIEW_LAYOUT
|
||||
assert isinstance(check.locator, PlainApp)
|
||||
|
||||
|
||||
def test_check_acl_raises_when_app_or_mode_missing():
|
||||
|
||||
Reference in new issue
Block a user