diff --git a/docs/api.md b/docs/api.md index 9c28476c4..2d323899c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -413,3 +413,11 @@ Initial API version. list of strings. When creating or updating a custom field value of a document for a select type custom field, the value should be the `id` of the option whereas previously was the index of the option. + +#### Version 8 + +- PaperlessTask objects now have a `task_name` field which replaces the old + `type` field. The `type` field is now used to represent the way the task + was created. Additionally, the tasks endpoint now returns different types + of tasks other than simply 'file' tasks. See the API schema for more + information. diff --git a/src-ui/src/environments/environment.prod.ts b/src-ui/src/environments/environment.prod.ts index 9db14f6c3..a7639a7b6 100644 --- a/src-ui/src/environments/environment.prod.ts +++ b/src-ui/src/environments/environment.prod.ts @@ -3,7 +3,7 @@ const base_url = new URL(document.baseURI) export const environment = { production: true, apiBaseUrl: document.baseURI + 'api/', - apiVersion: '7', + apiVersion: '8', appTitle: 'Paperless-ngx', version: '2.14.7', webSocketHost: window.location.host, diff --git a/src-ui/src/environments/environment.ts b/src-ui/src/environments/environment.ts index 2cad64ce0..1f3427de7 100644 --- a/src-ui/src/environments/environment.ts +++ b/src-ui/src/environments/environment.ts @@ -5,7 +5,7 @@ export const environment = { production: false, apiBaseUrl: 'http://localhost:8000/api/', - apiVersion: '7', + apiVersion: '8', appTitle: 'Paperless-ngx', version: 'DEVELOPMENT', webSocketHost: 'localhost:8000', diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index a67673efc..ccc6f65ae 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -421,6 +421,15 @@ class OwnedObjectListSerializer(serializers.ListSerializer): return super().to_representation(documents) +class GetAPIVersionMixin: + def get_api_version(self): + return int( + self.context.get("request").version + if self.context.get("request") + else settings.REST_FRAMEWORK["DEFAULT_VERSION"], + ) + + class CorrespondentSerializer(MatchingModelSerializer, OwnedObjectSerializer): last_correspondence = serializers.DateTimeField(read_only=True, required=False) @@ -717,7 +726,7 @@ class ReadWriteSerializerMethodField(serializers.SerializerMethodField): return {self.field_name: data} -class CustomFieldInstanceSerializer(serializers.ModelSerializer): +class CustomFieldInstanceSerializer(serializers.ModelSerializer, GetAPIVersionMixin): field = serializers.PrimaryKeyRelatedField(queryset=CustomField.objects.all()) value = ReadWriteSerializerMethodField(allow_null=True) @@ -809,13 +818,6 @@ class CustomFieldInstanceSerializer(serializers.ModelSerializer): return data - def get_api_version(self): - return int( - self.context.get("request").version - if self.context.get("request") - else settings.REST_FRAMEWORK["DEFAULT_VERSION"], - ) - def to_internal_value(self, data): ret = super().to_internal_value(data) @@ -1709,7 +1711,7 @@ class UiSettingsViewSerializer(serializers.ModelSerializer): return ui_settings -class TasksViewSerializer(OwnedObjectSerializer): +class TasksViewSerializer(OwnedObjectSerializer, GetAPIVersionMixin): class Meta: model = PaperlessTask fields = ( @@ -1752,6 +1754,13 @@ class TasksViewSerializer(OwnedObjectSerializer): return result + def to_representation(self, instance: PaperlessTask): + result = super().to_representation(instance) + if self.get_api_version() < 8: + # Older versions only returned file tasks (filtering handled in view) and had different naming scheme + result["type"] = "file" + return result + class RunTaskViewSerializer(serializers.Serializer): task_name = serializers.ChoiceField( diff --git a/src/documents/tests/test_api_tasks.py b/src/documents/tests/test_api_tasks.py index c139d05da..575fa3c3f 100644 --- a/src/documents/tests/test_api_tasks.py +++ b/src/documents/tests/test_api_tasks.py @@ -370,3 +370,45 @@ class TestTasks(DirectoriesMixin, APITestCase): self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) mock_check_sanity.assert_not_called() + + def test_handle_older_api_version(self): + """ + GIVEN: + - A request from the API with version < 8 + WHEN: + - Tasks are requested + THEN: + - Only consume file tasks are returned and the type is 'file' + """ + + task1 = PaperlessTask.objects.create( + task_id=str(uuid.uuid4()), + task_file_name="task_one.pdf", + task_name=PaperlessTask.TaskName.CONSUME_FILE, + ) + + task2 = PaperlessTask.objects.create( + task_id=str(uuid.uuid4()), + task_name=PaperlessTask.TaskName.CHECK_SANITY, + type=PaperlessTask.TaskType.AUTO, + ) + + response = self.client.get( + self.ENDPOINT, + headers={"Accept": "application/json; version=7"}, + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]["task_id"], task1.task_id) + self.assertEqual(response.data[0]["type"], "file") + + response = self.client.get( + self.ENDPOINT, + headers={"Accept": "application/json; version=8"}, + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 2) + self.assertEqual(response.data[0]["task_id"], task2.task_id) + self.assertEqual(response.data[0]["type"], PaperlessTask.TaskType.AUTO) diff --git a/src/documents/views.py b/src/documents/views.py index 1d4cb52dd..3401a0095 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -2287,6 +2287,7 @@ class TasksViewSet(ReadOnlyModelViewSet): ObjectOwnedOrGrantedPermissionsFilter, ) filterset_class = PaperlessTaskFilterSet + queryset = PaperlessTask.objects.all().order_by("-date_created") TASK_AND_ARGS_BY_NAME = { PaperlessTask.TaskName.INDEX_OPTIMIZE: (index_optimize, {}), @@ -2301,11 +2302,22 @@ class TasksViewSet(ReadOnlyModelViewSet): } def get_queryset(self): - queryset = PaperlessTask.objects.all().order_by("-date_created") task_id = self.request.query_params.get("task_id") if task_id is not None: - queryset = PaperlessTask.objects.filter(task_id=task_id) - return queryset + return PaperlessTask.objects.filter(task_id=task_id) + return super().get_queryset() + + def list(self, request, *args, **kwargs): + version = int( + request.version if request else settings.REST_FRAMEWORK["DEFAULT_VERSION"], + ) + if version < 8: + # Previous API versions only had file tasks, the format is also different (handled in serializer) + self.queryset = PaperlessTask.objects.filter( + task_name=PaperlessTask.TaskName.CONSUME_FILE, + ).order_by("-date_created") + + return super().list(request, *args, **kwargs) @action(methods=["post"], detail=False) def acknowledge(self, request): diff --git a/src/paperless/settings.py b/src/paperless/settings.py index ff1829528..ab8f8f4e3 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -345,7 +345,7 @@ REST_FRAMEWORK = { "DEFAULT_VERSION": "7", # Make sure these are ordered and that the most recent version appears # last. See api.md#api-versioning when adding new versions. - "ALLOWED_VERSIONS": ["1", "2", "3", "4", "5", "6", "7"], + "ALLOWED_VERSIONS": ["1", "2", "3", "4", "5", "6", "7", "8"], # DRF Spectacular default schema "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", }