mirror of
https://github.com/suitenumerique/drive.git
synced 2026-09-06 17:57:53 +02:00
✨(backend) expose url_preview on item object
We want to distinguish the url and the url_preview. The url_preview property will be provided only if the mimetype is listed in the ITEM_PREVIEWABLE_MIME_TYPES settings. Also an other route is added to nginx forcing the content-disposition with the value attachment for download url.
This commit is contained in:
+2
-1
@@ -10,7 +10,8 @@ and this project adheres to
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(back) create wopi applcation #2
|
||||
- ✨(backend) create wopi applcation #2
|
||||
- ✨(backend) expose url_preview on item object
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -17,6 +17,25 @@ server {
|
||||
proxy_set_header X-Amz-Date $authDate;
|
||||
proxy_set_header X-Amz-Content-SHA256 $authContentSha256;
|
||||
|
||||
# Get resource from Minio
|
||||
proxy_pass http://minio:9000/drive-media-storage/;
|
||||
proxy_set_header Host minio:9000;
|
||||
add_header Content-Disposition "attachment";
|
||||
}
|
||||
|
||||
# Proxy auth for media
|
||||
location /media/preview/ {
|
||||
# Auth request configuration
|
||||
auth_request /media-auth;
|
||||
auth_request_set $authHeader $upstream_http_authorization;
|
||||
auth_request_set $authDate $upstream_http_x_amz_date;
|
||||
auth_request_set $authContentSha256 $upstream_http_x_amz_content_sha256;
|
||||
|
||||
# Pass specific headers from the auth response
|
||||
proxy_set_header Authorization $authHeader;
|
||||
proxy_set_header X-Amz-Date $authDate;
|
||||
proxy_set_header X-Amz-Content-SHA256 $authContentSha256;
|
||||
|
||||
# Get resource from Minio
|
||||
proxy_pass http://minio:9000/drive-media-storage/;
|
||||
proxy_set_header Host minio:9000;
|
||||
|
||||
@@ -132,6 +132,7 @@ class ListItemSerializer(serializers.ModelSerializer):
|
||||
nb_accesses = serializers.IntegerField(read_only=True)
|
||||
user_roles = serializers.SerializerMethodField()
|
||||
url = serializers.SerializerMethodField()
|
||||
url_preview = serializers.SerializerMethodField()
|
||||
creator = UserLiteSerializer(read_only=True)
|
||||
hard_delete_at = serializers.SerializerMethodField(read_only=True)
|
||||
is_wopi_supported = serializers.SerializerMethodField()
|
||||
@@ -157,6 +158,7 @@ class ListItemSerializer(serializers.ModelSerializer):
|
||||
"type",
|
||||
"upload_state",
|
||||
"url",
|
||||
"url_preview",
|
||||
"filename",
|
||||
"mimetype",
|
||||
"main_workspace",
|
||||
@@ -184,6 +186,7 @@ class ListItemSerializer(serializers.ModelSerializer):
|
||||
"type",
|
||||
"upload_state",
|
||||
"url",
|
||||
"url_preview",
|
||||
"mimetype",
|
||||
"main_workspace",
|
||||
"size",
|
||||
@@ -228,6 +231,17 @@ class ListItemSerializer(serializers.ModelSerializer):
|
||||
|
||||
return f"{settings.MEDIA_BASE_URL}{settings.MEDIA_URL}{quote(item.file_key)}"
|
||||
|
||||
def get_url_preview(self, item):
|
||||
"""Return the URL of the item."""
|
||||
if (
|
||||
item.type != models.ItemTypeChoices.FILE
|
||||
or item.upload_state == models.ItemUploadStateChoices.PENDING
|
||||
or item.filename is None
|
||||
or not utils.is_previewable_item(item)
|
||||
):
|
||||
return None
|
||||
return f"{settings.MEDIA_BASE_URL}{settings.MEDIA_URL_PREVIEW}{quote(item.file_key)}"
|
||||
|
||||
def get_hard_delete_at(self, item):
|
||||
"""Return the hard delete date of the item."""
|
||||
if item.deleted_at is None:
|
||||
@@ -279,6 +293,7 @@ class ItemSerializer(ListItemSerializer):
|
||||
"type",
|
||||
"upload_state",
|
||||
"url",
|
||||
"url_preview",
|
||||
"filename",
|
||||
"mimetype",
|
||||
"main_workspace",
|
||||
@@ -304,6 +319,7 @@ class ItemSerializer(ListItemSerializer):
|
||||
"type",
|
||||
"upload_state",
|
||||
"url",
|
||||
"url_preview",
|
||||
"mimetype",
|
||||
"main_workspace",
|
||||
"size",
|
||||
|
||||
@@ -133,6 +133,22 @@ def generate_upload_policy(item):
|
||||
return policy
|
||||
|
||||
|
||||
def is_previewable_item(item):
|
||||
"""
|
||||
Check if a mime type is previewable.
|
||||
"""
|
||||
if item.mimetype is None:
|
||||
return False
|
||||
|
||||
for allowed in settings.ITEM_PREVIEWABLE_MIME_TYPES:
|
||||
if allowed.endswith("/"):
|
||||
if item.mimetype.startswith(allowed):
|
||||
return True
|
||||
elif item.mimetype == allowed:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_item_file_head_object(item):
|
||||
"""
|
||||
Get the head object of an item file.
|
||||
|
||||
@@ -49,7 +49,7 @@ UUID_REGEX = (
|
||||
)
|
||||
FILE_EXT_REGEX = '[^.\\/:*?&"<>|\r\n]+'
|
||||
MEDIA_STORAGE_URL_PATTERN = re.compile(
|
||||
f"{settings.MEDIA_URL:s}"
|
||||
f"{settings.MEDIA_URL:s}(?P<preview>preview/)?"
|
||||
f"(?P<key>{ITEM_FOLDER:s}/(?P<pk>{UUID_REGEX:s})/.*{FILE_EXT_REGEX:s})$"
|
||||
)
|
||||
|
||||
@@ -1183,6 +1183,10 @@ class ItemViewSet(
|
||||
logger.debug("Item '%s' is not ready", item.id)
|
||||
raise drf.exceptions.PermissionDenied()
|
||||
|
||||
if url_params.get("preview") and not utils.is_previewable_item(item):
|
||||
logger.debug("Item '%s' is not previewable", item.id)
|
||||
raise drf.exceptions.PermissionDenied()
|
||||
|
||||
# Generate S3 authorization headers using the extracted URL parameters
|
||||
request = utils.generate_s3_authorization_headers(f"{url_params.get('key'):s}")
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ def test_api_items_children_list_anonymous_public_standalone():
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -91,6 +92,7 @@ def test_api_items_children_list_anonymous_public_standalone():
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
@@ -129,6 +131,7 @@ def test_api_items_children_list_anonymous_public_parent():
|
||||
|
||||
child2.upload_state = models.ItemUploadStateChoices.READY
|
||||
child2.filename = "logo.png"
|
||||
child2.mimetype = "image/png"
|
||||
child2.save()
|
||||
|
||||
response = APIClient().get(f"/api/v1.0/items/{item.id!s}/children/")
|
||||
@@ -162,6 +165,7 @@ def test_api_items_children_list_anonymous_public_parent():
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": models.ItemUploadStateChoices.PENDING,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -194,7 +198,8 @@ def test_api_items_children_list_anonymous_public_parent():
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": models.ItemUploadStateChoices.READY,
|
||||
"url": f"http://localhost:8083/media/item/{child2.id!s}/logo.png",
|
||||
"mimetype": None,
|
||||
"url_preview": f"http://localhost:8083/media/preview/item/{child2.id!s}/logo.png",
|
||||
"mimetype": "image/png",
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
"size": None,
|
||||
@@ -280,6 +285,7 @@ def test_api_items_children_list_authenticated_unrelated_public_or_authenticated
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -314,6 +320,7 @@ def test_api_items_children_list_authenticated_unrelated_public_or_authenticated
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
@@ -385,6 +392,7 @@ def test_api_items_children_list_authenticated_public_or_authenticated_parent(
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -419,6 +427,7 @@ def test_api_items_children_list_authenticated_public_or_authenticated_parent(
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
@@ -515,6 +524,7 @@ def test_api_items_children_list_authenticated_related_direct():
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -549,6 +559,7 @@ def test_api_items_children_list_authenticated_related_direct():
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
@@ -621,6 +632,7 @@ def test_api_items_children_list_authenticated_related_parent():
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -655,6 +667,7 @@ def test_api_items_children_list_authenticated_related_parent():
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
@@ -790,6 +803,7 @@ def test_api_items_children_list_authenticated_related_team_members(
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -824,6 +838,7 @@ def test_api_items_children_list_authenticated_related_team_members(
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
@@ -892,6 +907,7 @@ def test_api_items_children_list_filter_type():
|
||||
if child1.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child1.filename,
|
||||
@@ -939,6 +955,7 @@ def test_api_items_children_list_filter_type():
|
||||
if child2.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": child2.filename,
|
||||
|
||||
@@ -86,6 +86,7 @@ def test_api_item_favorite_list_authenticated_with_favorite():
|
||||
"updated_at": item.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": item.upload_state,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": ["reader"],
|
||||
"main_workspace": False,
|
||||
|
||||
@@ -67,6 +67,7 @@ def test_api_items_list_format():
|
||||
|
||||
item2.upload_state = models.ItemUploadStateChoices.READY
|
||||
item2.filename = "logo.png"
|
||||
item2.mimetype = "image/png"
|
||||
item2.save()
|
||||
|
||||
item3 = user.get_main_workspace()
|
||||
@@ -106,7 +107,8 @@ def test_api_items_list_format():
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": models.ItemUploadStateChoices.READY,
|
||||
"url": f"http://localhost:8083/media/item/{item2.id!s}/logo.png",
|
||||
"mimetype": None,
|
||||
"url_preview": f"http://localhost:8083/media/preview/item/{item2.id!s}/logo.png",
|
||||
"mimetype": "image/png",
|
||||
"main_workspace": False,
|
||||
"filename": item2.filename,
|
||||
"size": None,
|
||||
@@ -138,6 +140,7 @@ def test_api_items_list_format():
|
||||
"type": models.ItemTypeChoices.FOLDER,
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -170,6 +173,7 @@ def test_api_items_list_format():
|
||||
"type": models.ItemTypeChoices.FOLDER,
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": True,
|
||||
"filename": item3.filename,
|
||||
|
||||
@@ -51,6 +51,7 @@ def test_api_items_retrieve_anonymous_public_standalone():
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -104,6 +105,7 @@ def test_api_items_retrieve_anonymous_public_parent():
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -202,6 +204,7 @@ def test_api_items_retrieve_authenticated_unrelated_public_or_authenticated(reac
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -261,6 +264,7 @@ def test_api_items_retrieve_authenticated_public_or_authenticated_parent(reach):
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -398,6 +402,7 @@ def test_api_items_retrieve_authenticated_related_direct():
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -459,6 +464,7 @@ def test_api_items_retrieve_authenticated_related_parent():
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -638,6 +644,7 @@ def test_api_items_retrieve_authenticated_related_team_members(
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -711,6 +718,7 @@ def test_api_items_retrieve_authenticated_related_team_administrators(
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -784,6 +792,7 @@ def test_api_items_retrieve_authenticated_related_team_owners(
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -1149,6 +1158,7 @@ def test_api_items_retrieve_file_with_url_property(upload_state):
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": upload_state,
|
||||
"url": f"http://localhost:8083/media/item/{item.id!s}/logo.png",
|
||||
"url_preview": f"http://localhost:8083/media/preview/item/{item.id!s}/logo.png",
|
||||
"mimetype": "image/png",
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -1160,6 +1170,74 @@ def test_api_items_retrieve_file_with_url_property(upload_state):
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"upload_state",
|
||||
[
|
||||
models.ItemUploadStateChoices.READY,
|
||||
models.ItemUploadStateChoices.ANALYZING,
|
||||
models.ItemUploadStateChoices.FILE_TOO_LARGE_TO_ANALYZE,
|
||||
models.ItemUploadStateChoices.SUSPICIOUS,
|
||||
],
|
||||
)
|
||||
def test_api_items_retrieve_file_with_url_property_non_previewable(upload_state):
|
||||
"""
|
||||
The `url` property should not be none if the item is not pending but the
|
||||
url preview should.
|
||||
"""
|
||||
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
item = factories.ItemFactory(
|
||||
creator=user,
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
link_reach="public",
|
||||
update_upload_state=upload_state,
|
||||
filename="document.odt",
|
||||
mimetype="application/vnd.oasis.opendocument.text",
|
||||
size=8,
|
||||
users=[(user, models.RoleChoices.OWNER)],
|
||||
)
|
||||
|
||||
response = client.get(f"/api/v1.0/items/{item.id!s}/")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"id": str(item.id),
|
||||
"abilities": item.get_abilities(user),
|
||||
"created_at": item.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": {
|
||||
"id": str(item.creator.id),
|
||||
"full_name": item.creator.full_name,
|
||||
"short_name": item.creator.short_name,
|
||||
},
|
||||
"depth": 1,
|
||||
"is_favorite": False,
|
||||
"link_reach": "public",
|
||||
"link_role": item.link_role,
|
||||
"nb_accesses": 1,
|
||||
"numchild": 0,
|
||||
"numchild_folder": 0,
|
||||
"path": str(item.path),
|
||||
"title": item.title,
|
||||
"updated_at": item.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"user_roles": [models.RoleChoices.OWNER],
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": upload_state,
|
||||
"url": f"http://localhost:8083/media/item/{item.id!s}/document.odt",
|
||||
"url_preview": None,
|
||||
"mimetype": "application/vnd.oasis.opendocument.text",
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
"size": 8,
|
||||
"description": None,
|
||||
"deleted_at": None,
|
||||
"hard_delete_at": None,
|
||||
"is_wopi_supported": False,
|
||||
}
|
||||
|
||||
|
||||
def test_api_items_retrieve_file_with_url_property_with_spaces():
|
||||
"""
|
||||
The `url` property should have white spaces encoded.
|
||||
@@ -1206,6 +1284,10 @@ def test_api_items_retrieve_file_with_url_property_with_spaces():
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": models.ItemUploadStateChoices.READY,
|
||||
"url": f"http://localhost:8083/media/item/{item.id!s}/logo%20with%20spaces.png",
|
||||
"url_preview": (
|
||||
f"http://localhost:8083/media/preview/item/{item.id!s}/"
|
||||
"logo%20with%20spaces.png"
|
||||
),
|
||||
"mimetype": "image/png",
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
@@ -1344,6 +1426,7 @@ def test_api_items_retrieve_file_analysing_not_creator():
|
||||
"type": models.ItemTypeChoices.FILE,
|
||||
"upload_state": models.ItemUploadStateChoices.ANALYZING,
|
||||
"url": f"http://localhost:8083/media/item/{item.id!s}/logo.png",
|
||||
"url_preview": f"http://localhost:8083/media/preview/item/{item.id!s}/logo.png",
|
||||
"mimetype": "image/png",
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
|
||||
@@ -82,6 +82,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
.replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": ["owner"],
|
||||
},
|
||||
{
|
||||
@@ -115,6 +116,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
"updated_at": top_parent.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": [top_parent_access.role],
|
||||
},
|
||||
{
|
||||
@@ -175,6 +177,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": [top_parent_access.role],
|
||||
}
|
||||
],
|
||||
@@ -185,6 +188,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
"updated_at": parent.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": [top_parent_access.role],
|
||||
},
|
||||
{
|
||||
@@ -245,6 +249,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": [top_parent_access.role],
|
||||
},
|
||||
{
|
||||
@@ -277,6 +282,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
"updated_at": parent.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": [top_parent_access.role],
|
||||
},
|
||||
],
|
||||
@@ -287,6 +293,7 @@ def test_api_items_search_authenticated_without_filters():
|
||||
"updated_at": children.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": "pending",
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"user_roles": [top_parent_access.role],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -86,6 +86,7 @@ def test_api_items_trashbin_format(settings):
|
||||
if item.type == models.ItemTypeChoices.FILE
|
||||
else None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"main_workspace": False,
|
||||
"filename": item.filename,
|
||||
|
||||
@@ -161,6 +161,7 @@ def test_items_api_anonymous_to_a_public_tree_structure():
|
||||
"updated_at": level2_1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": [],
|
||||
"main_workspace": False,
|
||||
@@ -194,6 +195,7 @@ def test_items_api_anonymous_to_a_public_tree_structure():
|
||||
"updated_at": level2_2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": [],
|
||||
"main_workspace": False,
|
||||
@@ -225,6 +227,7 @@ def test_items_api_anonymous_to_a_public_tree_structure():
|
||||
"updated_at": level1_2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": [],
|
||||
"main_workspace": False,
|
||||
@@ -374,6 +377,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(level2_1.item.get_roles(user)),
|
||||
"main_workspace": False,
|
||||
@@ -417,6 +421,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(level3_1.item.get_roles(user)),
|
||||
"main_workspace": False,
|
||||
@@ -452,6 +457,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(level2_2.item.get_roles(user)),
|
||||
"main_workspace": False,
|
||||
@@ -487,6 +493,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(level1_1.item.get_roles(user)),
|
||||
"main_workspace": False,
|
||||
@@ -524,6 +531,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(level1_2.item.get_roles(user)),
|
||||
"main_workspace": False,
|
||||
@@ -561,6 +569,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(level1_3.item.get_roles(user)),
|
||||
"main_workspace": False,
|
||||
@@ -592,6 +601,7 @@ def test_items_api_tree_authenticated_direct_access(django_assert_num_queries):
|
||||
"updated_at": root.item.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": list(root.item.get_roles(user)),
|
||||
"main_workspace": True,
|
||||
@@ -706,6 +716,7 @@ def test_api_items_tree_authenticated_with_access_authenticated():
|
||||
"updated_at": level1_1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": [],
|
||||
"main_workspace": False,
|
||||
@@ -740,6 +751,7 @@ def test_api_items_tree_authenticated_with_access_authenticated():
|
||||
"updated_at": level2_1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": [],
|
||||
"main_workspace": False,
|
||||
@@ -773,6 +785,7 @@ def test_api_items_tree_authenticated_with_access_authenticated():
|
||||
"updated_at": level2_2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"upload_state": None,
|
||||
"url": None,
|
||||
"url_preview": None,
|
||||
"mimetype": None,
|
||||
"user_roles": [],
|
||||
"main_workspace": False,
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"""Test utils.is_previewable_item"""
|
||||
|
||||
import pytest
|
||||
|
||||
from core import factories, models
|
||||
from core.api import utils
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_is_previewable_item_returns_false_when_mimetype_is_none():
|
||||
"""Test is_previewable_item returns False when mimetype is None"""
|
||||
item = factories.ItemFactory(
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
filename="file.bin",
|
||||
mimetype=None,
|
||||
)
|
||||
|
||||
assert utils.is_previewable_item(item) is False
|
||||
|
||||
|
||||
def test_is_previewable_item_returns_true_for_prefix_allowed_type_image_png():
|
||||
"""Test is_previewable_item returns True for prefix allowed type image/png"""
|
||||
item = factories.ItemFactory(
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
filename="image.png",
|
||||
mimetype="image/png",
|
||||
)
|
||||
|
||||
assert utils.is_previewable_item(item) is True
|
||||
|
||||
|
||||
def test_is_previewable_item_returns_true_for_exact_allowed_type_pdf():
|
||||
"""Test is_previewable_item returns True for exact allowed type application/pdf"""
|
||||
item = factories.ItemFactory(
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
filename="document.pdf",
|
||||
mimetype="application/pdf",
|
||||
)
|
||||
|
||||
assert utils.is_previewable_item(item) is True
|
||||
|
||||
|
||||
def test_is_previewable_item_returns_false_for_unallowed_type_json():
|
||||
"""Test is_previewable_item returns False for unallowed type application/json"""
|
||||
item = factories.ItemFactory(
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
filename="data.json",
|
||||
mimetype="application/json",
|
||||
)
|
||||
|
||||
assert utils.is_previewable_item(item) is False
|
||||
|
||||
|
||||
def test_is_previewable_item_returns_false_for_exact_mismatch_pdfx():
|
||||
"""Test is_previewable_item returns False for exact mismatch application/pdfx"""
|
||||
item = factories.ItemFactory(
|
||||
type=models.ItemTypeChoices.FILE,
|
||||
filename="document.pdfx",
|
||||
mimetype="application/pdfx",
|
||||
)
|
||||
|
||||
assert utils.is_previewable_item(item) is False
|
||||
@@ -102,6 +102,7 @@ class Base(Configuration):
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_ROOT = os.path.join(DATA_DIR, "static")
|
||||
MEDIA_URL = "/media/"
|
||||
MEDIA_URL_PREVIEW = "/media/preview/"
|
||||
MEDIA_ROOT = os.path.join(DATA_DIR, "media")
|
||||
MEDIA_BASE_URL = values.Value(
|
||||
None, environ_name="MEDIA_BASE_URL", environ_prefix=None
|
||||
@@ -173,6 +174,17 @@ class Base(Configuration):
|
||||
environ_prefix=None,
|
||||
)
|
||||
|
||||
ITEM_PREVIEWABLE_MIME_TYPES = values.ListValue(
|
||||
[
|
||||
"image/",
|
||||
"video/",
|
||||
"audio/",
|
||||
"application/pdf",
|
||||
],
|
||||
environ_name="ITEM_PREVIEWABLE_MIME_TYPES",
|
||||
environ_prefix=None,
|
||||
)
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user