71 lines
2.6 KiB
Python
71 lines
2.6 KiB
Python
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
from django.core.files.base import ContentFile
|
|
from django.http import Http404
|
|
|
|
from api.v1.documents.media_delivery import document_file_response
|
|
|
|
|
|
def test_nginx_response_is_internal_escaped_and_does_not_read_file(settings, tmp_path):
|
|
settings.MEDIA_ROOT = tmp_path
|
|
settings.DOCUMENTS_USE_X_ACCEL_REDIRECT = True
|
|
path = tmp_path / "documents" / "public" / "контракт #1.pdf"
|
|
path.parent.mkdir(parents=True)
|
|
path.write_bytes(b"private document")
|
|
response = document_file_response(SimpleNamespace(path=path), filename=path.name)
|
|
assert response["X-Accel-Redirect"].startswith("/_protected_documents/public/%")
|
|
assert "%20%231.pdf" in response["X-Accel-Redirect"]
|
|
assert response.content == b""
|
|
assert response["Cache-Control"] == "private, no-store"
|
|
assert response["Content-Type"] == "application/pdf"
|
|
|
|
|
|
def test_nginx_response_rejects_outside_paths_and_missing_files(settings, tmp_path):
|
|
settings.MEDIA_ROOT = tmp_path
|
|
settings.DOCUMENTS_USE_X_ACCEL_REDIRECT = True
|
|
(tmp_path / "documents").mkdir()
|
|
outside = tmp_path / "private.env"
|
|
outside.write_bytes(b"not document data")
|
|
for path in (
|
|
outside,
|
|
tmp_path / "documents" / "missing.pdf",
|
|
tmp_path / "documents",
|
|
):
|
|
with pytest.raises(Http404):
|
|
document_file_response(SimpleNamespace(path=path), filename="file.pdf")
|
|
|
|
|
|
def test_nginx_response_rejects_symlink_escape(settings, tmp_path):
|
|
settings.MEDIA_ROOT = tmp_path
|
|
settings.DOCUMENTS_USE_X_ACCEL_REDIRECT = True
|
|
(tmp_path / "documents").mkdir()
|
|
outside = tmp_path / "private.env"
|
|
outside.write_bytes(b"not document data")
|
|
link = tmp_path / "documents" / "link.pdf"
|
|
try:
|
|
link.symlink_to(outside)
|
|
except OSError:
|
|
pytest.skip("Creating symlinks is unavailable on this host")
|
|
with pytest.raises(Http404):
|
|
document_file_response(SimpleNamespace(path=link), filename="file.pdf")
|
|
|
|
|
|
@pytest.mark.parametrize("accelerated", [True, False])
|
|
@pytest.mark.django_db
|
|
def test_document_file_response_supports_nonlocal_storage(settings, accelerated):
|
|
settings.DOCUMENTS_USE_X_ACCEL_REDIRECT = accelerated
|
|
|
|
class RemoteFile:
|
|
@property
|
|
def path(self):
|
|
raise NotImplementedError
|
|
|
|
def open(self, mode):
|
|
return ContentFile(b"authorized remote content", name="document.pdf")
|
|
|
|
response = document_file_response(RemoteFile(), filename="document.pdf")
|
|
assert "X-Accel-Redirect" not in response
|
|
assert b"".join(response.streaming_content) == b"authorized remote content"
|
|
response.close()
|