Files
odoo_source/addons/test_mail/tests/test_mail_channel.py
T
Thibault Delavallée e2b33f460d [REF] mail, various: rename subtype parameter of message_post to subtype_xmlid
PURPOSE

Clean posting process and improve mail.message definition and comprehension.

SPECIFICATIONS

In order to be more explicit subtype parameter is renamed to subtype_xmlid.
It therefore clearly indicates it should be a valid subtype Xml ID. Support
of ill formatted Xml IDs is removed because there is no reason to try to
add some random prefix. Give something that exists or go to hell, punk !

LINKS

Task ID 2071556
PR #38692
2019-12-02 15:18:44 +00:00

367 lines
18 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import tagged
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.test_mail.tests.common import TestMailCommon
from odoo.exceptions import AccessError, except_orm, ValidationError, UserError
from odoo.tools import mute_logger, formataddr
class TestChannelAccessRights(TestMailCommon):
@classmethod
def setUpClass(cls):
super(TestChannelAccessRights, cls).setUpClass()
Channel = cls.env['mail.channel'].with_context(cls._test_context)
cls.user_public = mail_new_test_user(cls.env, login='bert', groups='base.group_public', name='Bert Tartignole')
cls.user_portal = mail_new_test_user(cls.env, login='chell', groups='base.group_portal', name='Chell Gladys')
# Pigs: base group for tests
cls.group_pigs = Channel.create({
'name': 'Pigs',
'public': 'groups',
'group_public_id': cls.env.ref('base.group_user').id})
# Jobs: public group
cls.group_public = Channel.create({
'name': 'Jobs',
'description': 'NotFalse',
'public': 'public'})
# Private: private group
cls.group_private = Channel.create({
'name': 'Private',
'public': 'private'})
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_access_rights_public(self):
# Read public group -> ok
self.group_public.with_user(self.user_public).read()
# Read Pigs -> ko, restricted to employees
# TODO: Change the except_orm to Warning ( Because here it's call check_access_rule
# which still generate exception in except_orm.So we need to change all
# except_orm to warning in mail module.)
with self.assertRaises(except_orm):
self.group_pigs.with_user(self.user_public).read()
# Read a private group when being a member: ok
self.group_private.write({'channel_partner_ids': [(4, self.user_public.partner_id.id)]})
self.group_private.with_user(self.user_public).read()
# Create group: ko, no access rights
with self.assertRaises(AccessError):
self.env['mail.channel'].with_user(self.user_public).create({'name': 'Test'})
# Update group: ko, no access rights
with self.assertRaises(AccessError):
self.group_public.with_user(self.user_public).write({'name': 'Broutouschnouk'})
# Unlink group: ko, no access rights
with self.assertRaises(AccessError):
self.group_public.with_user(self.user_public).unlink()
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models', 'odoo.models.unlink')
def test_access_rights_groups(self):
# Employee read employee-based group: ok
# TODO Change the except_orm to Warning
self.group_pigs.with_user(self.user_employee).read()
# Employee can create a group
self.env['mail.channel'].with_user(self.user_employee).create({'name': 'Test'})
# Employee update employee-based group: ok
self.group_pigs.with_user(self.user_employee).write({'name': 'modified'})
# Employee unlink employee-based group: ok
self.group_pigs.with_user(self.user_employee).unlink()
# Employee cannot read a private group
with self.assertRaises(except_orm):
self.group_private.with_user(self.user_employee).read()
# Employee cannot write on private
with self.assertRaises(AccessError):
self.group_private.with_user(self.user_employee).write({'name': 're-modified'})
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_access_rights_followers_ko(self):
# self.group_private.name has been put in the cache during the setup as sudo
# It must therefore be removed from the cache in other to validate the fact user_portal can't read it.
self.group_private.invalidate_cache(['name'])
with self.assertRaises(AccessError):
self.group_private.with_user(self.user_portal).name
def test_access_rights_followers_portal(self):
# Do: Chell is added into Pigs members and browse it -> ok for messages, ko for partners (no read permission)
self.group_private.write({'channel_partner_ids': [(4, self.user_portal.partner_id.id)]})
chell_pigs = self.group_private.with_user(self.user_portal)
trigger_read = chell_pigs.name
for message in chell_pigs.message_ids:
trigger_read = message.subject
for partner in chell_pigs.message_partner_ids:
if partner.id == self.user_portal.partner_id.id:
# Chell can read her own partner record
continue
# TODO Change the except_orm to Warning
with self.assertRaises(except_orm):
trigger_read = partner.name
class TestChannelFeatures(TestMailCommon):
@classmethod
def setUpClass(cls):
super(TestChannelFeatures, cls).setUpClass()
cls.test_channel = cls.env['mail.channel'].with_context(cls._test_context).create({
'name': 'Test',
'description': 'Description',
'alias_name': 'test',
'public': 'public',
})
cls.test_partner = cls.env['res.partner'].with_context(cls._test_context).create({
'name': 'Test Partner',
'email': 'test@example.com',
})
def _join_channel(self, channel, partners):
for partner in partners:
channel.write({'channel_last_seen_partner_ids': [(0, 0, {'partner_id': partner.id})]})
channel.invalidate_cache()
def _leave_channel(self, channel, partners):
for partner in partners:
channel._action_unfollow(partner)
def test_channel_listeners(self):
self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
self.assertEqual(self.test_channel.channel_partner_ids, self.env['res.partner'])
self._join_channel(self.test_channel, self.test_partner)
self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
self.assertEqual(self.test_channel.channel_partner_ids, self.test_partner)
self._leave_channel(self.test_channel, self.test_partner)
self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
self.assertEqual(self.test_channel.channel_partner_ids, self.env['res.partner'])
def test_channel_post_nofollow(self):
self.test_channel.message_post(body='Test', message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertEqual(self.test_channel.message_channel_ids, self.test_channel)
self.assertEqual(self.test_channel.message_partner_ids, self.env['res.partner'])
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
def test_channel_mailing_list_recipients(self):
""" Posting a message on a mailing list should send one email to all recipients """
self.env['ir.config_parameter'].set_param('mail.catchall.domain', 'schlouby.fr')
self.test_channel.write({'email_send': True})
# Subscribe an user without email. We shouldn't try to send email to them.
nomail = self.env['res.users'].create({
"login": "nomail",
"name": "No Mail",
"email": False,
"notification_type": "email",
})
self._join_channel(self.test_channel, self.user_employee.partner_id | self.test_partner | nomail.partner_id)
with self.mock_mail_gateway():
self.test_channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertSentEmail(self.test_channel.env.user.partner_id, [self.partner_employee, self.test_partner])
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
def test_channel_chat_recipients(self):
""" Posting a message on a chat should not send emails """
self.env['ir.config_parameter'].set_param('mail.catchall.domain', 'schlouby.fr')
self.test_channel.write({'email_send': False})
self._join_channel(self.test_channel, self.user_employee.partner_id | self.test_partner)
with self.mock_mail_gateway():
self.test_channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertNotSentEmail()
self.assertEqual(len(self._mails), 0)
@mute_logger('odoo.addons.mail.models.mail_mail', 'odoo.models.unlink')
def test_channel_classic_recipients(self):
""" Posting a message on a classic channel should work like classic post """
self.test_channel.write({'alias_name': False})
self.test_channel.message_subscribe([self.user_employee.partner_id.id, self.test_partner.id])
with self.mock_mail_gateway():
self.test_channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertSentEmail(self.test_channel.env.user.partner_id, [self.test_partner])
@mute_logger('odoo.addons.mail.models.mail_mail')
def test_channel_out_of_office(self):
self.user_employee.out_of_office_message = 'Out'
test_chat = self.env['mail.channel'].with_context(self._test_context).create({
'channel_partner_ids': [(4, self.user_employee.partner_id.id), (4, self.user_admin.partner_id.id)],
'public': 'private',
'channel_type': 'chat',
'email_send': False,
'name': 'test'
})
infos = test_chat.with_user(self.user_admin).channel_info()
self.assertEqual(infos[0]['direct_partner'][0]['out_of_office_message'], 'Out')
@tagged('moderation')
class TestChannelModeration(TestMailCommon):
@classmethod
def setUpClass(cls):
super(TestChannelModeration, cls).setUpClass()
cls.channel_1 = cls.env['mail.channel'].create({
'name': 'Moderation_1',
'email_send': True,
'moderation': True,
'channel_partner_ids': [(4, cls.partner_employee.id)],
'moderator_ids': [(4, cls.user_employee.id)],
})
cls.user_portal = cls._create_portal_user()
def test_moderator_consistency(self):
# moderators should be channel members
with self.assertRaises(ValidationError):
self.channel_1.write({'moderator_ids': [(4, self.user_admin.id)]})
# member -> moderator or
self.channel_1.write({'channel_partner_ids': [(4, self.partner_admin.id)]})
self.channel_1.write({'moderator_ids': [(4, self.user_admin.id)]})
# member -> moderator ko if no email
self.channel_1.write({'moderator_ids': [(3, self.partner_admin.id)]})
self.user_admin.write({'email': False})
with self.assertRaises(ValidationError):
self.channel_1.write({'moderator_ids': [(4, self.user_admin.id)]})
def test_moderation_consistency(self):
# moderation enabled channels are restricted to mailing lists
with self.assertRaises(ValidationError):
self.channel_1.write({'email_send': False})
# moderation enabled channels should always have moderators
with self.assertRaises(ValidationError):
self.channel_1.write({'moderator_ids': [(5, 0)]})
def test_moderation_count(self):
self.assertEqual(self.channel_1.moderation_count, 0)
self.channel_1.write({'moderation_ids': [
(0, 0, {'email': 'test0@example.com', 'status': 'allow'}),
(0, 0, {'email': 'test1@example.com', 'status': 'ban'})
]})
self.assertEqual(self.channel_1.moderation_count, 2)
@mute_logger('odoo.addons.mail.models.mail_channel', 'odoo.models.unlink')
def test_send_guidelines(self):
self.channel_1.write({'channel_partner_ids': [(4, self.partner_portal.id), (4, self.partner_admin.id)]})
self.channel_1._update_moderation_email([self.partner_admin.email], 'ban')
with self.mock_mail_gateway():
self.channel_1.with_user(self.user_employee).send_guidelines()
for mail in self._new_mails:
self.assertEqual(mail.author_id, self.partner_employee)
self.assertEqual(mail.subject, 'Guidelines of channel %s' % self.channel_1.name)
self.assertEqual(mail.state, 'outgoing')
self.assertEqual(mail.email_from, self.user_employee.company_id.catchall_formatted)
self.assertEqual(self._new_mails.mapped('recipient_ids'), self.partner_employee | self.partner_portal)
def test_send_guidelines_crash(self):
self.channel_1.write({
'channel_partner_ids': [(4, self.partner_admin.id)],
'moderator_ids': [(4, self.user_admin.id), (3, self.user_employee.id)]
})
with self.assertRaises(UserError):
self.channel_1.with_user(self.user_employee).send_guidelines()
def test_update_moderation_email(self):
self.channel_1.write({'moderation_ids': [
(0, 0, {'email': 'test0@example.com', 'status': 'allow'}),
(0, 0, {'email': 'test1@example.com', 'status': 'ban'})
]})
self.channel_1._update_moderation_email(['test0@example.com', 'test3@example.com'], 'ban')
self.assertEqual(len(self.channel_1.moderation_ids), 3)
self.assertTrue(all(status == 'ban' for status in self.channel_1.moderation_ids.mapped('status')))
def test_moderation_reset(self):
self.channel_2 = self.env['mail.channel'].create({
'name': 'Moderation_1',
'email_send': True,
'moderation': True,
'channel_partner_ids': [(4, self.partner_employee.id)],
'moderator_ids': [(4, self.user_employee.id)],
})
self.msg_c1_1 = self._add_messages(self.channel_1, 'Body11', author=self.partner_admin, moderation_status='accepted')
self.msg_c1_2 = self._add_messages(self.channel_1, 'Body12', author=self.partner_admin, moderation_status='pending_moderation')
self.msg_c2_1 = self._add_messages(self.channel_2, 'Body21', author=self.partner_admin, moderation_status='pending_moderation')
self.assertEqual(self.env['mail.message'].search_count([
('moderation_status', '=', 'pending_moderation'),
('model', '=', 'mail.channel'), ('res_id', '=', self.channel_1.id)
]), 1)
self.channel_1.write({'moderation': False})
self.assertEqual(self.env['mail.message'].search_count([
('moderation_status', '=', 'pending_moderation'),
('model', '=', 'mail.channel'), ('res_id', '=', self.channel_1.id)
]), 0)
self.assertEqual(self.env['mail.message'].search_count([
('moderation_status', '=', 'pending_moderation'),
('model', '=', 'mail.channel'), ('res_id', '=', self.channel_2.id)
]), 1)
self.channel_2.write({'moderation': False})
self.assertEqual(self.env['mail.message'].search_count([
('moderation_status', '=', 'pending_moderation'),
('model', '=', 'mail.channel'), ('res_id', '=', self.channel_2.id)
]), 0)
@mute_logger('odoo.models.unlink')
def test_message_post(self):
email1 = 'test0@example.com'
email2 = 'test1@example.com'
self.channel_1._update_moderation_email([email1], 'ban')
self.channel_1._update_moderation_email([email2], 'allow')
msg_admin = self.channel_1.message_post(message_type='email', subtype_xmlid='mail.mt_comment', author_id=self.partner_admin.id)
msg_moderator = self.channel_1.message_post(message_type='comment', subtype_xmlid='mail.mt_comment', author_id=self.partner_employee.id)
msg_email1 = self.channel_1.message_post(message_type='comment', subtype_xmlid='mail.mt_comment', email_from=formataddr(("MyName", email1)))
msg_email2 = self.channel_1.message_post(message_type='email', subtype_xmlid='mail.mt_comment', email_from=email2)
msg_notif = self.channel_1.message_post()
messages = self.env['mail.message'].search([('model', '=', 'mail.channel'), ('res_id', '=', self.channel_1.id)])
pending_messages = messages.filtered(lambda m: m.moderation_status == 'pending_moderation')
accepted_messages = messages.filtered(lambda m: m.moderation_status == 'accepted')
self.assertFalse(msg_email1)
self.assertEqual(msg_admin, pending_messages)
self.assertEqual(accepted_messages, msg_moderator | msg_email2 | msg_notif)
self.assertFalse(msg_admin.channel_ids)
self.assertEqual(msg_email2.channel_ids, self.channel_1)
def test_user_is_moderator(self):
self.assertTrue(self.user_employee.is_moderator)
self.assertFalse(self.user_admin.is_moderator)
self.channel_1.write({
'channel_partner_ids': [(4, self.partner_admin.id)],
'moderator_ids': [(4, self.user_admin.id)],
})
self.assertTrue(self.user_admin.is_moderator)
def test_user_moderation_counter(self):
self._add_messages(self.channel_1, 'B', moderation_status='pending_moderation', author=self.partner_admin)
self._add_messages(self.channel_1, 'B', moderation_status='accepted', author=self.partner_admin)
self._add_messages(self.channel_1, 'B', moderation_status='accepted', author=self.partner_employee)
self._add_messages(self.channel_1, 'B', moderation_status='pending_moderation', author=self.partner_employee)
self._add_messages(self.channel_1, 'B', moderation_status='accepted', author=self.partner_employee)
self.assertEqual(self.user_employee.moderation_counter, 2)
self.assertEqual(self.user_admin.moderation_counter, 0)
self.channel_1.write({
'channel_partner_ids': [(4, self.partner_admin.id)],
'moderator_ids': [(4, self.user_admin.id)]
})
self.assertEqual(self.user_employee.moderation_counter, 2)
self.assertEqual(self.user_admin.moderation_counter, 0)