|
6 | 6 | from urllib.parse import urlparse |
7 | 7 | from uuid import uuid4 |
8 | 8 |
|
9 | | -from django.conf import settings |
10 | 9 | from django.core.files.storage import default_storage |
11 | 10 | from django.utils import timezone |
12 | 11 |
|
@@ -37,7 +36,7 @@ def test_api_documents_media_auth_unkown_document(): |
37 | 36 | assert models.Document.objects.exists() is False |
38 | 37 |
|
39 | 38 |
|
40 | | -def test_api_documents_media_auth_anonymous_public(): |
| 39 | +def test_api_documents_media_auth_anonymous_public(settings): |
41 | 40 | """Anonymous users should be able to retrieve attachments linked to a public document""" |
42 | 41 | document_id = uuid4() |
43 | 42 | filename = f"{uuid4()!s}.jpg" |
@@ -139,7 +138,7 @@ def test_api_documents_media_auth_anonymous_authenticated_or_restricted(reach): |
139 | 138 | assert "Authorization" not in response |
140 | 139 |
|
141 | 140 |
|
142 | | -def test_api_documents_media_auth_anonymous_attachments(): |
| 141 | +def test_api_documents_media_auth_anonymous_attachments(settings): |
143 | 142 | """ |
144 | 143 | Declaring a media key as original attachment on a document to which |
145 | 144 | a user has access should give them access to the attachment file |
@@ -202,7 +201,9 @@ def test_api_documents_media_auth_anonymous_attachments(): |
202 | 201 |
|
203 | 202 |
|
204 | 203 | @pytest.mark.parametrize("reach", ["public", "authenticated"]) |
205 | | -def test_api_documents_media_auth_authenticated_public_or_authenticated(reach): |
| 204 | +def test_api_documents_media_auth_authenticated_public_or_authenticated( |
| 205 | + reach, settings |
| 206 | +): |
206 | 207 | """ |
207 | 208 | Authenticated users who are not related to a document should be able to retrieve |
208 | 209 | attachments related to a document with public or authenticated link reach. |
@@ -284,7 +285,7 @@ def test_api_documents_media_auth_authenticated_restricted(): |
284 | 285 |
|
285 | 286 |
|
286 | 287 | @pytest.mark.parametrize("via", VIA) |
287 | | -def test_api_documents_media_auth_related(via, mock_user_teams): |
| 288 | +def test_api_documents_media_auth_related(via, mock_user_teams, settings): |
288 | 289 | """ |
289 | 290 | Users who have a specific access to a document, whatever the role, should be able to |
290 | 291 | retrieve related attachments. |
@@ -368,7 +369,7 @@ def test_api_documents_media_auth_not_ready_status(): |
368 | 369 | assert response.status_code == 403 |
369 | 370 |
|
370 | 371 |
|
371 | | -def test_api_documents_media_auth_missing_status_metadata(): |
| 372 | +def test_api_documents_media_auth_missing_status_metadata(settings): |
372 | 373 | """Attachments without status metadata should be considered as ready""" |
373 | 374 | document_id = uuid4() |
374 | 375 | filename = f"{uuid4()!s}.jpg" |
@@ -412,3 +413,51 @@ def test_api_documents_media_auth_missing_status_metadata(): |
412 | 413 | timeout=1, |
413 | 414 | ) |
414 | 415 | assert response.content.decode("utf-8") == "my prose" |
| 416 | + |
| 417 | + |
| 418 | +def test_api_documents_media_auth_anonymous_public_custom_origin_header(settings): |
| 419 | + """Changing the setting MEDIA_AUTH_ORIGINAL_URL_HEADER to match other header should work""" |
| 420 | + settings.MEDIA_AUTH_ORIGINAL_URL_HEADER = "HTTP_X_FORWARDED_URI" |
| 421 | + document_id = uuid4() |
| 422 | + filename = f"{uuid4()!s}.jpg" |
| 423 | + key = f"{document_id!s}/attachments/{filename:s}" |
| 424 | + default_storage.connection.meta.client.put_object( |
| 425 | + Bucket=default_storage.bucket_name, |
| 426 | + Key=key, |
| 427 | + Body=BytesIO(b"my prose"), |
| 428 | + ContentType="text/plain", |
| 429 | + Metadata={"status": DocumentAttachmentStatus.READY}, |
| 430 | + ) |
| 431 | + |
| 432 | + factories.DocumentFactory(id=document_id, link_reach="public", attachments=[key]) |
| 433 | + |
| 434 | + original_url = f"http://localhost/media/{key:s}" |
| 435 | + now = timezone.now() |
| 436 | + with freeze_time(now): |
| 437 | + response = APIClient().get( |
| 438 | + "/api/v1.0/documents/media-auth/", HTTP_X_FORWARDED_URI=original_url |
| 439 | + ) |
| 440 | + |
| 441 | + assert response.status_code == 200 |
| 442 | + |
| 443 | + authorization = response["Authorization"] |
| 444 | + assert "AWS4-HMAC-SHA256 Credential=" in authorization |
| 445 | + assert ( |
| 446 | + "SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=" |
| 447 | + in authorization |
| 448 | + ) |
| 449 | + assert response["X-Amz-Date"] == now.strftime("%Y%m%dT%H%M%SZ") |
| 450 | + |
| 451 | + s3_url = urlparse(settings.AWS_S3_ENDPOINT_URL) |
| 452 | + file_url = f"{settings.AWS_S3_ENDPOINT_URL:s}/impress-media-storage/{key:s}" |
| 453 | + response = requests.get( |
| 454 | + file_url, |
| 455 | + headers={ |
| 456 | + "authorization": authorization, |
| 457 | + "x-amz-date": response["x-amz-date"], |
| 458 | + "x-amz-content-sha256": response["x-amz-content-sha256"], |
| 459 | + "Host": f"{s3_url.hostname:s}:{s3_url.port:d}", |
| 460 | + }, |
| 461 | + timeout=1, |
| 462 | + ) |
| 463 | + assert response.content.decode("utf-8") == "my prose" |
0 commit comments