Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions ai_tool/models/ai_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ class AiTool(models.Model):
)

def _get_tool_definition(self):
func = getattr(self.env[self.model_id.model], self.function_name)
# model_id points to ir.model, which non-admin users cannot read.
# The model name is only metadata, so resolve it as sudo.
model = self.sudo().model_id.model
func = getattr(self.env[model], self.function_name)
return {
"name": self.name,
"description": self.description,
Expand Down Expand Up @@ -77,18 +80,20 @@ def _ai_post_message_parse_body(self, message):
return plaintext2html(message)

def _execute_tool(self, *args, record=None, **kwargs):
# model_id points to ir.model, which non-admin users cannot read.
# Resolve the model name as sudo (metadata only); the call below
# still runs with the caller's own rights via self.env[model].
model = self.sudo().model_id.model
if self.kind == "generic":
return getattr(self.env[self.model_id.model], self.function_name)(
*args, **kwargs
)
return getattr(self.env[model], self.function_name)(*args, **kwargs)
if not record:
raise ValueError("Record must be provided for non-generic tools")
if self.kind == "generic_model":
return getattr(self.env[self.model_id.model], self.function_name)(
return getattr(self.env[model], self.function_name)(
*args, record=record, **kwargs
)
elif record._name != self.model_id.model:
elif record._name != model:
raise ValueError(
f"Record model {record._name} does not match tool model {self.model_id.model}"
f"Record model {record._name} does not match tool model {model}"
)
return getattr(record, self.function_name)(*args, **kwargs) or {}
18 changes: 18 additions & 0 deletions ai_tool/tests/test_ai_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,21 @@ def test_post_message_tool_record_different_model(self):
tool.kind = "record"
with self.assertRaises(ValueError):
tool._execute_tool(message="Hello World", record=self.partner)

def test_tool_non_admin_user(self):
"""A plain internal user (no ir.model access) must be able to build a
tool definition and execute a generic tool: resolving the tool's model
is metadata and must not require Administration/Access Rights."""
user = self.env["res.users"].create(
{
"name": "Ai Tool Plain User",
"login": "ai_tool_plain_user",
"groups_id": [(6, 0, [self.env.ref("base.group_user").id])],
}
)
self.assertFalse(user.has_group("base.group_system"))
tool = self.env.ref("ai_tool.current_date").with_user(user)
definition = tool._get_tool_definition()
self.assertEqual(definition["name"], "get_date")
result = tool._execute_tool()
self.assertIn("date", result)
Loading