[FIX] base: access_token error handling correctly
When an attachment is requested with an access_token, a server error
would occur in some situation.
With this changeset when an access token is specified:
- returns a 404 error if the attachment does not exist
- returns a 403 error if the attachment has no access_token
Without this change, the added test would fail with:
```
status = test_access(access_token='Secret')
self.assertEqual(status, 403,
"no access if access token for attachment without access token")
| if not consteq(obj.access_token, access_token):
| TypeError: unsupported operand types(s) or combination of types: 'bool' and 'str'
status = test_access(access_token='Secret')
self.assertEqual(status, 404,
"no access with access token for deleted attachment")
| if not consteq(obj.access_token, access_token):
| odoo.exceptions.MissingError: ('Record does not exist or has been deleted.', None)
```
close #26647
opw-1884419
closes #27275
Co-authored-by: Wolfgang Taferner <wtaferner@users.noreply.github.com>
This commit is contained in:
co-authored by
Wolfgang Taferner
parent
2a697f1c5b
commit
46f2e1918f
@@ -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']
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user