mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-13 02:14:23 +00:00
Hold resumed turns and public-link visitors to the right wiki rules
A paused turn is found by the agent owner's id, so anyone holding one of the owner's agent keys could resume the owner's own chat with its saved wiki edit rights. A resume now counts as an API or widget caller when either the saved state or the resuming request is one, cuts the wiki tool to wiki_view unless the wiki allows outside edits, and gives the tool executor the same flags. A request that names an agent, by key or id, may only resume that agent's turn; otherwise the claim is released and the request refused. Public-link visitors run as themselves and reach only wikis they may edit, so the wiki switch no longer applies to them. Instead every wiki write in a public-link run waits for the visitor's approval, so the agent owner's prompt or sources can't steer an edit to the visitor's wiki unasked.
This commit is contained in:
1 parent
91e70d2f0c
commit
051452c438
10 files changed
+405
-64
No files matched your search
@@ -119,7 +119,7 @@ class TestWikiConfigAccess:
|
||||
|
||||
|
||||
class TestWikiOutsideEdits:
|
||||
"""API, widget and public-link runs edit a wiki only when its owner allows."""
|
||||
"""API-key runs edit a wiki only when its owner allows; link visitors are asked."""
|
||||
|
||||
def _tools(self, conn, caller, sid, agent_config):
|
||||
from docsgpt.agents.tools.wiki import WIKI_TOOL_ID, add_wiki_tool
|
||||
@@ -130,19 +130,44 @@ class TestWikiOutsideEdits:
|
||||
proc.decoded_token = {"sub": caller}
|
||||
proc.agent_config = agent_config
|
||||
cfg = proc._build_wiki_config()
|
||||
if cfg is None:
|
||||
return None
|
||||
tools = {}
|
||||
add_wiki_tool(tools, cfg)
|
||||
return {a["name"] for a in tools[WIKI_TOOL_ID]["actions"]}
|
||||
return {a["name"]: bool(a.get("require_approval")) for a in tools[WIKI_TOOL_ID]["actions"]}
|
||||
|
||||
@pytest.mark.parametrize("flag", ["external_api_caller", "public_link_caller"])
|
||||
def test_outside_caller_reads_until_the_owner_allows_edits(self, use_conn, flag):
|
||||
sid = str(SourcesRepository(use_conn).create("W", user_id=OWNER, config={"kind": "wiki"})["id"])
|
||||
assert self._tools(use_conn, OWNER, sid, {flag: True}) == {"wiki_view"}
|
||||
def _wiki(self, conn, owner=OWNER):
|
||||
return str(SourcesRepository(conn).create("W", user_id=owner, config={"kind": "wiki"})["id"])
|
||||
|
||||
def test_api_key_caller_reads_until_the_owner_allows_edits(self, use_conn):
|
||||
# A widget or API run acts as the agent owner, who owns the wiki.
|
||||
sid = self._wiki(use_conn)
|
||||
assert self._tools(use_conn, OWNER, sid, {"external_api_caller": True}) == {"wiki_view": False}
|
||||
SourcesRepository(use_conn).set_wiki_outside_edits(sid, OWNER, True)
|
||||
assert "wiki_create" in self._tools(use_conn, OWNER, sid, {flag: True})
|
||||
tools = self._tools(use_conn, OWNER, sid, {"external_api_caller": True})
|
||||
assert tools["wiki_create"] is False
|
||||
|
||||
def test_owner_and_team_editor_keep_every_action(self, use_conn):
|
||||
sid = str(SourcesRepository(use_conn).create("W", user_id=OWNER, config={"kind": "wiki"})["id"])
|
||||
sid = self._wiki(use_conn)
|
||||
_share(use_conn, "source", sid, "ed", "editor")
|
||||
assert "wiki_create" in self._tools(use_conn, OWNER, sid, {})
|
||||
assert "wiki_create" in self._tools(use_conn, "ed", sid, {})
|
||||
assert self._tools(use_conn, OWNER, sid, {})["wiki_create"] is False
|
||||
assert self._tools(use_conn, "ed", sid, {})["wiki_create"] is False
|
||||
|
||||
def test_link_visitor_edits_their_own_wiki_after_approving(self, use_conn):
|
||||
# Visitor owns a wiki that the agent (someone else's) also uses.
|
||||
sid = self._wiki(use_conn, owner="visitor")
|
||||
tools = self._tools(use_conn, "visitor", sid, {"public_link_caller": True})
|
||||
assert tools["wiki_view"] is False
|
||||
assert tools["wiki_create"] is True and tools["wiki_delete"] is True
|
||||
|
||||
def test_link_visitor_who_edits_the_wiki_through_a_team(self, use_conn):
|
||||
sid = self._wiki(use_conn)
|
||||
_share(use_conn, "source", sid, "visitor", "editor")
|
||||
tools = self._tools(use_conn, "visitor", sid, {"public_link_caller": True})
|
||||
assert tools["wiki_create"] is True
|
||||
|
||||
def test_link_visitor_without_edit_rights_gets_no_wiki_tool(self, use_conn):
|
||||
sid = self._wiki(use_conn)
|
||||
assert self._tools(use_conn, "visitor", sid, {"public_link_caller": True}) is None
|
||||
_share(use_conn, "source", sid, "visitor", "viewer")
|
||||
assert self._tools(use_conn, "visitor", sid, {"public_link_caller": True}) is None
|
||||
Reference in new issue
Block a user