mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-15 02:16:08 +00:00
Validate tool action updates and keep fixed values owner-only
update_tool_actions now checks the submitted actions against the tool's stored ones: no new actions or parameters, fixed values must fit their parameter's type. A team editor can still switch actions on and off but gets 403 for changing a fixed value.
This commit is contained in:
1 parent
34038ae1c2
commit
f6bdd853d5
2 files changed
+125
-16
No files matched your search
@@ -1306,26 +1306,103 @@ class TestUpdateToolActionsHappy:
|
||||
response = UpdateToolActions().post()
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_updates_actions(self, app, pg_conn):
|
||||
from docsgpt.api.user.tools.routes import UpdateToolActions
|
||||
@staticmethod
|
||||
def _seed_actions_tool(pg_conn, user):
|
||||
from docsgpt.storage.db.repositories.user_tools import UserToolsRepository
|
||||
|
||||
user = "u-actions"
|
||||
tool = _seed_tool(pg_conn, user=user)
|
||||
return UserToolsRepository(pg_conn).create(
|
||||
user,
|
||||
"telegram",
|
||||
config={},
|
||||
display_name="Telegram",
|
||||
description="",
|
||||
actions=[
|
||||
{
|
||||
"name": "telegram_send_message",
|
||||
"description": "Send a message",
|
||||
"active": True,
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {"type": "string", "filled_by_llm": True, "value": ""},
|
||||
"chat_id": {"type": "string", "filled_by_llm": True, "value": ""},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
status=True,
|
||||
)
|
||||
|
||||
def _post(self, app, pg_conn, user, tool_id, actions):
|
||||
from docsgpt.api.user.tools.routes import UpdateToolActions
|
||||
|
||||
with _patch_tools_db(pg_conn), app.test_request_context(
|
||||
"/api/update_tool_actions",
|
||||
method="POST",
|
||||
json={
|
||||
"id": str(tool["id"]),
|
||||
"actions": [
|
||||
{"name": "action_1", "active": True, "parameters": {}}
|
||||
],
|
||||
},
|
||||
json={"id": tool_id, "actions": actions},
|
||||
):
|
||||
from flask import request
|
||||
request.decoded_token = {"sub": user}
|
||||
response = UpdateToolActions().post()
|
||||
return UpdateToolActions().post()
|
||||
|
||||
@staticmethod
|
||||
def _stored(pg_conn, tool):
|
||||
from docsgpt.storage.db.repositories.user_tools import UserToolsRepository
|
||||
|
||||
return UserToolsRepository(pg_conn).get_by_id(str(tool["id"]))["actions"][0]
|
||||
|
||||
def test_updates_actions(self, app, pg_conn):
|
||||
user = "u-actions"
|
||||
tool = self._seed_actions_tool(pg_conn, user)
|
||||
response = self._post(
|
||||
app, pg_conn, user, str(tool["id"]), [{"name": "telegram_send_message", "active": False}],
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert self._stored(pg_conn, tool)["active"] is False
|
||||
|
||||
def test_owner_pins_a_parameter(self, app, pg_conn):
|
||||
user = "u-actions-pin"
|
||||
tool = self._seed_actions_tool(pg_conn, user)
|
||||
response = self._post(app, pg_conn, user, str(tool["id"]), [{
|
||||
"name": "telegram_send_message",
|
||||
"parameters": {"properties": {"chat_id": {"filled_by_llm": False, "value": "123"}}},
|
||||
}])
|
||||
assert response.status_code == 200
|
||||
chat_id = self._stored(pg_conn, tool)["parameters"]["properties"]["chat_id"]
|
||||
assert chat_id["filled_by_llm"] is False and chat_id["value"] == "123"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"actions",
|
||||
[
|
||||
[{"name": "made_up_action", "active": True}],
|
||||
[{"name": "telegram_send_message", "parameters": {"properties": {"token": {"value": "x"}}}}],
|
||||
[{"active": True}],
|
||||
"not a list",
|
||||
],
|
||||
)
|
||||
def test_rejects_actions_that_do_not_match_the_schema(self, app, pg_conn, actions):
|
||||
user = "u-actions-bad"
|
||||
tool = self._seed_actions_tool(pg_conn, user)
|
||||
response = self._post(app, pg_conn, user, str(tool["id"]), actions)
|
||||
assert response.status_code == 400
|
||||
assert self._stored(pg_conn, tool)["active"] is True
|
||||
|
||||
def test_team_editor_can_change_actions_but_not_pins(self, app, pg_conn):
|
||||
owner, editor = "u-owner", "u-editor"
|
||||
tool = self._seed_actions_tool(pg_conn, owner)
|
||||
with patch("docsgpt.api.user.tools.routes.effective_write_owner", return_value=owner):
|
||||
toggled = self._post(
|
||||
app, pg_conn, editor, str(tool["id"]), [{"name": "telegram_send_message", "active": False}],
|
||||
)
|
||||
pinned = self._post(app, pg_conn, editor, str(tool["id"]), [{
|
||||
"name": "telegram_send_message",
|
||||
"parameters": {"properties": {"chat_id": {"filled_by_llm": False, "value": "666"}}},
|
||||
}])
|
||||
assert toggled.status_code == 200
|
||||
assert pinned.status_code == 403
|
||||
stored = self._stored(pg_conn, tool)
|
||||
assert stored["active"] is False
|
||||
assert stored["parameters"]["properties"]["chat_id"]["filled_by_llm"] is True
|
||||
|
||||
|
||||
class TestUpdateToolStatusHappy:
|
||||
|
||||
Reference in new issue
Block a user