diff --git a/odoo/addons/base/ir/ir_http.py b/odoo/addons/base/ir/ir_http.py index 751f4aed9ee..eab07d2768e 100644 --- a/odoo/addons/base/ir/ir_http.py +++ b/odoo/addons/base/ir/ir_http.py @@ -278,10 +278,6 @@ class IrHttp(models.AbstractModel): obj = None if xmlid: obj = env.ref(xmlid, False) - elif id and model == 'ir.attachment' and access_token: - obj = env[model].sudo().browse(int(id)) - if not consteq(obj.access_token, access_token): - return (403, [], None) elif id and model in env.registry: obj = env[model].browse(int(id)) @@ -289,6 +285,12 @@ class IrHttp(models.AbstractModel): if not obj or not obj.exists() or field not in obj: return (404, [], None) + # access token grant access + if model == 'ir.attachment' and access_token: + obj = obj.sudo() + if not consteq(obj.access_token or '', access_token): + return (403, [], None) + # check read access try: last_update = obj['__last_update'] diff --git a/odoo/addons/base/tests/test_ir_http.py b/odoo/addons/base/tests/test_ir_http.py index 420a16004ce..2cdcaf74dcf 100644 --- a/odoo/addons/base/tests/test_ir_http.py +++ b/odoo/addons/base/tests/test_ir_http.py @@ -79,3 +79,54 @@ class test_ir_http_mimetype(common.TransactionCase): ) mimetype = dict(headers).get('Content-Type') self.assertEqual(mimetype, 'image/gif') + + def test_ir_http_attachment_access(self): + """ Test attachment access with and without access token """ + public_user = self.env.ref('base.public_user') + attachment = self.env['ir.attachment'].create({ + 'datas': GIF, + 'name': 'Test valid access token with image', + 'datas_fname': 'image.gif' + }) + + defaults = { + 'id': attachment.id, + 'default_mimetype': 'image/gif', + 'env': public_user.sudo(public_user.id).env, + } + + def test_access(**kwargs): + status, _, _ = self.env['ir.http'].binary_content( + **defaults, **kwargs + ) + return status + + status = test_access() + self.assertEqual(status, 403, "no access") + + status = test_access(access_token='Secret') + self.assertEqual(status, 403, + "no access if access token for attachment without access token") + + attachment.access_token = 'Secret' + status = test_access(access_token='Secret') + self.assertEqual(status, 200, "access for correct access token") + + status = test_access(access_token='Wrong') + self.assertEqual(status, 403, "no access for wrong access token") + + attachment.public = True + status = test_access() + self.assertEqual(status, 200, "access for attachment with access") + + status = test_access(access_token='Wrong') + self.assertEqual(status, 403, + "no access for wrong access token for attachment with access") + + attachment.unlink() + status = test_access() + self.assertEqual(status, 404, "no access for deleted attachment") + + status = test_access(access_token='Secret') + self.assertEqual(status, 404, + "no access with access token for deleted attachment")