From 5e81850ea64b533f0576c919a427820554096284 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= <tde@odoo.com>
Date: Tue, 27 Apr 2021 13:44:18 +0200
Subject: [PATCH] [FIX] base: ir_attachment check logic

How to fix mail.template attachments by re-attaching them to some
template:

```sql
with template_attach as
 (select *
    from email_template_attachment_rel
   where attachment_id in (
          select id
            from ir_attachment
           where res_id = 0 and not public and res_model='mail.template')
 )
update ir_attachment a set res_id = ta.email_template_id
                      from template_attach ta
                     where a.id = ta.attachment_id;
```
---
 addons/mail/wizard/mail_compose_message.py  | 10 +++++++++-
 addons/test_mail/tests/test_mail_message.py |  4 +++-
 addons/web/static/src/xml/base.xml          |  2 +-
 odoo/addons/base/models/ir_attachment.py    |  4 ++--
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index 19a0fcf0679d..41e5d9e35d82 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -442,9 +442,17 @@ class MailComposer(models.TransientModel):
                 'subject': record.subject or False,
                 'body_html': record.body or False,
                 'model_id': model.id or False,
-                'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])],
             }
             template = self.env['mail.template'].create(values)
+
+            if record.attachment_ids:
+                # transfer pending attachments to the new template
+                attachments = self.env['ir.attachment'].sudo().browse(record.attachment_ids.ids).filtered(
+                    lambda a: a.res_model == 'mail.compose.message' and a.create_uid.id == self._uid)
+                if attachments:
+                    attachments.write({'res_model': template._name, 'res_id': template.id})
+                template.attachment_ids |= record.attachment_ids
+
             # generate the saved template
             record.write({'template_id': template.id})
             record.onchange_template_id_wrapper()
diff --git a/addons/test_mail/tests/test_mail_message.py b/addons/test_mail/tests/test_mail_message.py
index b8c03a9b1cd3..fff9b373e68e 100644
--- a/addons/test_mail/tests/test_mail_message.py
+++ b/addons/test_mail/tests/test_mail_message.py
@@ -261,7 +261,9 @@ class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails):
     def test_mail_message_access_read_notification(self):
         attachment = self.env['ir.attachment'].create({
             'datas': base64.b64encode(b'My attachment'),
-            'name': 'doc.txt'})
+            'name': 'doc.txt',
+            'res_model': self.message._name,
+            'res_id': self.message.id})
         # attach the attachment to the message
         self.message.write({'attachment_ids': [(4, attachment.id)]})
         self.message.write({'partner_ids': [(4, self.user_employee.partner_id.id)]})
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 9ef92a2d96f5..df02a1d6dda6 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1013,7 +1013,7 @@
             <t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
             <t t-set="multi_upload" t-value="true"/>
             <input type="hidden" name="model" t-att-value="widget.model"/>
-            <input type="hidden" name="id" value="0"/>
+            <input type="hidden" name="id" t-att-value="widget.res_id or 0"/>
         </t>
     </div>
 </div>
diff --git a/odoo/addons/base/models/ir_attachment.py b/odoo/addons/base/models/ir_attachment.py
index 6e3a42a96f9c..4d15374e5741 100644
--- a/odoo/addons/base/models/ir_attachment.py
+++ b/odoo/addons/base/models/ir_attachment.py
@@ -347,10 +347,10 @@ class IrAttachment(models.Model):
             self.env['ir.attachment'].flush(['res_model', 'res_id', 'create_uid', 'public', 'res_field'])
             self._cr.execute('SELECT res_model, res_id, create_uid, public, res_field FROM ir_attachment WHERE id IN %s', [tuple(self.ids)])
             for res_model, res_id, create_uid, public, res_field in self._cr.fetchall():
-                if not self.env.is_system() and res_field:
-                    raise AccessError(_("Sorry, you are not allowed to access this document."))
                 if public and mode == 'read':
                     continue
+                if not self.env.is_system() and (res_field or (not res_id and create_uid != self.env.uid)):
+                    raise AccessError(_("Sorry, you are not allowed to access this document."))
                 if not (res_model and res_id):
                     if create_uid != self._uid:
                         require_employee = True
-- 
GitLab