[FW][FIX] knowledge: correctly handle desync status when detaching children
This commit fixes the case when we have desynchronized children for which the current user does not have write access and we move the parent to the private section (or archive the parent). In that case, children that are desynchronized should not have the members from their parents copied onto them when detaching. See '_detach_unwritable_descendants' and associated tests for more details. Task-2859616 X-original-commit: odoo/odoo@348740fa9f Part-of: odoo/odoo#95471
This commit is contained in:
committed by
Thibault Delavallée
parent
57d04db7e1
commit
48b99e2f0c
@@ -1156,6 +1156,10 @@ class Article(models.Model):
|
||||
This method takes care of correctly detaching those children and returns
|
||||
a subset of children to which the user effectively has write access to.
|
||||
|
||||
As the children are moved to "root" articles we also reset their desync
|
||||
status. Indeed, a root article cannot be desyncronized as stated by SQL
|
||||
constraints.
|
||||
|
||||
Note: this might produce funny results when involving a hierarchy with
|
||||
invisible nodes in it (A-B-C where B is not achievable). You might
|
||||
archive / privatize articles and break hierarchy without knowing it.
|
||||
@@ -1167,18 +1171,23 @@ class Article(models.Model):
|
||||
other_descendants_sudo = all_descendants_sudo - writable_descendants
|
||||
|
||||
# copy rights to allow breaking the hierarchy while keeping access for members
|
||||
for article_sudo in other_descendants_sudo:
|
||||
# do this on synchronized articles as desynchronized one do not inherit from parent
|
||||
for article_sudo in other_descendants_sudo.filtered(lambda article: not article.is_desynchronized):
|
||||
article_sudo.write({
|
||||
'article_member_ids': article_sudo._copy_access_from_parents_commands()
|
||||
})
|
||||
|
||||
# create new root articles: direct children of these articles
|
||||
# create new root articles: direct children of these articles, reset desync
|
||||
new_roots_woperm = other_descendants_sudo.filtered(lambda article: article.parent_id in self and not article.internal_permission)
|
||||
new_roots_wperm = other_descendants_sudo.filtered(lambda article: article.parent_id in self and article.internal_permission)
|
||||
if new_roots_wperm:
|
||||
new_roots_wperm.write({'parent_id': False})
|
||||
new_roots_wperm.write({
|
||||
'is_desynchronized': False,
|
||||
'parent_id': False
|
||||
})
|
||||
for new_root in new_roots_woperm:
|
||||
new_root.write({
|
||||
'is_desynchronized': False,
|
||||
'internal_permission': new_root.inherited_permission,
|
||||
'parent_id': False,
|
||||
})
|
||||
|
||||
@@ -607,6 +607,78 @@ class TestKnowledgeArticleBusiness(KnowledgeCommonWData):
|
||||
wkspace_child_no_access.with_env(self.env).body
|
||||
wkspace_child_no_access.with_user(self.user_employee2).body
|
||||
|
||||
@mute_logger('odoo.addons.base.models.ir_rule', 'odoo.models.unlink')
|
||||
@users('employee')
|
||||
def test_article_make_private_w_desynchronized(self):
|
||||
""" Test a special case when making private: we have desynchronized children.
|
||||
Children that are de-synchronized should NOT have members from their parent(s)
|
||||
copied onto them when they are detached.
|
||||
|
||||
Specific setup for this test
|
||||
# - Playground workspace w+ (customer-r+,employee-w+)
|
||||
# - Child1 " w+DES (customer-r+,employee-r+)
|
||||
# - Gd Child1 " "
|
||||
# - Gd Child2 " "
|
||||
# - GdGd Child1 " "
|
||||
# - Child2 " "
|
||||
# - Gd Child1 " "
|
||||
# - GdGd Child " "
|
||||
"""
|
||||
# add employee on playground and desynchronize its child
|
||||
self.article_workspace._add_members(self.partner_employee, 'write')
|
||||
self.workspace_children[0]._set_member_permission(
|
||||
self.article_workspace.article_member_ids.filtered(
|
||||
lambda member: member.partner_id == self.partner_employee
|
||||
),
|
||||
'read',
|
||||
is_based_on=True,
|
||||
)
|
||||
# check updated data
|
||||
self.assertTrue(self.workspace_children[0].is_desynchronized)
|
||||
self.assertMembers(
|
||||
self.article_workspace,
|
||||
'write',
|
||||
{self.partner_employee: 'write'}
|
||||
)
|
||||
self.assertMembers(
|
||||
self.workspace_children[0],
|
||||
'write',
|
||||
{self.partner_employee: 'read'}
|
||||
)
|
||||
|
||||
article_workspace = self.article_workspace.with_env(self.env)
|
||||
[workspace_child_desync, workspace_child_tosync] = self.workspace_children.with_env(self.env)
|
||||
|
||||
# add a member on the parent, it will NOT be propagated to the desync child
|
||||
article_workspace._add_members(self.customer, 'read')
|
||||
self.assertMembers(
|
||||
article_workspace,
|
||||
'write',
|
||||
{self.customer: 'read', self.partner_employee: 'write'}
|
||||
)
|
||||
|
||||
# now move the article to private and check the post-processing
|
||||
article_workspace._move_and_make_private()
|
||||
|
||||
# 1. desync article: moved to root (as employee does not have write access)
|
||||
# and is not desynchronized (root articles are never desynchornized)
|
||||
# should be moved to root (as employee does not have write access)
|
||||
self.assertEqual(workspace_child_desync.category, "workspace")
|
||||
self.assertFalse(workspace_child_desync.is_desynchronized)
|
||||
self.assertFalse(workspace_child_desync.parent_id)
|
||||
# it should NOT have had customer access copied onto it as it was desync when we moved it
|
||||
self.assertMembers(
|
||||
workspace_child_desync,
|
||||
"write",
|
||||
{self.partner_employee: 'read'}
|
||||
)
|
||||
|
||||
# 2. sync article: NOT moved to root (as employee has write access) and is
|
||||
# still sunchronized
|
||||
self.assertEqual(workspace_child_tosync.category, "private")
|
||||
self.assertFalse(workspace_child_desync.is_desynchronized)
|
||||
self.assertEqual(workspace_child_tosync.parent_id, article_workspace)
|
||||
|
||||
@mute_logger('odoo.addons.base.models.ir_rule', 'odoo.models.unlink')
|
||||
@users('employee_manager')
|
||||
def test_article_make_private_w_parent(self):
|
||||
|
||||
Reference in New Issue
Block a user