fix(resources): enforce visibility on list + get (private invisible to non-owner)
回退 5483d19 的 workspace-wide 改动。用户真实语义:
- owner 永远可见自己的资源(含 private)
- 非 owner 只见别人 visibility in {workspace, public} 的资源
- admin 全部可见
can_view 与 list_resources 共享同一谓词。list 端点恢复
owner == me OR visibility in {workspace, public} 的过滤,
admin 跳过。get_resource / download_url / jupyter-relative-path
/ delete_resource 全部经 get_visible_resource → can_view,自然
收敛到同一语义。补 1 个 owner-看自己-private 测试,4 个
visibility 测试保持。
This commit is contained in:
@@ -420,13 +420,14 @@ def _resource_ctx(workspace_id: str = "W001") -> SimpleNamespace:
|
||||
request_id="test",
|
||||
user=SimpleNamespace(user_id="U001"),
|
||||
workspace=SimpleNamespace(workspace_id=workspace_id),
|
||||
is_admin=False,
|
||||
)
|
||||
|
||||
|
||||
class TestCanViewWorkspaceWideVisibility:
|
||||
"""can_view is workspace-wide: any workspace member may view any active
|
||||
resource, matching list_resources since 2026-08-11. visibility is only a
|
||||
semantic tag on upload/bind and no longer gates reads."""
|
||||
class TestCanViewVisibility:
|
||||
"""同一 workspace 内:owner 永远可见自己的资源(含 private);
|
||||
其他成员只见 visibility in {workspace, public} 的资源;
|
||||
admin 全部可见。与 list_resources 的 SQL 谓词一致。"""
|
||||
|
||||
@staticmethod
|
||||
def _viewer() -> SimpleNamespace:
|
||||
@@ -437,9 +438,15 @@ class TestCanViewWorkspaceWideVisibility:
|
||||
is_admin=False,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _owner() -> SimpleNamespace:
|
||||
ctx = TestCanViewVisibility._viewer()
|
||||
ctx.user = SimpleNamespace(user_id="U001") # the owner
|
||||
return ctx
|
||||
|
||||
@staticmethod
|
||||
def _admin() -> SimpleNamespace:
|
||||
ctx = TestCanViewWorkspaceWideVisibility._viewer()
|
||||
ctx = TestCanViewVisibility._viewer()
|
||||
ctx.is_admin = True
|
||||
return ctx
|
||||
|
||||
@@ -449,13 +456,22 @@ class TestCanViewWorkspaceWideVisibility:
|
||||
res.visibility = visibility
|
||||
return res
|
||||
|
||||
def test_workspace_member_can_view_others_private_resource(self) -> None:
|
||||
def test_owner_can_view_own_private_resource(self) -> None:
|
||||
assert (
|
||||
can_view(
|
||||
self._resource("private"),
|
||||
self._owner(),
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
def test_workspace_member_cannot_view_others_private_resource(self) -> None:
|
||||
assert (
|
||||
can_view(
|
||||
self._resource("private"),
|
||||
self._viewer(),
|
||||
)
|
||||
is True
|
||||
is False
|
||||
)
|
||||
|
||||
def test_workspace_member_can_view_others_workspace_resource(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user