From 621393165f09b87677e15dc7fc4b10fb69aa6508 Mon Sep 17 00:00:00 2001 From: Samuel Paccoud - DINUM Date: Fri, 17 Jan 2025 18:59:24 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=85(backend)=20add=20missing=20test=20on?= =?UTF-8?q?=20media-auth=20and=20collaboration-auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These methods were involved in a bug that was fixed without first evidencing the error in a test: https://github.com/suitenumerique/docs/pull/556 Fixes https://github.com/suitenumerique/docs/issues/567 --- src/backend/core/api/viewsets.py | 4 ++- src/backend/core/enums.py | 16 +++++++++- .../test_api_documents_collaboration_auth.py | 21 +++++++++++++- .../test_api_documents_media_auth.py | 29 ++++++++++++++----- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index 0d43de47..e4d39918 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -2,7 +2,6 @@ # pylint: disable=too-many-lines import logging -import re import uuid from urllib.parse import unquote, urlparse @@ -35,6 +34,7 @@ from .filters import DocumentFilter, ListDocumentFilter logger = logging.getLogger(__name__) +<<<<<<< HEAD ATTACHMENTS_FOLDER = "attachments" UUID_REGEX = ( r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" @@ -45,6 +45,8 @@ MEDIA_STORAGE_URL_PATTERN = re.compile( f"(?P{ATTACHMENTS_FOLDER:s}/{UUID_REGEX:s}(?:-unsafe)?{FILE_EXT_REGEX:s})$" ) COLLABORATION_WS_URL_PATTERN = re.compile(rf"(?:^|&)room=(?P{UUID_REGEX})(?:&|$)") +======= +>>>>>>> 8076486a (✅(backend) add missing test on media-auth and collaboration-auth) # pylint: disable=too-many-ancestors diff --git a/src/backend/core/enums.py b/src/backend/core/enums.py index 592a84a4..8cd50baf 100644 --- a/src/backend/core/enums.py +++ b/src/backend/core/enums.py @@ -2,10 +2,24 @@ Core application enums declaration """ -from django.conf import global_settings +import re + +from django.conf import global_settings, settings from django.db import models from django.utils.translation import gettext_lazy as _ +ATTACHMENTS_FOLDER = "attachments" +UUID_REGEX = ( + r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" +) +FILE_EXT_REGEX = r"\.[a-zA-Z]{3,4}" +MEDIA_STORAGE_URL_PATTERN = re.compile( + f"{settings.MEDIA_URL:s}(?P{UUID_REGEX:s})/" + f"(?P{ATTACHMENTS_FOLDER:s}/{UUID_REGEX:s}{FILE_EXT_REGEX:s})$" +) +COLLABORATION_WS_URL_PATTERN = re.compile(rf"(?:^|&)room=(?P{UUID_REGEX})(?:&|$)") + + # In Django's code base, `LANGUAGES` is set by default with all supported languages. # We can use it for the choice of languages which should not be limited to the few languages # active in the app. diff --git a/src/backend/core/tests/documents/test_api_documents_collaboration_auth.py b/src/backend/core/tests/documents/test_api_documents_collaboration_auth.py index 201e2d01..de7ec6a7 100644 --- a/src/backend/core/tests/documents/test_api_documents_collaboration_auth.py +++ b/src/backend/core/tests/documents/test_api_documents_collaboration_auth.py @@ -2,6 +2,8 @@ Test collaboration websocket access API endpoint for users in impress's core app. """ +from uuid import uuid4 + from django.test import override_settings import pytest @@ -13,6 +15,21 @@ from core.tests.conftest import TEAM, USER, VIA pytestmark = pytest.mark.django_db +def test_api_documents_collaboration_auth_unkown_document(): + """ + Trying to connect to the collaboration server on a document ID that does not exist + should not have the side effect to create it (no regression test). + """ + original_url = f"http://localhost/collaboration/ws/?room={uuid4()!s}" + + response = APIClient().get( + "/api/v1.0/documents/collaboration-auth/", HTTP_X_ORIGINAL_URL=original_url + ) + + assert response.status_code == 403 + assert models.Document.objects.exists() is False + + def test_api_documents_collaboration_auth_original_url_not_matching(): """ Trying to authenticate on the collaboration server with an invalid @@ -31,11 +48,13 @@ def test_api_documents_collaboration_auth_original_url_not_matching(): assert "X-User-Id" not in response -def test_api_documents_collaboration_auth_secret_not_defined(): +def test_api_documents_collaboration_auth_secret_not_defined(settings): """ Trying to authenticate on the collaboration server when the secret is not defined should return a 403. """ + settings.COLLABORATION_SERVER_SECRET = None + document = factories.DocumentFactory(link_reach="public") response = APIClient().get( diff --git a/src/backend/core/tests/documents/test_api_documents_media_auth.py b/src/backend/core/tests/documents/test_api_documents_media_auth.py index b4bd2fa9..25e47ed9 100644 --- a/src/backend/core/tests/documents/test_api_documents_media_auth.py +++ b/src/backend/core/tests/documents/test_api_documents_media_auth.py @@ -2,9 +2,9 @@ Test file uploads API endpoint for users in impress's core app. """ -import uuid from io import BytesIO from urllib.parse import urlparse +from uuid import uuid4 from django.conf import settings from django.core.files.storage import default_storage @@ -14,17 +14,32 @@ import pytest import requests from rest_framework.test import APIClient -from core import factories +from core import factories, models from core.tests.conftest import TEAM, USER, VIA pytestmark = pytest.mark.django_db +def test_api_documents_media_auth_unkown_document(): + """ + Trying to download a media related to a document ID that does not exist + should not have the side effect to create it (no regression test). + """ + original_url = f"http://localhost/media/{uuid4()!s}/attachments/{uuid4()!s}.jpg" + + response = APIClient().get( + "/api/v1.0/documents/media-auth/", HTTP_X_ORIGINAL_URL=original_url + ) + + assert response.status_code == 403 + assert models.Document.objects.exists() is False + + def test_api_documents_media_auth_anonymous_public(): """Anonymous users should be able to retrieve attachments linked to a public document""" document = factories.DocumentFactory(link_reach="public") - filename = f"{uuid.uuid4()!s}.jpg" + filename = f"{uuid4()!s}.jpg" key = f"{document.pk!s}/attachments/{filename:s}" default_storage.connection.meta.client.put_object( @@ -96,7 +111,7 @@ def test_api_documents_media_auth_anonymous_authenticated_or_restricted(reach): """ document = factories.DocumentFactory(link_reach=reach) - filename = f"{uuid.uuid4()!s}.jpg" + filename = f"{uuid4()!s}.jpg" media_url = f"http://localhost/media/{document.pk!s}/attachments/{filename:s}" response = APIClient().get( @@ -119,7 +134,7 @@ def test_api_documents_media_auth_authenticated_public_or_authenticated(reach): client = APIClient() client.force_login(user) - filename = f"{uuid.uuid4()!s}.jpg" + filename = f"{uuid4()!s}.jpg" key = f"{document.pk!s}/attachments/{filename:s}" default_storage.connection.meta.client.put_object( @@ -170,7 +185,7 @@ def test_api_documents_media_auth_authenticated_restricted(): client = APIClient() client.force_login(user) - filename = f"{uuid.uuid4()!s}.jpg" + filename = f"{uuid4()!s}.jpg" media_url = f"http://localhost/media/{document.pk!s}/attachments/{filename:s}" response = client.get( @@ -198,7 +213,7 @@ def test_api_documents_media_auth_related(via, mock_user_teams): mock_user_teams.return_value = ["lasuite", "unknown"] factories.TeamDocumentAccessFactory(document=document, team="lasuite") - filename = f"{uuid.uuid4()!s}.jpg" + filename = f"{uuid4()!s}.jpg" key = f"{document.pk!s}/attachments/{filename:s}" default_storage.connection.meta.client.put_object(