diff options
| author | Mathieu Duckaerts-Antoine <dam@odoo.com> | 2018-05-24 15:27:28 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2018-06-06 16:01:33 +0200 |
| commit | 299ebb2cdf63de2e3967da0d2f3e7effd239812b (patch) | |
| tree | f2681c0fc1e283acdfd5942392db8f17ddc7801d /addons/test_mail/tests/test_mail_message.py | |
| parent | eeab18d753db21bca0636836c40df91268549390 (diff) | |
[IMP] mail: add moderation on channels
Purpose of this commit is to allow moderation on incoming messages in
discussion channels. On some channels on which moderation is required
messages should be in a pending moderation stage. Moderators can accept
or refuse messages as well as always allow or ban messages coming from
a given set of emails.
Channels now have an option to be moderated. Moderators can be added on
channels. They have access to a specific UI in Discuss to see and take
action on messages waiting for moderation.
Concerning mail.thread message that are pending moderation are not notified.
It means nobody receives a notification about them. Moderation process calls
the notification once the message is validated.
Various features included in this commit :
* a model is added to store the decision about emails, allow or ban;
* access rights are updated so that only moderators can modify moderation
fields on message;
* specific bus notifications are send to moderated people as well as to
moderators on incoming emails as well as when a decision is taken;
* options are added on channels to send explanations to moderated emails;
* options are added on channels to write and send guidelines explaining
why and how moderation is performed;
* a reminder is send daily to moderators with remaining messages to moderate;
* discuss UI is adapted and a new channel is added below Inbox and Starred
giving access to moderation tools;
* chanenl UI is adapted allowing to moderate directly inside channels;
This commit is linked to task ID 29521. Closes #21921.
Diffstat (limited to 'addons/test_mail/tests/test_mail_message.py')
| -rw-r--r-- | addons/test_mail/tests/test_mail_message.py | 105 |
1 files changed, 104 insertions, 1 deletions
diff --git a/addons/test_mail/tests/test_mail_message.py b/addons/test_mail/tests/test_mail_message.py index 5d747e0a207..94540272b4e 100644 --- a/addons/test_mail/tests/test_mail_message.py +++ b/addons/test_mail/tests/test_mail_message.py @@ -5,6 +5,7 @@ import base64 from odoo.addons.test_mail.tests import common from odoo.exceptions import AccessError, except_orm from odoo.tools import mute_logger +from odoo.tests import tagged class TestMessageValues(common.BaseFunctionalTest, common.MockEmails): @@ -213,6 +214,10 @@ class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails): messages = self.env['mail.message'].sudo(self.user_portal).search([('subject', 'like', '_ZTest')]) self.assertEqual(messages, msg4 | msg5) + # -------------------------------------------------- + # READ + # -------------------------------------------------- + @mute_logger('odoo.addons.base.models.ir_model', 'odoo.models') def test_mail_message_access_read_crash(self): # TODO: Change the except_orm to Warning ( Because here it's call check_access_rule @@ -251,6 +256,16 @@ class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails): # Test: Bert reads the message, ok because linked to a doc he is allowed to read self.message.sudo(self.user_employee).read() + def test_mail_message_access_read_crash_moderation(self): + # with self.assertRaises(AccessError): + self.message.write({'model': 'mail.channel', 'res_id': self.group_public.id, 'moderation_status': 'pending_moderation'}) + # Test: Bert reads the message, ok because linked to a doc he is allowed to read + self.message.sudo(self.user_employee).read() + + # -------------------------------------------------- + # CREATE + # -------------------------------------------------- + @mute_logger('odoo.addons.base.models.ir_model') def test_mail_message_access_create_crash_public(self): # Do: Bert creates a message on Pigs -> ko, no creation rights @@ -284,6 +299,25 @@ class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails): self.message.write({'partner_ids': [(4, self.user_employee.partner_id.id)]}) self.env['mail.message'].sudo(self.user_employee).create({'model': 'mail.channel', 'res_id': self.group_private.id, 'body': 'Test', 'parent_id': self.message.id}) + # -------------------------------------------------- + # WRITE + # -------------------------------------------------- + + def test_mail_message_access_write_moderation(self): + """ Only moderators can modify pending messages """ + self.group_public.write({ + 'email_send': True, + 'moderation': True, + 'channel_partner_ids': [(4, self.partner_employee.id)], + 'moderator_ids': [(4, self.user_employee.id)], + }) + self.message.write({'model': 'mail.channel', 'res_id': self.group_public.id, 'moderation_status': 'pending_moderation'}) + self.message.sudo(self.user_employee).write({'moderation_status': 'accepted'}) + + def test_mail_message_access_write_crash_moderation(self): + self.message.write({'model': 'mail.channel', 'res_id': self.group_public.id, 'moderation_status': 'pending_moderation'}) + with self.assertRaises(AccessError): + self.message.sudo(self.user_employee).write({'moderation_status': 'accepted'}) @mute_logger('openerp.addons.mail.models.mail_mail') def test_mark_all_as_read(self): @@ -350,4 +384,73 @@ class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails): portal_partner.env['mail.message'].mark_all_as_read(channel_ids=[], domain=[]) na_count = portal_partner.get_needaction_count() - self.assertEqual(na_count, 0, "mark all read should conclude all needactions even inacessible ones")
\ No newline at end of file + self.assertEqual(na_count, 0, "mark all read should conclude all needactions even inacessible ones") + + +@tagged('moderation') +class TestMessageModeration(common.Moderation): + + @classmethod + def setUpClass(cls): + super(TestMessageModeration, cls).setUpClass() + + cls.msg_admin_pending_c1 = cls._create_new_message(cls, cls.channel_1.id, status='pending_moderation', author=cls.partner_admin) + cls.msg_admin_pending_c1_2 = cls._create_new_message(cls, cls.channel_1.id, status='pending_moderation', author=cls.partner_admin) + cls.msg_emp2_pending_c1 = cls._create_new_message(cls, cls.channel_1.id, status='pending_moderation', author=cls.partner_employee_2) + + @mute_logger('odoo.models.unlink') + def test_moderate_accept(self): + self._clear_bus() + # A pending moderation message needs to have field channel_ids empty. Moderators + # need to be able to notify a pending moderation message (in a channel they moderate). + self.assertFalse(self.msg_admin_pending_c1.channel_ids) + self.msg_admin_pending_c1.sudo(self.user_employee)._moderate('accept') + self.assertEqual(self.msg_admin_pending_c1.channel_ids, self.channel_1) + self.assertEqual(self.msg_admin_pending_c1.moderation_status, 'accepted') + self.assertEqual(self.msg_admin_pending_c1_2.moderation_status, 'pending_moderation') + self.assertBusNotification([(self.cr.dbname, 'mail.channel', self.channel_1.id)]) + + @mute_logger('odoo.models.unlink') + def test_moderate_allow(self): + self._clear_bus() + # A pending moderation message needs to have field channel_ids empty. Moderators + # need to be able to notify a pending moderation message (in a channel they moderate). + self.assertFalse(self.msg_admin_pending_c1.channel_ids) + self.assertFalse(self.msg_admin_pending_c1_2.channel_ids) + self.msg_admin_pending_c1.sudo(self.user_employee)._moderate('allow') + self.assertEqual(self.msg_admin_pending_c1.channel_ids, self.channel_1) + self.assertEqual(self.msg_admin_pending_c1_2.channel_ids, self.channel_1) + self.assertEqual(self.msg_admin_pending_c1.moderation_status, 'accepted') + self.assertEqual(self.msg_admin_pending_c1_2.moderation_status, 'accepted') + self.assertBusNotification([ + (self.cr.dbname, 'mail.channel', self.channel_1.id), + (self.cr.dbname, 'mail.channel', self.channel_1.id)]) + + @mute_logger('odoo.models.unlink') + def test_moderate_reject(self): + self._init_mock_build_email() + (self.msg_admin_pending_c1 | self.msg_emp2_pending_c1).sudo(self.user_employee)._moderate_send_reject_email('Title', 'Message to author') + self.env['mail.mail'].process_email_queue() + self.assertEmails(self.partner_employee, self.partner_employee_2 | self.partner_admin, subject='Title', body_content='Message to author') + + def test_moderate_discard(self): + self._clear_bus() + id1, id2 = self.msg_admin_pending_c1.id, self.msg_emp2_pending_c1.id # save ids because unlink will discard them + (self.msg_admin_pending_c1 | self.msg_emp2_pending_c1).sudo(self.user_employee)._moderate_discard() + + self.assertBusNotification( + [(self.cr.dbname, 'res.partner', self.partner_admin.id), + (self.cr.dbname, 'res.partner', self.partner_employee_2.id), + (self.cr.dbname, 'res.partner', self.partner_employee.id)], + [{'type': 'deletion', 'message_ids': [id1]}, # admin: one message deleted because discarded + {'type': 'deletion', 'message_ids': [id2]}, # employee_2: one message delete because discarded + {'type': 'deletion', 'message_ids': [id1, id2]}] # employee: two messages deleted because moderation done + ) + + @mute_logger('odoo.models.unlink') + def test_notify_moderators(self): + # create pending messages in another channel to have two notification to push + msg_emp_pending_c2 = self._create_new_message(self.channel_2.id, status='pending_moderation', author=self.partner_employee) + + self.env['mail.message']._notify_moderators() + self.assertEmails(False, self.partner_employee | self.partner_employee_2, subject='Message are pending moderation', email_from=self.env.user.company_id.catchall or self.env.user.company_id.email) |
