summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurélien Warnon <awa@odoo.com>2020-11-25 12:53:53 +0000
committerAurélien Warnon <awa@odoo.com>2020-11-30 07:55:52 +0000
commit6b6e546ac95d9acb2964121dd52aa2896d31bc33 (patch)
treefcfcf4500aac1a991fcc5b873e5be37f742f9fcf
parentdb3296c034fe4c82d19580418fd5cdecdf578395 (diff)
[FIX] mail: fix mail.mail default values collision
This commit cleans the default_* keys of the context before creating mail.mails and mail.notifications when notifying the record by email. Without this change, there can be a collision when the ORM tries to compute default values for the state field (for example): - Model "A" has a 'state' field ; - Create an action that redirects to model "A" form view, setting some default values in the context such as {'default_state': 'done'} ; - Model "A" has an inherit on 'mail.thread' and a 'user_id' field to set a responsible user ; - Model "A" record is created with a responsible user, who is automatically notified by email that the record "has been assigned to him" ; (see mail_thread#_message_auto_subscribe_notify) - A 'mail.mail' is in turn created ; - The 'mail.mail' model ALSO has a 'state' field, and the context is propagated so the ORM will try to assign 'done' to that field, which is an incorrect value ; - -> Crash. If we ensure that the default_* keys are cleaned from the context, the default values computation of the mail.mail record will not be affected and everything works fine. A test was added to ensure this behavior. Task 2393259 closes odoo/odoo#62545 X-original-commit: 769bef6560cc3aa565a3530549bdad19fc6cac4c Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com> Signed-off-by: awa-odoo <awa-odoo@users.noreply.github.com>
-rw-r--r--addons/mail/models/mail_thread.py13
-rw-r--r--addons/test_mail/tests/test_mail_followers.py45
2 files changed, 55 insertions, 3 deletions
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 63ee621ef7c..18962e5b049 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -2232,7 +2232,14 @@ class MailThread(models.AbstractModel):
}
base_mail_values = self._notify_by_email_add_values(base_mail_values)
- Mail = self.env['mail.mail'].sudo()
+ # Clean the context to get rid of residual default_* keys that could cause issues during
+ # the mail.mail creation.
+ # Example: 'default_state' would refer to the default state of a previously created record
+ # from another model that in turns triggers an assignation notification that ends up here.
+ # This will lead to a traceback when trying to create a mail.mail with this state value that
+ # doesn't exist.
+ SafeMail = self.env['mail.mail'].sudo().with_context(clean_context(self._context))
+ SafeNotification = self.env['mail.notification'].sudo().with_context(clean_context(self._context))
emails = self.env['mail.mail'].sudo()
# loop on groups (customer, portal, user, ... + model specific like group_sale_salesman)
@@ -2265,7 +2272,7 @@ class MailThread(models.AbstractModel):
if email_to:
create_values['email_to'] = email_to
create_values.update(base_mail_values) # mail_message_id, mail_server_id, auto_delete, references, headers
- email = Mail.create(create_values)
+ email = SafeMail.create(create_values)
if email and recipient_ids:
tocreate_recipient_ids = list(recipient_ids)
@@ -2292,7 +2299,7 @@ class MailThread(models.AbstractModel):
emails |= email
if notif_create_values:
- self.env['mail.notification'].sudo().create(notif_create_values)
+ SafeNotification.create(notif_create_values)
# NOTE:
# 1. for more than 50 followers, use the queue system
diff --git a/addons/test_mail/tests/test_mail_followers.py b/addons/test_mail/tests/test_mail_followers.py
index fe8c5f38d96..ba2ef2074c8 100644
--- a/addons/test_mail/tests/test_mail_followers.py
+++ b/addons/test_mail/tests/test_mail_followers.py
@@ -270,6 +270,51 @@ class AdvancedFollowersTest(TestMailCommon):
all_defaults)
+class AdvancedResponsibleNotifiedTest(TestMailCommon):
+ def setUp(self):
+ super(AdvancedResponsibleNotifiedTest, self).setUp()
+
+ # patch registry to simulate a ready environment so that _message_auto_subscribe_notify
+ # will be executed with the associated notification
+ old = self.env.registry.ready
+ self.env.registry.ready = True
+ self.addCleanup(setattr, self.env.registry, 'ready', old)
+
+ def test_auto_subscribe_notify_email(self):
+ """ Responsible is notified when assigned """
+ partner = self.env['res.partner'].create({"name": "demo1", "email": "demo1@test.com"})
+ notified_user = self.env['res.users'].create({
+ 'login': 'demo1',
+ 'partner_id': partner.id,
+ 'notification_type': 'email',
+ })
+
+ # TODO master: add a 'state' selection field on 'mail.test.track' with a 'done' value to have a complete test
+ # check that 'default_state' context does not collide with mail.mail default values
+ sub = self.env['mail.test.track'].with_user(self.user_employee).with_context({
+ 'default_state': 'done',
+ 'mail_notify_force_send': False
+ }).create({
+ 'name': 'Test',
+ 'user_id': notified_user.id,
+ })
+
+ self.assertEqual(sub.message_partner_ids, (self.user_employee.partner_id | notified_user.partner_id))
+ # fetch created "You have been assigned to 'Test'" mail.message
+ mail_message = self.env['mail.message'].search([
+ ('model', '=', 'mail.test.track'),
+ ('res_id', '=', sub.id),
+ ('partner_ids', 'in', partner.id),
+ ])
+ self.assertEqual(1, len(mail_message))
+
+ # verify that a mail.mail is attached to it with the correct state ('outgoing')
+ mail_notification = mail_message.notification_ids
+ self.assertEqual(1, len(mail_notification))
+ self.assertTrue(bool(mail_notification.mail_id))
+ self.assertEqual('outgoing', mail_notification.mail_id.state)
+
+
@tagged('post_install', '-at_install')
class DuplicateNotificationTest(TestMailCommon):
def test_no_duplicate_notification(self):