[IMP] mail: add message_partner inverse on threads

This change allows for adding and removing followers from threads
by directly setting the message_partner_ids field of threads.

This enables the use of many2many_tags to add followers to a thread.

Task-2804888

closes odoo/odoo#95645

Related: odoo/enterprise#29284
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Renaud Thiry
2022-09-14 21:21:09 +02:00
committed by Thibault Delavallée
parent f05adbc8b5
commit bcce093ed3
2 changed files with 72 additions and 0 deletions
+12
View File
@@ -85,6 +85,7 @@ class MailThread(models.AbstractModel):
message_partner_ids = fields.Many2many(
comodel_name='res.partner', string='Followers (Partners)',
compute='_compute_message_partner_ids',
inverse='_inverse_message_partner_ids',
search='_search_message_partner_ids',
groups='base.group_user')
message_ids = fields.One2many(
@@ -113,6 +114,17 @@ class MailThread(models.AbstractModel):
for thread in self:
thread.message_partner_ids = thread.message_follower_ids.mapped('partner_id')
def _inverse_message_partner_ids(self):
for thread in self:
new_partners_ids = thread.message_partner_ids
previous_partners_ids = thread.message_follower_ids.partner_id
removed_partners_ids = previous_partners_ids - new_partners_ids
added_patners_ids = new_partners_ids - previous_partners_ids
if added_patners_ids:
thread.message_subscribe(added_patners_ids.ids)
if removed_partners_ids:
thread.message_unsubscribe(removed_partners_ids.ids)
@api.model
def _search_message_partner_ids(self, operator, operand):
"""Search function for message_follower_ids
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail.tests.common import TestMailCommon
from odoo.exceptions import AccessError
from odoo.tests import tagged
from odoo.tests import users
@@ -143,6 +144,65 @@ class BaseFollowersTest(TestMailCommon):
self.assertEqual(document.message_partner_ids, self.partner_portal, 'No active test: customer not visible')
self.assertEqual(document.message_follower_ids.partner_id, self.partner_portal | customer)
@users('employee')
def test_followers_inverse_message_partner(self):
test_record = self.test_record.with_env(self.env)
partner0, partner1, partner2, partner3 = self.env['res.partner'].create(
[{'email': f'partner.{n}@test.lan', 'name': f'partner{n}'} for n in range(4)]
)
self.assertFalse(test_record.message_follower_ids)
self.assertFalse(test_record.message_partner_ids)
# fillup with API
test_record.message_subscribe(partner_ids=partner3.ids)
self.assertEqual(test_record.message_follower_ids.partner_id, partner3)
# set empty
test_record.message_partner_ids = None
self.assertFalse(test_record.message_follower_ids.partner_id)
# set 1
test_record.message_partner_ids = partner0
self.assertEqual(test_record.message_follower_ids.partner_id, partner0)
# set multiple when non-empty
test_record.message_partner_ids = partner1 + partner2
self.assertEqual(test_record.message_follower_ids.partner_id, partner1 + partner2)
# remove 1
test_record.message_partner_ids -= partner1
self.assertEqual(test_record.message_follower_ids.partner_id, partner2)
# add multiple with one already set
test_record.message_partner_ids += partner1 + partner2
self.assertEqual(test_record.message_follower_ids.partner_id, partner1 + partner2)
# remove outside of existing
test_record.message_partner_ids -= partner3
self.assertEqual(test_record.message_follower_ids.partner_id, partner1 + partner2)
# reset
test_record.message_partner_ids = False
self.assertFalse(test_record.message_follower_ids.partner_id)
# test with inactive and commands
partner0.write({'active': False})
test_record.write({'message_partner_ids': [(4, partner0.id), (4, partner1.id)]})
self.assertEqual(test_record.message_follower_ids.partner_id, partner1)
def test_followers_inverse_message_partner_access_rights(self):
""" Make sure we're not bypassing security checks by setting a partner
instead of a follower """
test_record = self.test_record.with_user(self.user_portal)
partner0 = self.env['res.partner'].create({
'email': 'partner1@test.lan',
'name': 'partner1',
})
_name = test_record.name # check portal user can read
# set empty
with self.assertRaises(AccessError):
test_record.message_partner_ids = None
# set 1
with self.assertRaises(AccessError):
test_record.message_partner_ids = partner0
# remove 1
with self.assertRaises(AccessError):
test_record.message_partner_ids -= partner0
@users('employee')
def test_followers_private_address(self):
""" Test standard API does not subscribe private addresses """