155 lines
5.8 KiB
Python
155 lines
5.8 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
from unittest.mock import patch
|
|
|
|
from odoo import Command
|
|
from odoo.exceptions import AccessError
|
|
from odoo.tests import new_test_user, TransactionCase, tagged, users
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestAiFieldsAccess(TransactionCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.internal_user = new_test_user(cls.env, 'internal')
|
|
|
|
def test_ai_access_agent_system(self):
|
|
# system: every right
|
|
agent = self.env['ai.agent'].create({'name': 'test agent'})
|
|
agent.write({'subtitle': 'bloups'})
|
|
self.assertEqual(self.env['ai.agent'].search([('name', '=', 'test agent')]), agent)
|
|
agent.unlink()
|
|
self.assertFalse(agent.exists())
|
|
|
|
@users('internal')
|
|
def test_ai_access_agent_internal(self):
|
|
# internal: readonly
|
|
with self.assertRaises(AccessError):
|
|
self.env['ai.agent'].create({'name': 'test agent'})
|
|
agent_sudo = self.env['ai.agent'].sudo().create({'name': 'test agent'})
|
|
agent = self.env['ai.agent'].search([('name', '=', 'test agent')])
|
|
self.assertEqual(agent, agent_sudo)
|
|
self.assertEqual('test agent', agent.name)
|
|
with self.assertRaises(AccessError):
|
|
agent.write({'subtitle': 'bloups'})
|
|
with self.assertRaises(AccessError):
|
|
agent.unlink()
|
|
|
|
def test_ai_access_embedding_system(self):
|
|
# system: every right
|
|
attachment = self.env['ir.attachment'].create({
|
|
'name': 'test attachment',
|
|
'datas': 'dGVzdA==', # "test" in base64
|
|
'res_model': 'ai.embedding',
|
|
'res_id': 0,
|
|
})
|
|
embedding = self.env['ai.embedding'].create({
|
|
'attachment_id': attachment.id,
|
|
'content': 'test content',
|
|
'embedding_model': 'text-embedding-3-small',
|
|
})
|
|
embedding.write({'content': 'updated content'})
|
|
self.assertEqual(
|
|
self.env['ai.embedding'].search([('id', '=', embedding.id)]),
|
|
embedding
|
|
)
|
|
embedding.unlink()
|
|
self.assertFalse(embedding.exists())
|
|
|
|
@users('internal')
|
|
def test_ai_access_embedding_internal(self):
|
|
# internal: readonly
|
|
attachment = self.env['ir.attachment'].create({
|
|
'name': 'test attachment',
|
|
'datas': 'dGVzdA==', # "test" in base64
|
|
'res_model': 'ai.embedding',
|
|
'res_id': 0,
|
|
})
|
|
with self.assertRaises(AccessError):
|
|
self.env['ai.embedding'].create({
|
|
'attachment_id': attachment.id,
|
|
'content': 'test content',
|
|
'embedding_model': 'text-embedding-3-small',
|
|
})
|
|
embedding_sudo = self.env['ai.embedding'].sudo().create({
|
|
'attachment_id': attachment.id,
|
|
'content': 'test content',
|
|
'embedding_model': 'text-embedding-3-small',
|
|
})
|
|
embedding = self.env['ai.embedding'].search([('id', '=', embedding_sudo.id)])
|
|
self.assertEqual(embedding, embedding_sudo)
|
|
self.assertEqual('test content', embedding.content)
|
|
with self.assertRaises(AccessError):
|
|
embedding.write({'content': 'updated content'})
|
|
with self.assertRaises(AccessError):
|
|
embedding.unlink()
|
|
|
|
def test_ai_access_topic_system(self):
|
|
# system: every right
|
|
topic = self.env['ai.topic'].create({
|
|
'name': 'test topic',
|
|
'description': 'topic description',
|
|
})
|
|
topic.write({'description': 'updated topic description'})
|
|
self.assertEqual(
|
|
self.env['ai.topic'].search([('id', '=', topic.id)]),
|
|
topic
|
|
)
|
|
topic.unlink()
|
|
self.assertFalse(topic.exists())
|
|
|
|
@users('internal')
|
|
def test_ai_access_topic_internal(self):
|
|
# internal: readonly
|
|
with self.assertRaises(AccessError):
|
|
self.env['ai.topic'].create({
|
|
'name': 'test topic',
|
|
'description': 'topic description',
|
|
})
|
|
topic_sudo = self.env['ai.topic'].sudo().create({
|
|
'name': 'test topic',
|
|
'description': 'topic description',
|
|
})
|
|
topic = self.env['ai.topic'].search([('id', '=', topic_sudo.id)])
|
|
self.assertEqual(topic, topic_sudo)
|
|
self.assertEqual('test topic', topic.name)
|
|
with self.assertRaises(AccessError):
|
|
topic.write({'description': 'updated topic description'})
|
|
with self.assertRaises(AccessError):
|
|
topic.unlink()
|
|
|
|
@users('internal')
|
|
def test_generate_response_non_admin_tool_access(self):
|
|
"""Test that non-admin users can call _generate_response without access errors on tool_ids."""
|
|
|
|
tool = self.env['ir.actions.server'].sudo().create({
|
|
'name': 'Test Tool',
|
|
'state': 'code',
|
|
'model_id': self.env.ref('base.model_res_partner').id,
|
|
'code': "",
|
|
'use_in_ai': True,
|
|
})
|
|
|
|
topic = self.env['ai.topic'].sudo().create({
|
|
'name': 'Test Topic',
|
|
'tool_ids': [Command.set([tool.id])],
|
|
})
|
|
|
|
agent = self.env['ai.agent'].sudo().create({
|
|
'name': 'Test Agent',
|
|
'topic_ids': [Command.set([topic.id])],
|
|
})
|
|
|
|
with patch('odoo.addons.ai.utils.llm_api_service.LLMApiService.request_llm') as mock_request_llm:
|
|
mock_request_llm.return_value = ['Hello!']
|
|
|
|
response = agent.with_user(self.env.user)._generate_response("hello")
|
|
|
|
self.assertEqual(response, ['Hello!'])
|
|
mock_request_llm.assert_called_once()
|
|
call_kwargs = mock_request_llm.call_args.kwargs
|
|
self.assertIn('tools', call_kwargs)
|
|
self.assertEqual(len(call_kwargs['tools']), 1)
|
|
self.assertEqual('Test Tool', next(iter(call_kwargs['tools'].values()))[0])
|