diff --git a/pyproject.toml b/pyproject.toml index c9bd7b7d1..7e8ad1f61 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -239,9 +239,6 @@ lint.per-file-ignores."src/paperless/checks.py" = [ lint.per-file-ignores."src/paperless/settings.py" = [ "PTH", ] # TODO Enable & remove -lint.per-file-ignores."src/paperless/views.py" = [ - "PTH", -] # TODO Enable & remove lint.per-file-ignores."src/paperless_mail/mail.py" = [ "PTH", ] # TODO Enable & remove diff --git a/src/paperless/tests/test_views.py b/src/paperless/tests/test_views.py new file mode 100644 index 000000000..76bf694fc --- /dev/null +++ b/src/paperless/tests/test_views.py @@ -0,0 +1,25 @@ +import tempfile +from pathlib import Path + +from django.conf import settings + + +def test_favicon_view(client): + with tempfile.TemporaryDirectory() as tmpdir: + static_dir = Path(tmpdir) + favicon_path = static_dir / "paperless" / "img" / "favicon.ico" + favicon_path.parent.mkdir(parents=True, exist_ok=True) + favicon_path.write_bytes(b"FAKE ICON DATA") + + settings.STATIC_ROOT = static_dir + + response = client.get("/favicon.ico") + assert response.status_code == 200 + assert response["Content-Type"] == "image/x-icon" + assert b"".join(response.streaming_content) == b"FAKE ICON DATA" + + +def test_favicon_view_missing_file(client): + settings.STATIC_ROOT = Path(tempfile.mkdtemp()) + response = client.get("/favicon.ico") + assert response.status_code == 404 diff --git a/src/paperless/views.py b/src/paperless/views.py index 050bb3f61..4d102029f 100644 --- a/src/paperless/views.py +++ b/src/paperless/views.py @@ -1,5 +1,5 @@ -import os from collections import OrderedDict +from pathlib import Path from allauth.mfa import signals from allauth.mfa.adapter import get_adapter as get_mfa_adapter @@ -11,8 +11,9 @@ from allauth.socialaccount.adapter import get_adapter from allauth.socialaccount.models import SocialAccount from django.contrib.auth.models import Group from django.contrib.auth.models import User +from django.contrib.staticfiles.storage import staticfiles_storage from django.db.models.functions import Lower -from django.http import HttpResponse +from django.http import FileResponse from django.http import HttpResponseBadRequest from django.http import HttpResponseForbidden from django.http import HttpResponseNotFound @@ -92,16 +93,12 @@ class StandardPagination(PageNumberPagination): class FaviconView(View): - def get(self, request, *args, **kwargs): # pragma: no cover - favicon = os.path.join( - os.path.dirname(__file__), - "static", - "paperless", - "img", - "favicon.ico", - ) - with open(favicon, "rb") as f: - return HttpResponse(f, content_type="image/x-icon") + def get(self, request, *args, **kwargs): + try: + path = Path(staticfiles_storage.path("paperless/img/favicon.ico")) + return FileResponse(path.open("rb"), content_type="image/x-icon") + except FileNotFoundError: + return HttpResponseNotFound("favicon.ico not found") class UserViewSet(ModelViewSet):