infrasynth-backend-kit/tests/test_files/test_services.py
jcv-dev 551b42eab5 feat: production-hardening pass across the kit
Close the gaps between the documented contract (API-STANDARD, TENANCY,
ENTITLEMENTS) and the implementation, and remove committed build artifacts.

Security:
- verify + process inbound webhooks (HMAC/handler verify, size limit,
  timestamp tolerance, idempotency via InboundEvent.external_id)
- real 2FA login flow (pre-auth challenge; tokens only after verify/recovery)
- wire HybridPermission into security/audit views; add API-key rotate and
  users/<id>/permissions|roles endpoints
- tenant-scoped throttling on by default; webhook replay protection
- verify MercadoPago webhook signatures
- login brute-force guard, configurable password policy, real ALTCHA PoW

Correctness:
- apply verified billing webhooks idempotently (subscription/entitlement/
  invoice/PaymentTransaction); scheduled payment lifecycle jobs
- capture audit update diffs automatically; add audit retention purge
- working notification retries, per-channel rate limits, log retention
- pluggable virus scanner, upload-size limit, pipeline toggle
- feature rollout %/environment targeting; settings-driven registrations
- workflow guards (instance cap, route depth, self-assignment, clone on re-entry)
- wire every previously-dead INFRASYNTH_* setting; drop truly dead ones

Delivery:
- README + CHANGELOG; CI format check + coverage gate
- keep test media out of the tree; untrack .coverage, __pycache__,
  egg-info, docs/ and invoice artifacts
2026-09-24 10:41:21 -05:00

185 lines
8.2 KiB
Python

import hashlib
from unittest import mock
import pytest
from django.core.files.uploadedfile import SimpleUploadedFile
from infrasynth.files.models import FileCategory, StoredFile
from infrasynth.files.services import FileService
from infrasynth.files.signals import file_deleted, file_uploaded
pytestmark = pytest.mark.django_db
def _make_pdf(name="doc.pdf", content=b"%PDF-1.4 test content"):
return SimpleUploadedFile(name, content, content_type="application/pdf")
@pytest.fixture
def upload_signals():
sent = []
receiver = lambda **kw: sent.append(kw) # noqa: E731
file_uploaded.connect(receiver, weak=False)
yield sent
file_uploaded.disconnect(receiver)
class TestUpload:
def test_upload_creates_stored_file(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
assert StoredFile.objects.filter(pk=stored.id).exists()
assert stored.original_filename == "doc.pdf"
assert stored.mime_type == "application/pdf"
assert stored.size_bytes == len(b"%PDF-1.4 test content")
assert stored.storage_backend == "local"
assert stored.storage_key.startswith(stored.storage_key.split("/")[0] + "/")
assert stored.storage_key.endswith("doc.pdf")
assert stored.checksum_sha256 == hashlib.sha256(b"%PDF-1.4 test content").hexdigest()
def test_upload_with_category_uses_storage_path(self, user, media_root):
category = FileCategory.objects.create(slug="contracts", name="Contracts", storage_path="contracts")
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user, category_slug="contracts")
assert stored.category_id == category.pk
assert stored.storage_key.startswith("contracts/")
def test_upload_rejects_invalid_extension(self, user, media_root):
FileCategory.objects.create(
slug="pdfs",
name="PDFs",
storage_path="pdfs",
allowed_extensions="pdf",
)
with pytest.raises(ValueError, match="not allowed"):
FileService().upload(_make_pdf("image.png"), filename="image.png", category_slug="pdfs")
def test_upload_rejects_oversized_file(self, user, media_root):
FileCategory.objects.create(
slug="small",
name="Small",
storage_path="small",
allowed_extensions="pdf",
max_size_bytes=10,
)
with pytest.raises(ValueError, match="exceeds max size"):
FileService().upload(_make_pdf(), filename="doc.pdf", category_slug="small")
def test_upload_inactive_category_rejected(self, user, media_root):
FileCategory.objects.create(slug="inactive", name="Inactive", storage_path="x", is_active=False)
with pytest.raises(ValueError, match="not found or inactive"):
FileService().upload(_make_pdf(), filename="doc.pdf", category_slug="inactive")
def test_upload_emits_signal(self, user, media_root, upload_signals):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
assert upload_signals
assert upload_signals[0]["file_id"] == stored.id
assert upload_signals[0]["filename"] == "doc.pdf"
def test_upload_file_is_stored_on_disk(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
path = media_root / stored.storage_key
assert path.exists()
assert path.read_bytes() == b"%PDF-1.4 test content"
class TestSignedUrl:
def test_generates_url(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
url = FileService().get_signed_url(stored.id)
assert "media" in url
assert stored.storage_key.split("/")[-1] in url
class TestDownload:
def test_local_file_returns_file_response(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
request = type("R", (), {})()
response = FileService().get_download_response(stored, request)
assert response.status_code == 200
assert "attachment" in response["Content-Disposition"]
body = b"".join(response.streaming_content)
assert body == b"%PDF-1.4 test content"
def test_non_local_redirects_to_signed_url(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
stored.storage_backend = "S3"
stored.save(update_fields=["storage_backend"])
with mock.patch(
"infrasynth.files.services.get_storage_backend",
return_value=mock.Mock(generate_signed_url=lambda key, exp: "https://signed/url"),
):
request = type("R", (), {})()
response = FileService().get_download_response(stored, request)
assert response.status_code == 302
assert response.url == "https://signed/url"
def test_x_sendfile_enabled(self, user, media_root, settings):
settings.INFRASYNTH_FILES = {
**settings.INFRASYNTH_FILES,
"ENABLE_X_SENDFILE": True,
}
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
request = type("R", (), {})()
response = FileService().get_download_response(stored, request)
assert response["X-Sendfile"] == stored.storage_key
class TestDelete:
def test_soft_delete_marks_metadata(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
assert FileService().delete(stored, soft=True) is True
stored.refresh_from_db()
assert stored.metadata.get("is_deleted") is True
assert StoredFile.objects.filter(pk=stored.pk).exists()
def test_hard_delete_removes_row_and_file(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
path = media_root / stored.storage_key
assert path.exists()
assert FileService().delete(stored, soft=False) is True
assert not StoredFile.objects.filter(pk=stored.pk).exists()
assert not path.exists()
def test_delete_emits_signal(self, user, media_root):
sent = []
receiver = lambda **kw: sent.append(kw) # noqa: E731
file_deleted.connect(receiver, weak=False)
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user)
FileService().delete(stored, soft=False)
assert sent
assert sent[0]["file_id"] == stored.id
file_deleted.disconnect(receiver)
class TestGetFileInfo:
def test_returns_full_metadata(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user, is_public=True)
info = FileService().get_file_info(stored)
assert info["id"] == stored.id
assert info["original_filename"] == "doc.pdf"
assert info["is_public"] is True
assert info["uploaded_by"]["id"] == user.id
assert info["category"] is None
assert info["created_at"]
def test_info_with_category(self, user, media_root):
FileCategory.objects.create(slug="docs", name="Docs", storage_path="docs")
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user, category_slug="docs")
info = FileService().get_file_info(stored)
assert info["category"] == {"slug": "docs", "name": "Docs"}
class TestPipelineScheduling:
def test_schedules_pipeline_execution(self, user, media_root):
from infrasynth.files.models import PipelineExecution, ProcessingPipeline
pipeline = ProcessingPipeline.objects.create(name="Noop", slug="noop", steps=[])
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user, pipeline_slug="noop")
execution = PipelineExecution.objects.get(file=stored)
assert execution.pipeline_id == pipeline.id
assert execution.status == PipelineExecution.Status.COMPLETED
def test_unknown_pipeline_ignored(self, user, media_root):
stored = FileService().upload(_make_pdf(), filename="doc.pdf", user=user, pipeline_slug="does-not-exist")
from infrasynth.files.models import PipelineExecution
assert not PipelineExecution.objects.filter(file=stored).exists()