fix(agent-assets): allow admin access to platform rules
This commit is contained in:
@@ -33,11 +33,19 @@ class AgentAssetAccessScope:
|
||||
@classmethod
|
||||
def from_user(cls, current_user: CurrentUserContext) -> AgentAssetAccessScope:
|
||||
tenant_id = str(current_user.tenant_id or "").strip()
|
||||
if not tenant_id or tenant_id == AGENT_ASSET_PLATFORM_TENANT_ID:
|
||||
is_platform_admin = bool(current_user.is_admin)
|
||||
if not tenant_id or (
|
||||
tenant_id == AGENT_ASSET_PLATFORM_TENANT_ID and not is_platform_admin
|
||||
):
|
||||
raise PermissionError("当前登录会话缺少有效租户。")
|
||||
return cls(tenant_id=tenant_id, is_platform_admin=bool(current_user.is_admin))
|
||||
return cls(tenant_id=tenant_id, is_platform_admin=is_platform_admin)
|
||||
|
||||
def visibility_clause(self, model: Any) -> Any:
|
||||
if self.tenant_id == AGENT_ASSET_PLATFORM_TENANT_ID:
|
||||
return and_(
|
||||
model.scope == AGENT_ASSET_PLATFORM_SCOPE,
|
||||
model.tenant_id == AGENT_ASSET_PLATFORM_TENANT_ID,
|
||||
)
|
||||
return or_(
|
||||
and_(
|
||||
model.scope == AGENT_ASSET_PLATFORM_SCOPE,
|
||||
|
||||
@@ -693,6 +693,9 @@ def test_platform_spreadsheet_onlyoffice_requires_platform_admin_to_edit(monkeyp
|
||||
admin_callback_token = parse_qs(
|
||||
urlsplit(admin_config.config["editorConfig"]["callbackUrl"]).query
|
||||
)["access_token"][0]
|
||||
admin_content_token = parse_qs(
|
||||
urlsplit(admin_config.config["document"]["url"]).query
|
||||
)["access_token"][0]
|
||||
finance_session = service.validate_rule_spreadsheet_access_token(
|
||||
rule.id,
|
||||
finance_callback_token,
|
||||
@@ -708,6 +711,33 @@ def test_platform_spreadsheet_onlyoffice_requires_platform_admin_to_edit(monkeyp
|
||||
assert admin_session.tenant_id == "platform"
|
||||
assert admin_session.resource_scope == "platform"
|
||||
assert admin_session.actor == "username:platform_admin"
|
||||
|
||||
content_session = service.validate_rule_spreadsheet_access_token(
|
||||
rule.id,
|
||||
admin_content_token,
|
||||
)
|
||||
onlyoffice_service = AgentAssetService(
|
||||
db,
|
||||
current_user=CurrentUserContext(
|
||||
username=content_session.actor,
|
||||
name="ONLYOFFICE",
|
||||
role_codes=["manager"],
|
||||
is_admin=True,
|
||||
tenant_id=content_session.tenant_id,
|
||||
),
|
||||
)
|
||||
content_path, content_type, content_name = (
|
||||
onlyoffice_service.get_rule_spreadsheet_content(
|
||||
rule.id,
|
||||
validated_session=content_session,
|
||||
)
|
||||
)
|
||||
assert content_path.exists()
|
||||
assert content_type == (
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
)
|
||||
assert content_name.endswith(".xlsx")
|
||||
|
||||
with pytest.raises(AgentAssetOnlyOfficeSecurityError, match="不匹配"):
|
||||
service.validate_rule_spreadsheet_access_token(
|
||||
"different-asset",
|
||||
|
||||
@@ -21,7 +21,7 @@ from app.models.agent_asset import AgentAsset, AgentAssetTestRun, AgentAssetVers
|
||||
from app.models.financial_record import ExpenseClaim
|
||||
from app.models.tenant import Tenant
|
||||
from app.schemas.agent_asset import AgentAssetRiskRuleScenarioTestRequest
|
||||
from app.services.agent_asset_access import stable_user_principal
|
||||
from app.services.agent_asset_access import AgentAssetAccessScope, stable_user_principal
|
||||
from app.services.agent_asset_onlyoffice_security import (
|
||||
AgentAssetOnlyOfficeSessionService,
|
||||
)
|
||||
@@ -173,6 +173,43 @@ def test_asset_reads_are_authenticated_and_tenant_scoped() -> None:
|
||||
assert anonymous.status_code == 401
|
||||
|
||||
|
||||
def test_platform_tenant_scope_requires_real_admin_and_is_platform_only() -> None:
|
||||
non_admin = CurrentUserContext(
|
||||
username="platform-manager",
|
||||
name="平台经理",
|
||||
role_codes=["manager"],
|
||||
is_admin=False,
|
||||
tenant_id="platform",
|
||||
)
|
||||
with pytest.raises(PermissionError, match="有效租户"):
|
||||
AgentAssetAccessScope.from_user(non_admin)
|
||||
|
||||
platform_admin = CurrentUserContext(
|
||||
username="platform-admin",
|
||||
name="平台管理员",
|
||||
role_codes=["manager"],
|
||||
is_admin=True,
|
||||
tenant_id="platform",
|
||||
)
|
||||
access_scope = AgentAssetAccessScope.from_user(platform_admin)
|
||||
|
||||
factory = _factory()
|
||||
with factory() as db:
|
||||
assets = _seed(db)
|
||||
visible_assets = list(
|
||||
db.scalars(
|
||||
select(AgentAsset).where(access_scope.visibility_clause(AgentAsset))
|
||||
).all()
|
||||
)
|
||||
|
||||
assert [asset.id for asset in visible_assets] == [assets["platform"].id]
|
||||
assert access_scope.can_write(assets["platform"]) is True
|
||||
assert access_scope.can_write(assets["tenant-a"]) is False
|
||||
access_scope.require_write(assets["platform"])
|
||||
with pytest.raises(LookupError, match="Asset not found"):
|
||||
access_scope.require_write(assets["tenant-a"])
|
||||
|
||||
|
||||
def test_version_write_uses_stable_principal_and_blocks_cross_tenant_or_platform() -> None:
|
||||
factory = _factory()
|
||||
with factory() as db:
|
||||
|
||||
Reference in New Issue
Block a user