mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 10:12:04 +02:00
vanilla 19.0
This commit is contained in:
parent
991d2234ca
commit
d1963a3c3a
3066 changed files with 1651266 additions and 922560 deletions
|
|
@ -4,10 +4,13 @@
|
|||
import io
|
||||
import base64
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from freezegun import freeze_time
|
||||
from PIL import Image
|
||||
from werkzeug.urls import url_unquote_plus
|
||||
|
||||
from odoo.tests.common import HttpCase, tagged
|
||||
from odoo.tests.common import HttpCase, new_test_user, tagged
|
||||
from odoo.tools.misc import limited_field_access_token
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
|
|
@ -157,3 +160,191 @@ class TestImage(HttpCase):
|
|||
assert_filenames(f'/web/image/{att.id}/4wzb_!!63148-0-t1.jpg_360x1Q75.jpg_.webp',
|
||||
r"""4wzb_!!63148-0-t1.jpg_360x1Q75.jpg_.webp""",
|
||||
)
|
||||
|
||||
def test_05_web_image_access_token(self):
|
||||
"""Tests that valid access tokens grant access to binary data."""
|
||||
|
||||
def get_datetime_from_token(token):
|
||||
return datetime.fromtimestamp(int(token.rsplit("o", 1)[1], 16))
|
||||
|
||||
attachment = self.env["ir.attachment"].create(
|
||||
{
|
||||
"datas": b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
|
||||
"name": "test.gif",
|
||||
"mimetype": "image/gif",
|
||||
}
|
||||
)
|
||||
# no token: ko
|
||||
res = self.url_open(f"/web/image/{attachment.id}")
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.headers["Content-Disposition"], "inline; filename=placeholder.png")
|
||||
# invalid token: ko
|
||||
res = self.url_open(f"/web/image/{attachment.id}?access_token=invalid_token")
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.headers["Content-Disposition"], "inline; filename=placeholder.png")
|
||||
# token from a different scope: ko
|
||||
token = limited_field_access_token(attachment, "raw", scope="other_scope")
|
||||
res = self.url_open(f"/web/image/{attachment.id}?access_token={token}")
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.headers["Content-Disposition"], "inline; filename=placeholder.png")
|
||||
# valid token: ok
|
||||
token = attachment._get_raw_access_token()
|
||||
res = self.url_open(f"/web/image/{attachment.id}?access_token={token}")
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.headers["Content-Disposition"], "inline; filename=test.gif")
|
||||
# token about to expire: ok
|
||||
with freeze_time(get_datetime_from_token(token) - timedelta(seconds=1)):
|
||||
res = self.url_open(f"/web/image/{attachment.id}?access_token={token}")
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.headers["Content-Disposition"], "inline; filename=test.gif")
|
||||
# expired token: ko
|
||||
with freeze_time(get_datetime_from_token(token)):
|
||||
res = self.url_open(f"/web/image/{attachment.id}?access_token={token}")
|
||||
res.raise_for_status()
|
||||
self.assertEqual(res.headers["Content-Disposition"], "inline; filename=placeholder.png")
|
||||
# within a 14-days period, the same token is generated
|
||||
start_of_period = datetime(2021, 2, 18, 0, 0, 0) # 14-days period 2021-02-18 to 2021-03-04
|
||||
base_result = datetime(2021, 3, 24, 15, 25, 40)
|
||||
for i in range(14):
|
||||
with freeze_time(start_of_period + timedelta(days=i, hours=i % 24, minutes=i % 60)):
|
||||
self.assertEqual(
|
||||
get_datetime_from_token(self.env["ir.attachment"].browse(2)._get_raw_access_token()),
|
||||
base_result,
|
||||
)
|
||||
# on each following 14-days period another token is generated, valid for exactly 14 extra
|
||||
# days from the previous token
|
||||
for i in range(50):
|
||||
with freeze_time(
|
||||
start_of_period + timedelta(days=14 * i + i % 14, hours=i % 24, minutes=i % 60)
|
||||
):
|
||||
self.assertEqual(
|
||||
get_datetime_from_token(
|
||||
self.env["ir.attachment"].browse(2)._get_raw_access_token()
|
||||
),
|
||||
base_result + timedelta(days=14 * i),
|
||||
)
|
||||
with freeze_time(datetime(2021, 3, 1, 1, 2, 3)):
|
||||
# at the same time...
|
||||
self.assertEqual(
|
||||
get_datetime_from_token(
|
||||
self.env["ir.attachment"].browse(2)._get_raw_access_token()
|
||||
),
|
||||
base_result,
|
||||
)
|
||||
# a different record generates a different token
|
||||
record_res = self.env["ir.attachment"].browse(3)._get_raw_access_token()
|
||||
self.assertNotIn(record_res, [base_result])
|
||||
# a different field generates a different token
|
||||
field_res = get_datetime_from_token(
|
||||
limited_field_access_token(self.env["ir.attachment"].browse(3), "datas", scope="binary")
|
||||
)
|
||||
self.assertNotIn(field_res, [base_result, record_res])
|
||||
# a different model generates a different token
|
||||
model_res = get_datetime_from_token(
|
||||
limited_field_access_token(self.env["res.partner"].browse(3), "raw", scope="binary")
|
||||
)
|
||||
self.assertNotIn(model_res, [base_result, record_res, field_res])
|
||||
|
||||
def test_06_web_image_attachment_access(self):
|
||||
"""Tests all the combination of user/ways to access an attachment through `/web/content`
|
||||
or `/web/image` routes"""
|
||||
new_test_user(self.env, "portal_user", groups="base.group_portal")
|
||||
new_test_user(self.env, "internal_user")
|
||||
# record of arbitrary model with restrictive ACL even for internal users
|
||||
restricted_record = self.env["res.users.settings"].create({"user_id": self.env.user.id})
|
||||
# record of arbitrary model with permissive ACL for internal users
|
||||
accessible_record = self.env["res.partner"].create({"name": "test partner"})
|
||||
attachments = self.env["ir.attachment"].create(
|
||||
[
|
||||
{
|
||||
"datas": b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
|
||||
"description": "restricted attachment",
|
||||
"name": "test.gif",
|
||||
"res_id": restricted_record.id,
|
||||
"res_model": restricted_record._name,
|
||||
},
|
||||
{
|
||||
"datas": b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
|
||||
"description": "restricted attachment",
|
||||
"name": "test.gif",
|
||||
"res_id": accessible_record.id,
|
||||
"res_model": accessible_record._name,
|
||||
},
|
||||
{
|
||||
"datas": b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
|
||||
"description": "standalone attachment",
|
||||
"name": "test.gif",
|
||||
},
|
||||
{
|
||||
"datas": b"R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=",
|
||||
"description": "public attachment",
|
||||
"name": "test.gif",
|
||||
"public": True,
|
||||
},
|
||||
]
|
||||
)
|
||||
attachments.generate_access_token()
|
||||
internal_restricted, internal_accessible, standalone, public = attachments
|
||||
tests = [
|
||||
# (attachment, user, token, expected result (True if accessible))
|
||||
(internal_restricted, "public_user", None, False),
|
||||
(internal_restricted, "public_user", "token", True),
|
||||
(internal_restricted, "public_user", "limited token", True),
|
||||
(internal_restricted, "portal_user", None, False),
|
||||
(internal_restricted, "portal_user", "token", True),
|
||||
(internal_restricted, "portal_user", "limited token", True),
|
||||
(internal_restricted, "internal_user", None, False),
|
||||
(internal_restricted, "internal_user", "token", True),
|
||||
(internal_restricted, "internal_user", "limited token", True),
|
||||
(internal_accessible, "public_user", None, False),
|
||||
(internal_accessible, "public_user", "token", True),
|
||||
(internal_accessible, "public_user", "limited token", True),
|
||||
(internal_accessible, "portal_user", None, False),
|
||||
(internal_accessible, "portal_user", "token", True),
|
||||
(internal_accessible, "portal_user", "limited token", True),
|
||||
(internal_accessible, "internal_user", None, True),
|
||||
(internal_accessible, "internal_user", "token", True),
|
||||
(internal_accessible, "internal_user", "limited token", True),
|
||||
(standalone, "public_user", None, False),
|
||||
(standalone, "public_user", "token", True),
|
||||
(standalone, "public_user", "limited token", True),
|
||||
(standalone, "portal_user", None, False),
|
||||
(standalone, "portal_user", "token", True),
|
||||
(standalone, "portal_user", "limited token", True),
|
||||
(standalone, "internal_user", None, False),
|
||||
(standalone, "internal_user", "token", True),
|
||||
(standalone, "internal_user", "limited token", True),
|
||||
(public, "public_user", None, True),
|
||||
(public, "public_user", "token", True),
|
||||
(public, "public_user", "limited token", True),
|
||||
(public, "portal_user", None, True),
|
||||
(public, "portal_user", "token", True),
|
||||
(public, "portal_user", "limited token", True),
|
||||
(public, "internal_user", None, True),
|
||||
(public, "internal_user", "token", True),
|
||||
(public, "internal_user", "limited token", True),
|
||||
]
|
||||
for attachment, user, token, result in tests:
|
||||
login = None if user == "public_user" else user
|
||||
self.authenticate(login, login)
|
||||
access_token_param = ""
|
||||
if token:
|
||||
access_token = (
|
||||
attachment.access_token
|
||||
if token == "token"
|
||||
else attachment._get_raw_access_token()
|
||||
)
|
||||
access_token_param = f"?access_token={access_token}"
|
||||
res = self.url_open(f"/web/image/{attachment.id}{access_token_param}")
|
||||
if result:
|
||||
self.assertEqual(
|
||||
res.headers["Content-Disposition"],
|
||||
"inline; filename=test.gif",
|
||||
f"{user} should have access to {attachment.description} with {token or 'no token'}",
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
res.headers["Content-Disposition"],
|
||||
"inline; filename=placeholder.png",
|
||||
f"{user} should not have access to {attachment.description} with {token or 'no token'}",
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue