Odoo18-Base/enterprise-17.0/knowledge/tests/common.py
2025-01-06 10:57:38 +07:00

429 lines
17 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import MailCommon, mail_new_test_user
from odoo.tools import mute_logger
class KnowledgeCommon(MailCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.user_portal = cls._create_portal_user()
cls.partner_portal = cls.user_portal.partner_id
cls.user_employee_manager = mail_new_test_user(
cls.env,
company_id=cls.company_admin.id,
country_id=cls.env.ref('base.be').id,
groups='base.group_user',
login='employee_manager',
name='Evelyne Employee',
notification_type='inbox',
signature='--\nEvelyne'
)
cls.partner_employee_manager = cls.user_employee_manager.partner_id
cls.user_employee2 = mail_new_test_user(
cls.env,
company_id=cls.company_admin.id,
country_id=cls.env.ref('base.be').id,
groups='base.group_user',
login='employee2',
name='Eglantine Employee',
notification_type='inbox',
signature='--\nEglantine'
)
cls.partner_employee2 = cls.user_employee2.partner_id
cls.user_public = mail_new_test_user(
cls.env,
company_id=cls.company_admin.id,
groups='base.group_public',
login='user_public',
name='Public Anonymous',
)
cls.partner_public = cls.user_public.partner_id
cls.customer = cls.env['res.partner'].create({
'country_id': cls.env.ref('base.be').id,
'email': 'corentine@test.example.com',
'mobile': '+32455001122',
'name': 'Corentine Customer',
'phone': '+32455334455',
})
def assertMembers(self, articles, exp_internal_permission, exp_partners_permissions, msg=None):
""" Custom assert for members, to ease writing tests. Check state of
members on articles, as sudo to avoid ACLs-based misunderstanding.
:param internal_permission: global internal permission of articles;
:param partners_permission: dict of pid: permission that are members
expected to be on articles;
"""
for article in articles.sudo():
self.assertEqual(article.internal_permission, exp_internal_permission)
self.assertEqual(
dict(
(member.partner_id, member.permission)
for member in article.article_member_ids
),
exp_partners_permissions,
msg
)
def assertSortedSequence(self, articles):
""" Assert that the articles are properly sorted according to their sequence
number
:param articles (Model<knowledge.article>): Recordset of knowledge.article
"""
for k in range(len(articles) - 1):
self.assertTrue(
articles[k].sequence <= articles[k + 1].sequence,
f'Article sequence issue: {articles[k].name} ({articles[k].sequence}) which is not <= than {articles[k + 1].name} ({articles[k + 1].sequence})')
def _create_private_article(self, name, target_user=None):
""" Due to membership model constraints, create test records as sudo
and return a record in current user environment. Creation itself is
not tested here. """
target_user = self.env.user if target_user is None else target_user
if target_user:
vals = {
'article_member_ids': [(0, 0, {
'partner_id': target_user.partner_id.id,
'permission': 'write',
})],
}
vals.update({
'internal_permission': 'none',
'name': name,
})
return self.env['knowledge.article'].sudo().create(vals).with_user(self.env.user)
def _create_cover(self):
pixel = 'R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs='
attachment = self.env['ir.attachment'].create({'name': 'pixel', 'datas': pixel, 'res_model': 'knowledge.cover', 'res_id': 0})
return self.env['knowledge.cover'].create({'attachment_id': attachment.id})
class KnowledgeCommonWData(KnowledgeCommon):
""" Light setup of articles for knowledge tests. It holds data for the
three main categories: workspace, shared and private articles. Some
children exist to have some permission tweaks. """
@classmethod
def setUpClass(cls):
super().setUpClass()
with mute_logger('odoo.models.unlink'):
cls.env['knowledge.article'].search([]).unlink()
# - Private seq=997 private none (manager-w+)
# - Child1 seq=0 " "
# - Shared seq=998 shared none (admin-w+,employee-r+,manager-r+)
# - Child1 seq=0 " " (employee-w+)
# - Child2 seq=0 " " (portal-r+)
# - Playground seq=999 workspace w+
# - Child1 seq=0 " "
# - Child2 seq=1 " "
cls._base_sequence = 999
cls.article_workspace = cls.env['knowledge.article'].create(
{'internal_permission': 'write',
'favorite_ids': [(0, 0, {'sequence': 1,
'user_id': cls.user_admin.id
}),
],
'name': 'Playground',
'sequence': cls._base_sequence,
'is_article_visible_by_everyone': True,
}
)
cls.workspace_children = cls.env['knowledge.article'].create([
{'name': 'Playground Child1',
'parent_id': cls.article_workspace.id,
},
{'name': 'Playground Child2',
'parent_id': cls.article_workspace.id,
},
])
cls.article_shared = cls.env['knowledge.article'].create(
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_admin.id,
'permission': 'write',
}),
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'read',
}),
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'read',
}),
],
'internal_permission': 'none',
'name': 'Shared',
'sequence': cls._base_sequence - 1,
}
)
cls.shared_children = cls.env['knowledge.article'].create([
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'write',
}),
],
'internal_permission': False,
'name': 'Shared Child1',
'parent_id': cls.article_shared.id,
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_portal.id,
'permission': 'read',
}),
],
'internal_permission': False,
'favorite_ids': [
(0, 0, {'sequence': 1,
'user_id': cls.user_portal.id,
}),
],
'name': 'Shared Child2',
'parent_id': cls.article_shared.id,
}
])
cls.article_private_manager = cls.env['knowledge.article'].create(
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'write',
}),
],
'internal_permission': 'none',
'name': 'Private',
'sequence': cls._base_sequence - 2,
}
)
cls.private_children = cls.env['knowledge.article'].create([
{'internal_permission': False,
'name': 'Private Child1',
'parent_id': cls.article_private_manager.id,
}
])
cls.env.flush_all()
class KnowledgeArticlePermissionsCase(KnowledgeCommon):
""" Specific test class to test permission management, inheritance and
computation on article model, based on both article and member permissions.
This does not really test ACLs, more the internals of permissions that
are used afterwards in ACLs and in various business methods / flows. """
@classmethod
def setUpClass(cls):
super().setUpClass()
with mute_logger('odoo.models.unlink'):
cls.env['knowledge.article'].search([]).unlink()
# ------------------------------------------------------------
# Perm (" = inherited) + exceptions
# WRITABLE ROOT write
# - Community " (w)
# - Members " (w) (-employee-read)
# - Readonly read (+manager-write)
# - Writable " (w) (+portal-read)
# - Writable child " (w)
# - Child "
# - Nyarlathotep DESYNC read, manager-write
# - Child "
# READABLE ROOT read (+manager-write)
# - TTRPG " (r)
# - OpenCthulhu write (+portal-read)
# - MansionsOfTerror DESYNC none, employee-write, manager-read
# - Child "
# - OpenParanoïa write (-employee-read, +portal-read)
# - Proprietary " (r)
# - Secret none
# - Child "
# - Board Games " (r)
# SHARED ROOT none (+manager-write, +employee-read)
# PRIVATE ROOT none (+employee-write)
#
# ------------------------------------------------------------
cls.article_roots = cls.env['knowledge.article'].create([
{'name': 'Writable Root',
'is_article_visible_by_everyone': True,
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'write',
}),
], # ensure at least one write access
'internal_permission': 'read',
'name': 'Readable Root',
'is_article_visible_by_everyone': True,
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'write',
}),
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'read',
}),
],
'internal_permission': 'none',
'favorite_ids': [
(0, 0, {'user_id': cls.user_employee_manager.id}),
(0, 0, {'user_id': cls.user_employee.id})
],
'name': 'Shared Root',
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'write',
}),
],
'internal_permission': 'none',
'name': 'Private Root',
}
])
cls.article_headers = cls.env['knowledge.article'].create([
# writable
{'name': 'Write-Community',
'parent_id': cls.article_roots[0].id,
},
# readable
{'name': 'Read-TTRPG',
'parent_id': cls.article_roots[1].id,
},
{'name': 'Read-Board Games',
'parent_id': cls.article_roots[1].id,
},
])
# Under Write internal permission
cls.article_write_contents = cls.env['knowledge.article'].create([
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'read',
}),
],
'favorite_ids': [
(0, 0, {'user_id': cls.user_admin.id}),
(0, 0, {'user_id': cls.user_employee.id})
],
'name': 'Members Subarticle',
'parent_id': cls.article_headers[0].id,
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'write',
}),
], # ensure at least one write access
'internal_permission': 'read',
'name': 'Readonly Subarticle',
'parent_id': cls.article_headers[0].id,
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_portal.id,
'permission': 'read',
}),
],
'body': '<p>Writable Subarticle through inheritance</p>',
'favorite_ids': [
(0, 0, {'user_id': cls.user_admin.id}),
(0, 0, {'user_id': cls.user_employee.id}),
(0, 0, {'user_id': cls.user_portal.id}),
],
'name': 'Writable Subarticle through inheritance',
'parent_id': cls.article_headers[0].id,
},
])
cls.article_write_contents_children = cls.env['knowledge.article'].create([
{'name': 'Child of writable through inheritance',
'parent_id': cls.article_write_contents[2].id,
},
])
cls.article_write_contents_children += cls.env['knowledge.article'].create([
{'name': 'Child of child of writable through inheritance',
'parent_id': cls.article_write_contents_children[0].id,
},
])
cls.article_write_desync = cls.env['knowledge.article'].create([
# Community/Writable
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'write',
}),
],
'internal_permission': 'read',
'is_desynchronized': True,
'name': 'Desync Nyarlathotep',
'parent_id': cls.article_write_contents[2].id,
},
])
cls.article_write_desync += cls.env['knowledge.article'].create([
{'name': 'Childof Desync Nyarlathotep',
'parent_id': cls.article_write_desync[0].id,
},
])
# Under Read internal permission
cls.article_read_contents = cls.env['knowledge.article'].create([
# TTRPG
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_portal.id,
'permission': 'read',
}),
],
'internal_permission': 'write',
'name': 'OpenCthulhu',
'parent_id': cls.article_headers[1].id,
},
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_portal.id,
'permission': 'read',
}),
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'read',
}),
],
'internal_permission': 'write',
'name': 'Open Paranoïa',
'parent_id': cls.article_headers[1].id,
},
{'name': 'Proprietary RPGs',
'parent_id': cls.article_headers[1].id,
},
{'internal_permission': 'none',
'name': 'Secret RPGs',
'parent_id': cls.article_headers[1].id,
},
])
cls.article_read_contents_children = cls.env['knowledge.article'].create([
{'name': 'Child of Secret RPGs',
'parent_id': cls.article_read_contents[3].id,
},
])
cls.article_read_desync = cls.env['knowledge.article'].create([
# Read/TTRPG: Open Cthulhu
{'article_member_ids': [
(0, 0, {'partner_id': cls.partner_employee.id,
'permission': 'write',
}),
(0, 0, {'partner_id': cls.partner_employee_manager.id,
'permission': 'read',
}),
],
'internal_permission': 'none',
'is_desynchronized': True,
'name': 'Mansions of Terror',
'parent_id': cls.article_read_contents[0].id,
},
])
cls.article_read_desync += cls.env['knowledge.article'].create([
{'name': 'Childof Desync Mansions',
'parent_id': cls.article_read_desync[0].id,
},
])
cls.articles_all = cls.article_roots + cls.article_headers + \
cls.article_write_contents + cls.article_write_contents_children + \
cls.article_read_contents + cls.article_read_contents_children + \
cls.article_write_desync + cls.article_read_desync
cls.env.flush_all()