From cf5a380ce1a96b680715fd5c0bff3af0f20e5310 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 6 Jun 2024 11:27:53 +0200 Subject: [PATCH 1/4] :sparkles: [#76] Add UUIDs to destruction lists --- .../migrations/0004_destructionlist_uuid.py | 19 ++++++++++++++++ .../migrations/0005_populate_uuid_values.py | 22 +++++++++++++++++++ .../migrations/0006_remove_uuid_null.py | 21 ++++++++++++++++++ .../openarchiefbeheer/destruction/models.py | 2 ++ 4 files changed, 64 insertions(+) create mode 100644 backend/src/openarchiefbeheer/destruction/migrations/0004_destructionlist_uuid.py create mode 100644 backend/src/openarchiefbeheer/destruction/migrations/0005_populate_uuid_values.py create mode 100644 backend/src/openarchiefbeheer/destruction/migrations/0006_remove_uuid_null.py diff --git a/backend/src/openarchiefbeheer/destruction/migrations/0004_destructionlist_uuid.py b/backend/src/openarchiefbeheer/destruction/migrations/0004_destructionlist_uuid.py new file mode 100644 index 000000000..77f6197b8 --- /dev/null +++ b/backend/src/openarchiefbeheer/destruction/migrations/0004_destructionlist_uuid.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.11 on 2024-06-06 09:17 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ("destruction", "0003_destructionlist_status_changed"), + ] + + operations = [ + migrations.AddField( + model_name="destructionlist", + name="uuid", + field=models.UUIDField(default=uuid.uuid4, null=True, verbose_name="uuid"), + ), + ] diff --git a/backend/src/openarchiefbeheer/destruction/migrations/0005_populate_uuid_values.py b/backend/src/openarchiefbeheer/destruction/migrations/0005_populate_uuid_values.py new file mode 100644 index 000000000..ad89b5e4a --- /dev/null +++ b/backend/src/openarchiefbeheer/destruction/migrations/0005_populate_uuid_values.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.11 on 2024-06-06 09:17 + +from django.db import migrations +import uuid + + +def generate_uuid(apps, schema_editor): + DestructionList = apps.get_model("destruction", "DestructionList") + for destruction_list in DestructionList.objects.all(): + destruction_list.uuid = uuid.uuid4() + destruction_list.save(update_fields=["uuid"]) + + +class Migration(migrations.Migration): + + dependencies = [ + ("destruction", "0004_destructionlist_uuid"), + ] + + operations = [ + migrations.RunPython(generate_uuid, reverse_code=migrations.RunPython.noop), + ] diff --git a/backend/src/openarchiefbeheer/destruction/migrations/0006_remove_uuid_null.py b/backend/src/openarchiefbeheer/destruction/migrations/0006_remove_uuid_null.py new file mode 100644 index 000000000..d27d40d4a --- /dev/null +++ b/backend/src/openarchiefbeheer/destruction/migrations/0006_remove_uuid_null.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.11 on 2024-06-06 09:17 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ("destruction", "0005_populate_uuid_values"), + ] + + operations = [ + migrations.AlterField( + model_name="destructionlist", + name="uuid", + field=models.UUIDField( + default=uuid.uuid4, unique=True, verbose_name="uuid" + ), + ), + ] diff --git a/backend/src/openarchiefbeheer/destruction/models.py b/backend/src/openarchiefbeheer/destruction/models.py index 1b2c556b5..0cead8cff 100644 --- a/backend/src/openarchiefbeheer/destruction/models.py +++ b/backend/src/openarchiefbeheer/destruction/models.py @@ -1,4 +1,5 @@ import logging +import uuid as _uuid from django.db import models from django.utils import timezone @@ -16,6 +17,7 @@ class DestructionList(models.Model): name = models.CharField(_("name"), max_length=200, unique=True) + uuid = models.UUIDField(_("uuid"), default=_uuid.uuid4, unique=True) author = models.ForeignKey( "accounts.User", on_delete=models.CASCADE, From 386e4e3b8d50bb0f18e1956728f0ccc5342385bc Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 6 Jun 2024 11:35:49 +0200 Subject: [PATCH 2/4] :sparkles: [#76] Use UUID in the API --- backend/src/openarchiefbeheer/destruction/admin.py | 1 + .../src/openarchiefbeheer/destruction/api/serializers.py | 9 +++++++-- .../src/openarchiefbeheer/destruction/api/viewsets.py | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/src/openarchiefbeheer/destruction/admin.py b/backend/src/openarchiefbeheer/destruction/admin.py index 2178f3f17..ec3df3461 100644 --- a/backend/src/openarchiefbeheer/destruction/admin.py +++ b/backend/src/openarchiefbeheer/destruction/admin.py @@ -8,6 +8,7 @@ class DestructionListAdmin(admin.ModelAdmin): list_display = ("name", "status", "created", "end") list_filter = ("status", "assignee") search_fields = ("name",) + readonly_fields = ("uuid",) @admin.register(DestructionListItem) diff --git a/backend/src/openarchiefbeheer/destruction/api/serializers.py b/backend/src/openarchiefbeheer/destruction/api/serializers.py index 91942f46b..be894ef18 100644 --- a/backend/src/openarchiefbeheer/destruction/api/serializers.py +++ b/backend/src/openarchiefbeheer/destruction/api/serializers.py @@ -77,6 +77,7 @@ class DestructionListSerializer(serializers.ModelSerializer): class Meta: model = DestructionList fields = ( + "uuid", "name", "author", "contains_sensitive_info", @@ -84,7 +85,11 @@ class Meta: "items", "status", ) - extra_kwargs = {"status": {"read_only": True}, "author": {"read_only": True}} + extra_kwargs = { + "uuid": {"read_only": True}, + "status": {"read_only": True}, + "author": {"read_only": True}, + } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -151,7 +156,7 @@ class DestructionListResponseSerializer(serializers.ModelSerializer): class Meta: model = DestructionList fields = ( - "pk", + "uuid", "name", "author", "contains_sensitive_info", diff --git a/backend/src/openarchiefbeheer/destruction/api/viewsets.py b/backend/src/openarchiefbeheer/destruction/api/viewsets.py index 0e463b6d3..1b85dd4e7 100644 --- a/backend/src/openarchiefbeheer/destruction/api/viewsets.py +++ b/backend/src/openarchiefbeheer/destruction/api/viewsets.py @@ -116,6 +116,7 @@ class DestructionListViewSet( ): serializer_class = DestructionListSerializer queryset = DestructionList.objects.all() + lookup_field = "uuid" filter_backends = (DjangoFilterBackend,) filterset_class = DestructionListFilterset From 3f0ed9eeb75893cac03eef1fddb1c3d658908265 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 6 Jun 2024 11:42:51 +0200 Subject: [PATCH 3/4] :white_check_mark: [#76] Update tests --- .../openarchiefbeheer/destruction/tests/test_endpoints.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py b/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py index a5a4642f3..13804c075 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py +++ b/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py @@ -204,7 +204,7 @@ def test_update_destruction_list(self): } self.client.force_authenticate(user=record_manager) endpoint = reverse( - "api:destructionlist-detail", kwargs={"pk": destruction_list.pk} + "api:destructionlist-detail", kwargs={"uuid": destruction_list.uuid} ) response = self.client.put( @@ -249,7 +249,7 @@ def test_partially_update_destruction_list(self): } self.client.force_authenticate(user=record_manager) endpoint = reverse( - "api:destructionlist-detail", kwargs={"pk": destruction_list.pk} + "api:destructionlist-detail", kwargs={"uuid": destruction_list.uuid} ) response = self.client.patch( @@ -287,8 +287,8 @@ def test_destruction_list_filter_on_assignee(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 2) self.assertEqual( - [destruction_list["pk"] for destruction_list in response.json()].sort(), - [lists[0].pk, lists[1].pk].sort(), + [destruction_list["uuid"] for destruction_list in response.json()].sort(), + [lists[0].uuid, lists[1].uuid].sort(), ) From 7a1782cd330386b291d09ef1b64145161254af2a Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 6 Jun 2024 11:45:54 +0200 Subject: [PATCH 4/4] :recycle: [#76] Update frontend to use UUIDs --- frontend/src/lib/api/destructionLists.ts | 2 +- frontend/src/pages/landing/Landing.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/api/destructionLists.ts b/frontend/src/lib/api/destructionLists.ts index 87bd986f2..a6679df07 100644 --- a/frontend/src/lib/api/destructionLists.ts +++ b/frontend/src/lib/api/destructionLists.ts @@ -5,7 +5,7 @@ import { request } from "./request"; import { User } from "./reviewers"; export type DestructionList = { - pk: number; + uuid: string; name: string; assignees: DestructionListAssignee[]; items: DestructionListItem[]; diff --git a/frontend/src/pages/landing/Landing.tsx b/frontend/src/pages/landing/Landing.tsx index 3aefbf4d6..64136ca7e 100644 --- a/frontend/src/pages/landing/Landing.tsx +++ b/frontend/src/pages/landing/Landing.tsx @@ -77,7 +77,7 @@ export const Landing = () => { title: list.name, days: timeAgo(list.created), assigneeNames: constructAssigneeNames(list.assignees), - href: `/destruction-list/${list.pk}`, + href: `/destruction-list/${list.uuid}`, })), ) as unknown as AttributeData[][];