Skip to content

Commit 5152d26

Browse files
committed
♻️ [#499] Refactor auditlog endpoint
1 parent 8e2983e commit 5152d26

File tree

10 files changed

+83
-43
lines changed

10 files changed

+83
-43
lines changed

backend/src/openarchiefbeheer/api/urls.py

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
DestructionListViewSet,
2525
ReviewResponseViewSet,
2626
)
27+
from openarchiefbeheer.logging.api.viewsets import LogsViewset
2728
from openarchiefbeheer.selection.api.views import (
2829
SelectionCountView,
2930
SelectionSelectAllView,
@@ -71,6 +72,7 @@
7172
basename="review-responses",
7273
)
7374
router.register(r"zaken", ZakenViewSet, basename="zaken")
75+
router.register(r"logs", LogsViewset, basename="logs")
7476

7577
destruction_list_router = BulkNestedRouter(
7678
router, r"destruction-lists", lookup="destruction_list"

backend/src/openarchiefbeheer/destruction/api/serializers.py

-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from rest_framework import serializers
1111
from rest_framework.exceptions import ValidationError
1212
from rest_framework.relations import SlugRelatedField
13-
from timeline_logger.models import TimelineLog
1413

1514
from openarchiefbeheer.accounts.api.serializers import UserSerializer
1615
from openarchiefbeheer.accounts.models import User
@@ -858,21 +857,6 @@ def create(self, validated_data: dict) -> ReviewResponse:
858857
return review_response
859858

860859

861-
class AuditTrailItemSerializer(serializers.ModelSerializer):
862-
message = serializers.CharField(source="get_message")
863-
user = UserSerializer()
864-
865-
class Meta:
866-
model = TimelineLog
867-
fields = (
868-
"pk",
869-
"timestamp",
870-
"user",
871-
"message",
872-
"extra_data",
873-
)
874-
875-
876860
class AbortDestructionSerializer(serializers.Serializer):
877861
comment = serializers.CharField(required=True, allow_blank=False)
878862

backend/src/openarchiefbeheer/destruction/api/viewsets.py

-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from datetime import date, timedelta
22

3-
from django.contrib.contenttypes.models import ContentType
43
from django.db import transaction
54
from django.db.models import Case, OuterRef, Prefetch, QuerySet, Subquery, Value, When
65
from django.shortcuts import get_object_or_404
@@ -13,7 +12,6 @@
1312
from rest_framework.exceptions import ValidationError
1413
from rest_framework.permissions import IsAuthenticated
1514
from rest_framework.response import Response
16-
from timeline_logger.models import TimelineLog
1715

1816
from openarchiefbeheer.logging import logevent
1917
from openarchiefbeheer.utils.paginators import PageNumberPagination
@@ -60,7 +58,6 @@
6058
)
6159
from .serializers import (
6260
AbortDestructionSerializer,
63-
AuditTrailItemSerializer,
6461
CoReviewerAssignementSerializer,
6562
DestructionListAssigneeReadSerializer,
6663
DestructionListCoReviewSerializer,
@@ -197,12 +194,6 @@
197194
request=ReassignementSerializer,
198195
responses={200: None},
199196
),
200-
auditlog=extend_schema(
201-
tags=["Destruction list"],
202-
summary=_("Retrieve audit log."),
203-
description=_("Retrieve the audit log for this destruction list."),
204-
responses={200: AuditTrailItemSerializer(many=True)},
205-
),
206197
mark_ready_review=extend_schema(
207198
tags=["Destruction list"],
208199
summary=_("Mark as ready to review."),
@@ -258,8 +249,6 @@ def get_permissions(self):
258249
permission_classes = [IsAuthenticated & CanMarkListAsFinal]
259250
elif self.action == "reassign":
260251
permission_classes = [IsAuthenticated & CanReassignDestructionList]
261-
elif self.action == "auditlog":
262-
permission_classes = [IsAuthenticated]
263252
elif self.action == "mark_ready_review":
264253
permission_classes = [IsAuthenticated & CanMarkAsReadyToReview]
265254
elif self.action == "abort_destruction":
@@ -359,16 +348,6 @@ def reassign(self, request, *args, **kwargs):
359348
)
360349
return Response()
361350

362-
@action(detail=True, methods=["get"], name="audit_log")
363-
def auditlog(self, request, *args, **kwargs):
364-
destruction_list = self.get_object()
365-
items = TimelineLog.objects.filter(
366-
content_type=ContentType.objects.get_for_model(DestructionList),
367-
object_id=destruction_list.pk,
368-
)
369-
serializer = AuditTrailItemSerializer(instance=items, many=True)
370-
return Response(serializer.data)
371-
372351
@action(detail=True, methods=["post"], name="mark-ready-review")
373352
def mark_ready_review(self, request, *args, **kwargs):
374353
destruction_list = self.get_object()

backend/src/openarchiefbeheer/destruction/tests/endpoints/test_reviewresponse.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,9 @@ def test_audit_log(self):
219219
)
220220
self.assertEqual(response.status_code, status.HTTP_200_OK)
221221

222-
endpoint_audittrail = reverse(
223-
"api:destructionlist-auditlog", kwargs={"uuid": destruction_list.uuid}
224-
)
225-
response_audittrail = self.client.get(endpoint_audittrail)
222+
endpoint_audittrail = furl(reverse("api:logs-list"))
223+
endpoint_audittrail.args["destruction_list"] = destruction_list.uuid
224+
response_audittrail = self.client.get(endpoint_audittrail.url)
226225

227226
self.assertEqual(response_audittrail.status_code, status.HTTP_200_OK)
228227

backend/src/openarchiefbeheer/logging/api/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from django.contrib.contenttypes.models import ContentType
2+
from django.db.models import QuerySet
3+
from django.utils.translation import gettext_lazy as _
4+
5+
from django_filters import FilterSet, UUIDFilter
6+
from timeline_logger.models import TimelineLog
7+
8+
from openarchiefbeheer.destruction.models import DestructionList
9+
10+
11+
class LogsFilterset(FilterSet):
12+
destruction_list = UUIDFilter(
13+
field_name="destruction_list",
14+
method="filter_destruction_list",
15+
help_text=_("Retrieve the logs of a particular destruction list."),
16+
)
17+
18+
class Meta:
19+
model = TimelineLog
20+
fields = ("destruction_list",)
21+
22+
def filter_destruction_list(
23+
self, queryset: QuerySet[TimelineLog], name: str, value: str
24+
) -> QuerySet[TimelineLog]:
25+
destruction_list = DestructionList.objects.filter(uuid=value).first()
26+
if not destruction_list:
27+
return queryset.none()
28+
29+
content_type = ContentType.objects.get_for_model(destruction_list)
30+
31+
return queryset.filter(
32+
content_type=content_type,
33+
object_id=destruction_list.pk,
34+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from rest_framework import serializers
2+
from timeline_logger.models import TimelineLog
3+
4+
from openarchiefbeheer.accounts.api.serializers import UserSerializer
5+
6+
7+
class AuditTrailItemSerializer(serializers.ModelSerializer):
8+
message = serializers.CharField(source="get_message")
9+
user = UserSerializer()
10+
11+
class Meta:
12+
model = TimelineLog
13+
fields = (
14+
"pk",
15+
"timestamp",
16+
"user",
17+
"message",
18+
"extra_data",
19+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from django.utils.translation import gettext_lazy as _
2+
3+
from django_filters.rest_framework import DjangoFilterBackend
4+
from drf_spectacular.utils import extend_schema, extend_schema_view
5+
from rest_framework import mixins
6+
from rest_framework.viewsets import GenericViewSet
7+
from timeline_logger.models import TimelineLog
8+
9+
from .filtersets import LogsFilterset
10+
from .serializers import AuditTrailItemSerializer
11+
12+
13+
@extend_schema_view(
14+
list=extend_schema(
15+
tags=["Logs"],
16+
summary=_("List logs"),
17+
),
18+
)
19+
class LogsViewset(mixins.ListModelMixin, GenericViewSet):
20+
queryset = TimelineLog.objects.all()
21+
serializer_class = AuditTrailItemSerializer
22+
filter_backends = (DjangoFilterBackend,)
23+
filterset_class = LogsFilterset

frontend/.storybook/mockData.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { zaaktypeChoicesFactory } from "../src/fixtures/zaaktypeChoices";
77

88
export const MOCKS = {
99
AUDIT_LOG: {
10-
url: "http://localhost:8000/api/v1/destruction-lists/00000000-0000-0000-0000-000000000000/auditlog/",
10+
url: "http://localhost:8000/api/v1/logs?destruction-list=00000000-0000-0000-0000-000000000000",
1111
method: "GET",
1212
status: 200,
1313
response: auditLogFactory(),

frontend/src/lib/api/auditLog.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export type AuditLogItem = {
2828
* @param uuid
2929
*/
3030
export async function listAuditLog(uuid: string) {
31-
const response = await request("GET", `/destruction-lists/${uuid}/auditlog/`);
31+
const response = await request("GET", "/logs/", { destruction_list: uuid });
3232
const promise: AuditLogItem[] = await response.json();
3333
return promise;
3434
}

0 commit comments

Comments
 (0)