diff --git a/src-ui/src/app/services/tasks.service.spec.ts b/src-ui/src/app/services/tasks.service.spec.ts index 41a374831..d746707b7 100644 --- a/src-ui/src/app/services/tasks.service.spec.ts +++ b/src-ui/src/app/services/tasks.service.spec.ts @@ -48,7 +48,7 @@ describe('TasksService', () => { it('calls acknowledge_tasks api endpoint on dismiss and reloads', () => { tasksService.dismissTasks(new Set([1, 2, 3])) const req = httpTestingController.expectOne( - `${environment.apiBaseUrl}acknowledge_tasks/` + `${environment.apiBaseUrl}tasks/acknowledge/` ) expect(req.request.method).toEqual('POST') expect(req.request.body).toEqual({ diff --git a/src-ui/src/app/services/tasks.service.ts b/src-ui/src/app/services/tasks.service.ts index e2c064e03..c3c8f1d2b 100644 --- a/src-ui/src/app/services/tasks.service.ts +++ b/src-ui/src/app/services/tasks.service.ts @@ -64,7 +64,7 @@ export class TasksService { public dismissTasks(task_ids: Set) { this.http - .post(`${this.baseUrl}acknowledge_tasks/`, { + .post(`${this.baseUrl}tasks/acknowledge/`, { tasks: [...task_ids], }) .pipe(first()) diff --git a/src/documents/tests/test_api_tasks.py b/src/documents/tests/test_api_tasks.py index 52ffb09fe..dd5425278 100644 --- a/src/documents/tests/test_api_tasks.py +++ b/src/documents/tests/test_api_tasks.py @@ -1,6 +1,7 @@ import uuid import celery +from django.contrib.auth.models import Permission from django.contrib.auth.models import User from rest_framework import status from rest_framework.test import APITestCase @@ -11,7 +12,6 @@ from documents.tests.utils import DirectoriesMixin class TestTasks(DirectoriesMixin, APITestCase): ENDPOINT = "/api/tasks/" - ENDPOINT_ACKNOWLEDGE = "/api/acknowledge_tasks/" def setUp(self): super().setUp() @@ -125,7 +125,7 @@ class TestTasks(DirectoriesMixin, APITestCase): self.assertEqual(len(response.data), 1) response = self.client.post( - self.ENDPOINT_ACKNOWLEDGE, + self.ENDPOINT + "acknowledge/", {"tasks": [task.id]}, ) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -133,6 +133,52 @@ class TestTasks(DirectoriesMixin, APITestCase): response = self.client.get(self.ENDPOINT) self.assertEqual(len(response.data), 0) + def test_tasks_owner_aware(self): + """ + GIVEN: + - Existing PaperlessTasks with owner and with no owner + WHEN: + - API call is made to get tasks + THEN: + - Only tasks with no owner or request user are returned + """ + + regular_user = User.objects.create_user(username="test") + regular_user.user_permissions.add(*Permission.objects.all()) + self.client.logout() + self.client.force_authenticate(user=regular_user) + + task1 = PaperlessTask.objects.create( + task_id=str(uuid.uuid4()), + task_file_name="task_one.pdf", + owner=self.user, + ) + + task2 = PaperlessTask.objects.create( + task_id=str(uuid.uuid4()), + task_file_name="task_two.pdf", + ) + + task3 = PaperlessTask.objects.create( + task_id=str(uuid.uuid4()), + task_file_name="task_three.pdf", + owner=regular_user, + ) + + response = self.client.get(self.ENDPOINT) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 2) + self.assertEqual(response.data[0]["task_id"], task3.task_id) + self.assertEqual(response.data[1]["task_id"], task2.task_id) + + acknowledge_response = self.client.post( + self.ENDPOINT + "acknowledge/", + {"tasks": [task1.id, task2.id, task3.id]}, + ) + self.assertEqual(acknowledge_response.status_code, status.HTTP_200_OK) + self.assertEqual(acknowledge_response.data, {"result": 2}) + def test_task_result_no_error(self): """ GIVEN: diff --git a/src/documents/views.py b/src/documents/views.py index 2d0c030f4..332d5f64a 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -1705,6 +1705,7 @@ class RemoteVersionView(GenericAPIView): class TasksViewSet(ReadOnlyModelViewSet): permission_classes = (IsAuthenticated, PaperlessObjectPermissions) serializer_class = TasksViewSerializer + filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,) def get_queryset(self): queryset = ( @@ -1719,19 +1720,17 @@ class TasksViewSet(ReadOnlyModelViewSet): queryset = PaperlessTask.objects.filter(task_id=task_id) return queryset - -class AcknowledgeTasksView(GenericAPIView): - permission_classes = (IsAuthenticated,) - serializer_class = AcknowledgeTasksViewSerializer - - def post(self, request, *args, **kwargs): - serializer = self.get_serializer(data=request.data) + @action(methods=["post"], detail=False) + def acknowledge(self, request): + serializer = AcknowledgeTasksViewSerializer(data=request.data) serializer.is_valid(raise_exception=True) - - tasks = serializer.validated_data.get("tasks") + task_ids = serializer.validated_data.get("tasks") try: - result = PaperlessTask.objects.filter(id__in=tasks).update( + tasks = PaperlessTask.objects.filter(id__in=task_ids) + if request.user is not None and not request.user.is_superuser: + tasks = tasks.filter(owner=request.user) | tasks.filter(owner=None) + result = tasks.update( acknowledged=True, ) return Response({"result": result}) diff --git a/src/paperless/urls.py b/src/paperless/urls.py index 2ebd7e739..5b7327b8d 100644 --- a/src/paperless/urls.py +++ b/src/paperless/urls.py @@ -18,7 +18,6 @@ from django.views.static import serve from rest_framework.authtoken import views from rest_framework.routers import DefaultRouter -from documents.views import AcknowledgeTasksView from documents.views import BulkDownloadView from documents.views import BulkEditObjectsView from documents.views import BulkEditView @@ -132,11 +131,6 @@ urlpatterns = [ name="remoteversion", ), re_path("^ui_settings/", UiSettingsView.as_view(), name="ui_settings"), - re_path( - "^acknowledge_tasks/", - AcknowledgeTasksView.as_view(), - name="acknowledge_tasks", - ), re_path( "^mail_accounts/test/", MailAccountTestView.as_view(),