From 79a449e021252494671d422bfeeef3cb3cb93cfa Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 6 Mar 2019 11:11:28 +0000 Subject: [PATCH] privacy_consent: Avoid race condition with mail queue cron Before this patch, all privacy consent emails were forced to be sent under a context with `mark_consent_sent=True` to track the state change and trigger the attached server action. When using the automatic mode, if a separate cron job started running the mail queue, it could happen that mails were being sent from that another worker, losing the context key and, as such, being sent without token and without being marked as sent nor executing the attached server action (if any). To avoid this problem, now the context dependency is removed. After all, the `mail.mail` object is only created when sending in `mass_mail` model, so other kind of notifications or messages are not affected. When a mail of type `mass_mail` is sent, we can assume that it is asking for consent and we can move draft consent requests to sent. --- privacy_consent/__init__.py | 1 - privacy_consent/models/mail_mail.py | 4 ++-- privacy_consent/models/privacy_activity.py | 5 ++--- privacy_consent/models/privacy_consent.py | 4 +--- privacy_consent/wizards/__init__.py | 1 - privacy_consent/wizards/mail_compose_message.py | 16 ---------------- 6 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 privacy_consent/wizards/__init__.py delete mode 100644 privacy_consent/wizards/mail_compose_message.py diff --git a/privacy_consent/__init__.py b/privacy_consent/__init__.py index ada0b87..91c5580 100644 --- a/privacy_consent/__init__.py +++ b/privacy_consent/__init__.py @@ -1,3 +1,2 @@ from . import controllers from . import models -from . import wizards diff --git a/privacy_consent/models/mail_mail.py b/privacy_consent/models/mail_mail.py index e53e7fc..25462e7 100644 --- a/privacy_consent/models/mail_mail.py +++ b/privacy_consent/models/mail_mail.py @@ -10,7 +10,7 @@ class MailMail(models.Model): def _postprocess_sent_message(self, mail_sent=True): """Write consent status after sending message.""" - if mail_sent and self.env.context.get('mark_consent_sent'): + if mail_sent: # Get all mails sent to consents consent_mails = self.filtered( lambda one: one.mail_message_id.model == "privacy.consent" @@ -37,7 +37,7 @@ class MailMail(models.Model): """ result = super(MailMail, self).send_get_mail_body(partner=partner) # Avoid polluting other model mails - if self.env.context.get("active_model") != "privacy.consent": + if self.model != "privacy.consent": return result # Tokenize consent links consent = self.env["privacy.consent"] \ diff --git a/privacy_consent/models/privacy_activity.py b/privacy_consent/models/privacy_activity.py index c7d20c9..578f2a7 100644 --- a/privacy_consent/models/privacy_activity.py +++ b/privacy_consent/models/privacy_activity.py @@ -120,11 +120,10 @@ class PrivacyActivity(models.Model): # Skip activitys where consent is not required for one in self.with_context(active_test=False) \ .filtered("consent_required"): - domain = safe_eval(one.subject_domain) - domain += [ + domain = [ ("id", "not in", one.mapped("consent_ids.partner_id").ids), ("email", "!=", False), - ] + ] + safe_eval(one.subject_domain) # Create missing consent requests for missing in self.env["res.partner"].search(domain): consents |= consents.create({ diff --git a/privacy_consent/models/privacy_consent.py b/privacy_consent/models/privacy_consent.py index 6dacd97..fd90678 100644 --- a/privacy_consent/models/privacy_consent.py +++ b/privacy_consent/models/privacy_consent.py @@ -104,8 +104,7 @@ class PrivacyConsent(models.Model): consents_by_template = {} for one in self.with_context(tpl_force_default_to=True, mail_notify_user_signature=False, - mail_auto_subscribe_no_notify=True, - mark_consent_sent=True): + mail_auto_subscribe_no_notify=True): # Group consents by template, to send in batch where possible template_id = one.activity_id.consent_template_id.id consents_by_template.setdefault(template_id, one) @@ -168,7 +167,6 @@ class PrivacyConsent(models.Model): "default_res_id": self.id, "default_template_id": self.activity_id.consent_template_id.id, "default_use_template": True, - "mark_consent_sent": True, "tpl_force_default_to": True, }, "force_email": True, diff --git a/privacy_consent/wizards/__init__.py b/privacy_consent/wizards/__init__.py deleted file mode 100644 index b528d99..0000000 --- a/privacy_consent/wizards/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import mail_compose_message diff --git a/privacy_consent/wizards/mail_compose_message.py b/privacy_consent/wizards/mail_compose_message.py deleted file mode 100644 index a63ecc1..0000000 --- a/privacy_consent/wizards/mail_compose_message.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2018 Tecnativa - Jairo Llopis -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -from odoo import api, models - - -class MailComposeMessage(models.TransientModel): - _inherit = "mail.compose.message" - - @api.multi - def send_mail(self, auto_commit=False): - """Force auto commit when sending consent emails.""" - if self.env.context.get('mark_consent_sent'): - auto_commit = True - return super(MailComposeMessage, self).send_mail(auto_commit)