64af753aab
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 19s
CI / security (pull_request) Successful in 32s
CI / typecheck (pull_request) Successful in 36s
CI / integration_tests (pull_request) Successful in 2m40s
CI / unit_tests (pull_request) Successful in 11m42s
CI / docker (pull_request) Successful in 40s
CI / benchmark-regression (pull_request) Successful in 21m35s
CI / coverage (pull_request) Successful in 45m10s
CI / lint (push) Successful in 12s
CI / quality (push) Successful in 18s
CI / build (push) Successful in 23s
CI / security (push) Successful in 32s
CI / typecheck (push) Successful in 57s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 2m43s
CI / unit_tests (push) Successful in 12m13s
CI / benchmark-publish (push) Successful in 12m19s
CI / docker (push) Successful in 1m2s
CI / coverage (push) Successful in 1h26m6s
Implemented namespace/project/plan/skill permission model with role bindings (owner/admin/editor/viewer) and default deny policy. Added enforcement hooks at CLI/service boundaries that are server-only; local mode returns permissive defaults. Includes role enums, permission check service, role matrix documentation. Includes Behave BDD scenarios, Robot integration tests, ASV benchmarks, and reference documentation. ISSUES CLOSED: #344
114 lines
3.2 KiB
Python
114 lines
3.2 KiB
Python
"""Robot Framework helper for permission system integration tests.
|
|
|
|
Exposes keyword functions that exercise the permission domain model
|
|
and PermissionService from Python so Robot tests can validate
|
|
behaviour without importing modules directly in Robot syntax.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
|
|
# Ensure the src directory is on the path for imports
|
|
_src = os.path.join(os.path.dirname(__file__), "..", "src")
|
|
if _src not in sys.path:
|
|
sys.path.insert(0, _src)
|
|
|
|
from cleveragents.application.services.permission_service import ( # noqa: E402
|
|
PermissionService,
|
|
)
|
|
from cleveragents.domain.models.core.permission import ( # noqa: E402
|
|
DEFAULT_LOCAL_ROLE_MAPPING,
|
|
ROLE_PERMISSIONS,
|
|
PermissionAction,
|
|
PermissionRole,
|
|
PermissionScope,
|
|
RoleBinding,
|
|
)
|
|
|
|
_SERVER_MODE_ENV = "CLEVERAGENTS_SERVER_MODE"
|
|
|
|
|
|
def get_permission_roles() -> list[str]:
|
|
"""Return all PermissionRole values."""
|
|
return [r.value for r in PermissionRole]
|
|
|
|
|
|
def get_permission_scopes() -> list[str]:
|
|
"""Return all PermissionScope values."""
|
|
return [s.value for s in PermissionScope]
|
|
|
|
|
|
def get_permission_actions() -> list[str]:
|
|
"""Return all PermissionAction values."""
|
|
return [a.value for a in PermissionAction]
|
|
|
|
|
|
def check_permission_local_mode(
|
|
principal: str, action: str, scope: str, scope_id: str
|
|
) -> bool:
|
|
"""Run a permission check in local mode and return the result."""
|
|
os.environ.pop(_SERVER_MODE_ENV, None)
|
|
svc = PermissionService()
|
|
check = svc.check_permission(
|
|
principal=principal,
|
|
action=PermissionAction(action),
|
|
scope=PermissionScope(scope),
|
|
scope_id=scope_id,
|
|
)
|
|
return check.result
|
|
|
|
|
|
def check_permission_server_no_bindings(
|
|
principal: str, action: str, scope: str, scope_id: str
|
|
) -> bool:
|
|
"""Run a permission check in server mode with no bindings."""
|
|
os.environ[_SERVER_MODE_ENV] = "true"
|
|
svc = PermissionService()
|
|
check = svc.check_permission(
|
|
principal=principal,
|
|
action=PermissionAction(action),
|
|
scope=PermissionScope(scope),
|
|
scope_id=scope_id,
|
|
)
|
|
os.environ.pop(_SERVER_MODE_ENV, None)
|
|
return check.result
|
|
|
|
|
|
def check_permission_server_with_binding(
|
|
principal: str,
|
|
role: str,
|
|
action: str,
|
|
scope: str,
|
|
scope_id: str,
|
|
) -> bool:
|
|
"""Run a permission check in server mode with a specific binding."""
|
|
os.environ[_SERVER_MODE_ENV] = "true"
|
|
binding = RoleBinding(
|
|
principal=principal,
|
|
role=PermissionRole(role),
|
|
scope=PermissionScope(scope),
|
|
scope_id=scope_id,
|
|
)
|
|
svc = PermissionService(bindings=[binding])
|
|
check = svc.check_permission(
|
|
principal=principal,
|
|
action=PermissionAction(action),
|
|
scope=PermissionScope(scope),
|
|
scope_id=scope_id,
|
|
)
|
|
os.environ.pop(_SERVER_MODE_ENV, None)
|
|
return check.result
|
|
|
|
|
|
def get_role_action_count(role: str) -> int:
|
|
"""Return the number of allowed actions for a given role."""
|
|
perm_role = PermissionRole(role)
|
|
return len(ROLE_PERMISSIONS[perm_role])
|
|
|
|
|
|
def get_default_local_role() -> str:
|
|
"""Return the default local role for the wildcard principal."""
|
|
return str(DEFAULT_LOCAL_ROLE_MAPPING["*"])
|