diff --git a/privacy_consent/__manifest__.py b/privacy_consent/__manifest__.py index 08f513b..db09bef 100644 --- a/privacy_consent/__manifest__.py +++ b/privacy_consent/__manifest__.py @@ -20,6 +20,7 @@ "data/ir_actions_server.xml", "data/ir_cron.xml", "data/mail.xml", + "templates/assets.xml", "templates/form.xml", "views/privacy_consent.xml", "views/privacy_activity.xml", diff --git a/privacy_consent/models/mail_mail.py b/privacy_consent/models/mail_mail.py index bb3f0bb..4c1f09d 100644 --- a/privacy_consent/models/mail_mail.py +++ b/privacy_consent/models/mail_mail.py @@ -37,7 +37,7 @@ class MailMail(models.Model): failure_type=failure_type, ) - def send_get_mail_body(self, partner=None): + def _send_prepare_body(self): """Replace privacy consent magic links. This replacement is done here instead of directly writing it into @@ -46,7 +46,7 @@ class MailMail(models.Model): which would enable any reader of such thread to impersonate the subject and choose in its behalf. """ - result = super(MailMail, self).send_get_mail_body(partner=partner) + result = super(MailMail, self)._send_prepare_body() # Avoid polluting other model mails if self.model != "privacy.consent": return result diff --git a/privacy_consent/models/privacy_consent.py b/privacy_consent/models/privacy_consent.py index 98fe56b..1722ba8 100644 --- a/privacy_consent/models/privacy_consent.py +++ b/privacy_consent/models/privacy_consent.py @@ -150,7 +150,7 @@ class PrivacyConsent(models.Model): """Let user manually ask for consent.""" return { "context": { - "default_composition_mode": "mass_mail", + "default_composition_mode": "comment", "default_model": self._name, "default_res_id": self.id, "default_template_id": self.activity_id.consent_template_id.id, diff --git a/privacy_consent/static/src/css/privacy_consent.scss b/privacy_consent/static/src/css/privacy_consent.scss new file mode 100644 index 0000000..605268a --- /dev/null +++ b/privacy_consent/static/src/css/privacy_consent.scss @@ -0,0 +1,7 @@ +/* Copyright 2020 Tecnativa - Jairo Llopis + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ + +.o_consent_form { + // Need !important to override an inline style of max-width: 300px + max-width: 100% !important; +} diff --git a/privacy_consent/templates/assets.xml b/privacy_consent/templates/assets.xml new file mode 100644 index 0000000..27e7436 --- /dev/null +++ b/privacy_consent/templates/assets.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/privacy_consent/templates/form.xml b/privacy_consent/templates/form.xml index b0e260b..7d241ca 100644 --- a/privacy_consent/templates/form.xml +++ b/privacy_consent/templates/form.xml @@ -9,6 +9,7 @@ by website layout if website is installed, and otherwise includes all possibly needed assets --> +

Thank you!

diff --git a/privacy_consent/tests/test_consent.py b/privacy_consent/tests/test_consent.py index 52c8000..24550e5 100644 --- a/privacy_consent/tests/test_consent.py +++ b/privacy_consent/tests/test_consent.py @@ -1,8 +1,10 @@ # Copyright 2018 Tecnativa - Jairo Llopis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from contextlib import contextmanager + from odoo.exceptions import ValidationError -from odoo.tests.common import HttpCase +from odoo.tests.common import HttpCase, Form class ActivityCase(HttpCase): @@ -70,6 +72,37 @@ class ActivityCase(HttpCase): "server_action_id": self.sync_blacklist.id, }) + @contextmanager + def _patch_build(self): + self._built_messages = [] + IMS = self.env['ir.mail_server'] + + def _build_email( + _self, + email_from, + email_to, + subject, + body, + *args, + **kwargs + ): + self._built_messages.append(body) + return _build_email.origin( + _self, + email_from, + email_to, + subject, + body, + *args, + **kwargs, + ) + + try: + IMS._patch_method('build_email', _build_email) + yield + finally: + IMS._revert_method('build_email') + def check_activity_auto_properly_sent(self): """Check emails sent by ``self.activity_auto``.""" consents = self.env["privacy.consent"].search([ @@ -81,8 +114,9 @@ class ActivityCase(HttpCase): messages = consent.message_ids self.assertEqual(len(messages), 2) # Check sent mails - self.cron_mail_queue.method_direct_trigger() - for consent in consents: + with self._patch_build(): + self.cron_mail_queue.method_direct_trigger() + for index, consent in enumerate(consents): good_email = "@" in (consent.partner_id.email or "") expected_messages = 3 if good_email else 2 self.assertEqual( @@ -119,6 +153,14 @@ class ActivityCase(HttpCase): ) # Partner's is_blacklisted should be synced with default consent self.assertFalse(consent.partner_id.is_blacklisted) + # Check the sent message was built properly tokenized + accept_url, reject_url = map(consent._url, (True, False)) + for body in self._built_messages: + if accept_url in body and reject_url in body: + self._built_messages.remove(body) + break + else: + raise AssertionError("Some message body should have these urls") def test_default_template(self): """We have a good mail template by default.""" @@ -182,19 +224,27 @@ class ActivityCase(HttpCase): # Send one manual request action = consents[0].action_manual_ask() self.assertEqual(action["res_model"], "mail.compose.message") - composer = self.env[action["res_model"]] \ - .with_context(active_ids=consents[0].ids, - active_model=consents._name, - **action["context"]).create({}) - composer.onchange_template_id_wrapper() - composer.send_mail() + Composer = self.env[action["res_model"]].with_context( + active_ids=consents[0].ids, + active_model=consents._name, + **action["context"], + ) + composer_wizard = Form(Composer) + self.assertIn(consents[0].partner_id.name, composer_wizard.body) + composer_record = composer_wizard.save() + with self._patch_build(): + composer_record.send_mail() + # Check the sent message was built properly tokenized + body = self._built_messages[0] + self.assertIn(consents[0]._url(True), body) + self.assertIn(consents[0]._url(False), body) messages = consents.mapped("message_ids") - messages self.assertEqual(len(messages), 2) self.assertEqual(messages[0].subtype_id, self.mt_consent_state_changed) self.assertEqual(consents.mapped("state"), ["sent", "draft", "draft"]) self.assertEqual( consents.mapped("partner_id.is_blacklisted"), - [False, False, False], + [True, False, False], ) # Placeholder links should be logged self.assertTrue("/privacy/consent/accept/" in messages[1].body)