mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-05-07 23:25:25 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 869151e455 |
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: lewagon/wait-on-check-action@9312864dfbc9fd208e9c0417843430751c042800 # v1.7.0
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
check-name: 'Merge and Push Manifest'
|
||||
check-name: 'Build Docker Image'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
wait-interval: 60
|
||||
build-release:
|
||||
@@ -177,7 +177,7 @@ jobs:
|
||||
version: ${{ steps.get-version.outputs.version }}
|
||||
prerelease: ${{ steps.get-version.outputs.prerelease }}
|
||||
publish: true
|
||||
commitish: ${{ steps.get-version.outputs.prerelease == 'true' && 'dev' || 'main' }}
|
||||
commitish: main
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload release archive
|
||||
|
||||
@@ -117,6 +117,17 @@ def preview_last_modified(request, pk: int) -> datetime | None:
|
||||
return doc.modified
|
||||
|
||||
|
||||
def thumbnail_etag(request: Any, pk: int) -> str | None:
|
||||
"""
|
||||
Thumbnails are version-dependent, so use the effective document checksum as
|
||||
the ETag to invalidate cache when the latest version changes.
|
||||
"""
|
||||
doc = resolve_effective_document_by_pk(pk, request).document
|
||||
if doc is None:
|
||||
return None
|
||||
return doc.checksum
|
||||
|
||||
|
||||
def thumbnail_last_modified(request: Any, pk: int) -> datetime | None:
|
||||
"""
|
||||
Returns the filesystem last modified either from cache or from filesystem.
|
||||
|
||||
@@ -464,6 +464,40 @@ class TestDocumentVersioningApi(DirectoriesMixin, APITestCase):
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(read_streaming_response(resp), b"thumb")
|
||||
|
||||
def test_thumb_etag_changes_when_latest_version_is_deleted(self) -> None:
|
||||
root = self._create_pdf(title="root", checksum="root")
|
||||
v1 = self._create_pdf(
|
||||
title="v1",
|
||||
checksum="v1",
|
||||
root_document=root,
|
||||
)
|
||||
v2 = self._create_pdf(
|
||||
title="v2",
|
||||
checksum="v2",
|
||||
root_document=root,
|
||||
)
|
||||
self._write_file(v1.thumbnail_path, b"thumb-v1")
|
||||
self._write_file(v2.thumbnail_path, b"thumb-v2")
|
||||
|
||||
resp = self.client.get(f"/api/documents/{root.id}/thumb/")
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(read_streaming_response(resp), b"thumb-v2")
|
||||
self.assertEqual(resp.headers["ETag"], '"v2"')
|
||||
|
||||
with mock.patch("documents.search.get_backend"):
|
||||
delete_resp = self.client.delete(
|
||||
f"/api/documents/{root.id}/versions/{v2.id}/",
|
||||
)
|
||||
self.assertEqual(delete_resp.status_code, status.HTTP_200_OK)
|
||||
|
||||
resp = self.client.get(
|
||||
f"/api/documents/{root.id}/thumb/",
|
||||
HTTP_IF_NONE_MATCH='"v2"',
|
||||
)
|
||||
self.assertEqual(resp.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(resp.headers["ETag"], '"v1"')
|
||||
self.assertEqual(read_streaming_response(resp), b"thumb-v1")
|
||||
|
||||
def test_metadata_version_param_uses_version(self) -> None:
|
||||
root = Document.objects.create(
|
||||
title="root",
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.test import TestCase
|
||||
|
||||
from documents.conditionals import metadata_etag
|
||||
from documents.conditionals import preview_etag
|
||||
from documents.conditionals import thumbnail_etag
|
||||
from documents.conditionals import thumbnail_last_modified
|
||||
from documents.models import Document
|
||||
from documents.tests.utils import DirectoriesMixin
|
||||
@@ -30,6 +31,7 @@ class TestConditionals(DirectoriesMixin, TestCase):
|
||||
|
||||
self.assertEqual(metadata_etag(request, root.id), latest.checksum)
|
||||
self.assertEqual(preview_etag(request, root.id), latest.archive_checksum)
|
||||
self.assertEqual(thumbnail_etag(request, root.id), latest.checksum)
|
||||
|
||||
def test_resolve_effective_doc_returns_none_for_invalid_or_unrelated_version(
|
||||
self,
|
||||
|
||||
@@ -67,7 +67,6 @@ from django.views import View
|
||||
from django.views.decorators.cache import cache_control
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import condition
|
||||
from django.views.decorators.http import last_modified
|
||||
from django.views.generic import TemplateView
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.openapi import AutoSchema
|
||||
@@ -124,6 +123,7 @@ from documents.conditionals import preview_etag
|
||||
from documents.conditionals import preview_last_modified
|
||||
from documents.conditionals import suggestions_etag
|
||||
from documents.conditionals import suggestions_last_modified
|
||||
from documents.conditionals import thumbnail_etag
|
||||
from documents.conditionals import thumbnail_last_modified
|
||||
from documents.data_models import ConsumableDocument
|
||||
from documents.data_models import DocumentMetadataOverrides
|
||||
@@ -1564,7 +1564,12 @@ class DocumentViewSet(
|
||||
|
||||
@action(methods=["get"], detail=True, filter_backends=[])
|
||||
@method_decorator(cache_control(no_cache=True))
|
||||
@method_decorator(last_modified(thumbnail_last_modified))
|
||||
@method_decorator(
|
||||
condition(
|
||||
etag_func=thumbnail_etag,
|
||||
last_modified_func=thumbnail_last_modified,
|
||||
),
|
||||
)
|
||||
def thumb(self, request, pk=None):
|
||||
resolved = self._resolve_request_and_root_doc(pk, request)
|
||||
if isinstance(resolved, HttpResponseForbidden):
|
||||
|
||||
Reference in New Issue
Block a user