Odoo18-Base/addons/mail_group/tests/test_mail_group_moderation.py
2025-01-06 10:57:38 +07:00

416 lines
20 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from psycopg2 import IntegrityError
from odoo import Command, tools
from odoo.addons.mail_group.tests.data import GROUP_TEMPLATE
from odoo.addons.mail_group.tests.common import TestMailListCommon
from odoo.exceptions import AccessError
from odoo.tests.common import tagged, users
from odoo.tools import mute_logger
@tagged('mail_group_moderation')
class TestMailGroupModeration(TestMailListCommon):
@classmethod
def setUpClass(cls):
super(TestMailGroupModeration, cls).setUpClass()
cls.test_group_2 = cls.env['mail.group'].create({
'access_mode': 'members',
'alias_name': 'test.mail.group.2',
'moderation': True,
'moderator_ids': [Command.link(cls.user_employee.id)],
'name': 'Test group 2',
})
@mute_logger('odoo.sql_db')
@users('employee')
def test_constraints(self):
mail_group = self.env['mail.group'].browse(self.test_group.ids)
with self.assertRaises(IntegrityError):
moderation = self.env['mail.group.moderation'].create({
'mail_group_id': mail_group.id,
'email': 'banned_member@test.com',
'status': 'ban',
})
@mute_logger('odoo.models.unlink', 'odoo.addons.mail_group.models.mail_group_message')
@users('employee')
def test_moderation_rule_api(self):
""" Test moderation rule creation / update through API """
mail_group = self.env['mail.group'].browse(self.test_group.ids)
mail_group_2 = self.env['mail.group'].browse(self.test_group_2.ids)
self.assertEqual(
set(mail_group.moderation_rule_ids.mapped('email')),
set(['banned_member@test.com'])
)
moderation_1, moderation_2, moderation_3 = self.env['mail.group.moderation'].create([{
'email': 'std@test.com',
'status': 'allow',
'mail_group_id': mail_group.id,
}, {
'email': 'xss@test.com',
'status': 'ban',
'mail_group_id': mail_group.id,
}, {
'email': 'xss@test.com',
'status': 'ban',
'mail_group_id': mail_group_2.id,
}])
self.assertEqual(
set(mail_group.moderation_rule_ids.mapped('email')),
set(['banned_member@test.com', 'std@test.com', 'xss@test.com'])
)
message_1, message_2, message_3 = self.env['mail.group.message'].create([{
'email_from': '"Boum" <sTd@teST.com>',
'mail_group_id': mail_group.id,
}, {
'email_from': '"xSs" <xss@teST.com>',
'mail_group_id': mail_group.id,
}, {
'email_from': '"Bob" <bob@teST.com>',
'mail_group_id': mail_group.id,
}])
# status 'bouh' does not exist
with self.assertRaises(ValueError):
(message_1 | message_2 | message_3)._create_moderation_rule('bouh')
(message_1 | message_2 | message_3)._create_moderation_rule('allow')
self.assertEqual(len(mail_group.moderation_rule_ids), 4, "Should have created only one moderation rule")
self.assertEqual(
set(mail_group.moderation_rule_ids.mapped('email')),
set(['banned_member@test.com', 'std@test.com', 'xss@test.com', 'bob@test.com'])
)
self.assertEqual(moderation_1.status, 'allow')
self.assertEqual(moderation_2.status, 'allow', 'Should have write on the existing moderation rule')
self.assertEqual(moderation_3.status, 'ban', 'Should not have changed moderation of the other group')
new_moderation = mail_group.moderation_rule_ids.filtered(lambda rule: rule.email == 'bob@test.com')
self.assertEqual(new_moderation.status, 'allow', 'Should have created the moderation with the right status')
@users('employee')
def test_moderation_rule_email_normalize(self):
""" Test emails are automatically normalized """
rule = self.env['mail.group.moderation'].create({
'mail_group_id': self.test_group.id,
'email': '"Bob" <bob@test.com>',
'status': 'ban',
})
self.assertEqual(rule.email, 'bob@test.com')
rule.email = '"Alice" <alice@test.com>'
self.assertEqual(rule.email, 'alice@test.com')
@mute_logger('odoo.addons.base.models.ir_rule', 'odoo.addons.base.models.ir_model')
def test_moderation_rule_security(self):
with self.assertRaises(AccessError, msg='Portal should not have access to moderation rules'):
self.env['mail.group.moderation'].with_user(self.user_portal).browse(self.moderation.ids).email
self.test_group.write({
'moderator_ids': [(4, self.user_admin.id), (3, self.user_employee.id)]
})
with self.assertRaises(AccessError, msg='Non moderators should not have access to moderation rules'):
self.env['mail.group.moderation'].with_user(self.user_employee).browse(self.moderation.ids).email
self.assertEqual(
self.env['mail.group.moderation'].with_user(self.user_admin).browse(self.moderation.ids).email,
'banned_member@test.com',
msg='Moderators should have access to moderation rules')
@tagged('mail_group_moderation')
class TestModeration(TestMailListCommon):
@classmethod
def setUpClass(cls):
super(TestModeration, cls).setUpClass()
# Test group: members, moderation
cls.test_group_2 = cls.env['mail.group'].create({
'access_mode': 'members',
'alias_name': 'test.mail.group.2',
'moderation': True,
'moderator_ids': [Command.link(cls.user_employee.id)],
'name': 'Test group 2',
})
cls.test_group_2_member_emp = cls.env['mail.group.member'].create({
'partner_id': cls.user_employee_2.partner_id.id,
'email': cls.user_employee_2.email,
'mail_group_id': cls.test_group_2.id,
})
# Existing messages on group 2
cls.test_group_2_msg_1_pending = cls.env['mail.group.message'].create({
'email_from': cls.email_from_unknown,
'subject': 'Group 2 Pending',
'mail_group_id': cls.test_group_2.id,
'moderation_status': 'pending_moderation',
})
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.addons.mail_group.models.mail_group_message')
@users('employee')
def test_moderation_flow_accept(self):
""" Unknown email sends email on moderated group, test accept """
mail_group = self.env['mail.group'].browse(self.test_group.ids)
self.assertEqual(len(mail_group.mail_group_message_ids), 3)
with self.mock_mail_gateway():
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='Old email', target_model='mail.group')
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='New email', target_model='mail.group')
# find messages
self.assertEqual(len(mail_group.mail_group_message_ids), 5)
old_email_message = mail_group.mail_group_message_ids[-2]
new_email_message = mail_group.mail_group_message_ids[-1]
# check message content
self.assertEqual(old_email_message.moderation_status, 'pending_moderation')
self.assertEqual(old_email_message.subject, 'Old email')
self.assertEqual(new_email_message.moderation_status, 'pending_moderation')
self.assertEqual(new_email_message.subject, 'New email')
# accept email without any moderation rule
with self.mock_mail_gateway():
new_email_message.action_moderate_accept()
self.assertEqual(len(self._new_mails), 4)
for email in self.test_group_valid_members.mapped('email'):
self.assertMailMailWEmails([email], 'outgoing',
content="This should be posted on a mail.group. Or not.",
fields_values={
'email_from': self.email_from_unknown,
'subject': 'New email',
},
mail_message=new_email_message.mail_message_id)
self.assertEqual(new_email_message.moderation_status, 'accepted', 'Should have accepted the message')
self.assertEqual(old_email_message.moderation_status, 'pending_moderation', 'Should not have touched other message of the same author')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.addons.mail_group.models.mail_group_message', 'odoo.models.unlink')
@users('employee')
def test_moderation_flow_allow(self):
""" Unknown email sends email on moderated group, test allow """
mail_group = self.test_group
mail_group_2_as2 = self.env['mail.group'].with_user(self.user_employee_2).browse(self.test_group_2.ids)
self.assertEqual(len(mail_group.mail_group_message_ids), 3)
group_2_message_count = len(mail_group_2_as2.mail_group_message_ids)
with self.mock_mail_gateway():
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='Old email', target_model='mail.group')
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='New email', target_model='mail.group')
# find messages
self.assertEqual(len(mail_group.mail_group_message_ids), 5)
old_email_message = mail_group.mail_group_message_ids[-2]
new_email_message = mail_group.mail_group_message_ids[-1]
# check message content
self.assertEqual(old_email_message.email_from, self.email_from_unknown)
self.assertEqual(old_email_message.moderation_status, 'pending_moderation')
self.assertEqual(old_email_message.subject, 'Old email')
self.assertEqual(new_email_message.email_from, self.email_from_unknown)
self.assertEqual(new_email_message.moderation_status, 'pending_moderation')
self.assertEqual(new_email_message.subject, 'New email')
# Create a moderation rule to always accept this email address
with self.mock_mail_gateway():
new_email_message.action_moderate_allow()
self.assertEqual(new_email_message.moderation_status, 'accepted', 'Should have accepted the message')
self.assertEqual(old_email_message.moderation_status, 'accepted', 'Should have accepted the old message of the same author')
# Test that the moderation rule has been created
new_rule = self.env['mail.group.moderation'].search([
('status', '=', 'allow'),
('email', '=', tools.email_normalize(self.email_from_unknown))
])
self.assertEqual(len(new_rule), 1, 'Should have created a moderation rule')
# Check emails have been sent
self.assertEqual(len(self._new_mails), 8)
for email in self.test_group_valid_members.mapped('email'):
self.assertMailMailWEmails([email], 'outgoing',
content="This should be posted on a mail.group. Or not.",
fields_values={
'email_from': self.email_from_unknown,
'subject': 'New email',
},
mail_message=new_email_message.mail_message_id)
self.assertMailMailWEmails([email], 'outgoing',
content="This should be posted on a mail.group. Or not.",
fields_values={
'email_from': self.email_from_unknown,
'subject': 'Old email',
},
mail_message=old_email_message.mail_message_id)
# Send a second email with the same FROM, but with a different name
with self.mock_mail_gateway():
self.format_and_process(
GROUP_TEMPLATE,
tools.formataddr(("Another Name", "bob.email@test.example.com")),
self.test_group.alias_id.display_name,
subject='Another email', target_model='mail.group')
# find messages
self.assertEqual(len(mail_group.mail_group_message_ids), 6)
new_email_message = mail_group.mail_group_message_ids[-1]
self.assertEqual(new_email_message.email_from, tools.formataddr(("Another Name", "bob.email@test.example.com")))
self.assertEqual(new_email_message.moderation_status, 'accepted', msg='Should have automatically accepted the email')
self.assertEqual(new_email_message.subject, 'Another email')
self.assertEqual(
self.test_group_2_msg_1_pending.moderation_status, 'pending_moderation',
'Should not have accepted message in the other group')
self.assertEqual(
len(mail_group_2_as2.mail_group_message_ids), group_2_message_count,
'Should never have created message in the other group')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.addons.mail_group.models.mail_group_message', 'odoo.models.unlink')
@users('employee')
def test_moderation_flow_ban(self):
""" Unknown email sends email on moderated group, test ban """
mail_group = self.env['mail.group'].browse(self.test_group.ids)
self.assertEqual(len(mail_group.mail_group_message_ids), 3)
with self.mock_mail_gateway():
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='Old email', target_model='mail.group')
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='New email', target_model='mail.group')
# find messages
self.assertEqual(len(mail_group.mail_group_message_ids), 5)
old_email_message = mail_group.mail_group_message_ids[-2]
new_email_message = mail_group.mail_group_message_ids[-1]
# ban and check moderation rule has been
with self.mock_mail_gateway():
new_email_message.action_moderate_ban()
self.assertEqual(old_email_message.moderation_status, 'rejected')
self.assertEqual(new_email_message.moderation_status, 'rejected')
# Test that the moderation rule has been created
new_rule = self.env['mail.group.moderation'].search([
('status', '=', 'ban'),
('email', '=', tools.email_normalize(self.email_from_unknown))
])
self.assertEqual(len(new_rule), 1, 'Should have created a moderation rule')
# Check no mail.mail has been sent
self.assertEqual(len(self._new_mails), 0, 'Should not have send emails')
# Send a second email with the same FROM, but with a different name
with self.mock_mail_gateway():
self.format_and_process(
GROUP_TEMPLATE,
tools.formataddr(("Another Name", "bob.email@test.example.com")),
self.test_group.alias_id.display_name,
subject='Another email', target_model='mail.group')
# find messages
self.assertEqual(len(mail_group.mail_group_message_ids), 6)
new_email_message = mail_group.mail_group_message_ids[-1]
self.assertEqual(new_email_message.moderation_status, 'rejected', 'Should have automatically rejected the email')
# Check no mail.mail has been sent
self.assertEqual(len(self._new_mails), 0, 'Should not have send emails')
@mute_logger('odoo.addons.mail.models.mail_thread', 'odoo.addons.mail_group.models.mail_group_message', 'odoo.models.unlink')
@users('employee')
def test_moderation_flow_reject(self):
""" Unknown email sends email on moderated group, test reject """
mail_group = self.env['mail.group'].browse(self.test_group.ids)
self.assertEqual(len(mail_group.mail_group_message_ids), 3)
with self.mock_mail_gateway():
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='Old email', target_model='mail.group')
self.format_and_process(
GROUP_TEMPLATE, self.email_from_unknown, self.test_group.alias_id.display_name,
subject='New email', target_model='mail.group')
# find messages
self.assertEqual(len(mail_group.mail_group_message_ids), 5)
old_email_message = mail_group.mail_group_message_ids[-2]
new_email_message = mail_group.mail_group_message_ids[-1]
# reject without moderation rule
with self.mock_mail_gateway():
new_email_message.action_moderate_reject_with_comment('Test Rejected', 'Bad email')
self.assertEqual(new_email_message.moderation_status, 'rejected', 'Should have rejected the message')
self.assertEqual(old_email_message.moderation_status, 'pending_moderation', 'Should not have rejected old message')
self.assertEqual(len(self._new_mails), 1, 'Should have sent the reject email')
self.assertMailMailWEmails([self.email_from_unknown], 'outgoing',
content="This should be posted on a mail.group. Or not.",
fields_values={
'email_from': self.user_employee.email_formatted,
'subject': 'Test Rejected',
})
@mute_logger('odoo.addons.mail_group.models.mail_group')
@users('employee')
def test_moderation_send_guidelines(self):
""" Test sending guidelines """
mail_group = self.env['mail.group'].browse(self.test_group.ids)
mail_group.write({
'moderation_guidelines': True,
'moderation_guidelines_msg': 'Test guidelines group',
})
with self.mock_mail_gateway():
mail_group.action_send_guidelines()
self.assertEqual(len(self._new_mails), 3)
for email in self.test_group_valid_members.mapped('email'):
self.assertMailMailWEmails([email], 'outgoing',
content="Test guidelines group",
fields_values={
'email_from': self.env.company.email_formatted,
'subject': 'Guidelines of group %s' % mail_group.name,
})
@mute_logger('odoo.addons.mail_group.models.mail_group')
@users('employee')
def test_moderation_send_guidelines_on_new_member(self):
""" Test sending guidelines when having a new members """
mail_group = self.env['mail.group'].browse(self.test_group.ids)
mail_group.write({
'moderation_guidelines': True,
'moderation_guidelines_msg': 'Test guidelines group',
})
with self.mock_mail_gateway():
mail_group._join_group('"New Member" <new.member@test.com>')
self.assertEqual(len(self._new_mails), 1)
self.assertMailMailWEmails(['"New Member" <new.member@test.com>'], 'outgoing',
content="Test guidelines group",
fields_values={
'email_from': self.env.company.email_formatted,
'subject': 'Guidelines of group %s' % mail_group.name,
})