From 6bc55207d20a1d023db14cc285b4b903c8ffdc3d Mon Sep 17 00:00:00 2001 From: FranciscoLozCoding Date: Fri, 26 Jan 2024 14:47:41 -0600 Subject: [PATCH 1/3] added exception for split() --- manifests/views.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/manifests/views.py b/manifests/views.py index 99530c2..415e23f 100644 --- a/manifests/views.py +++ b/manifests/views.py @@ -19,6 +19,7 @@ from django.db import IntegrityError from node_auth.mixins import NodeAuthMixin, NodeOwnedObjectsMixin from app.authentication import TokenAuthentication as UserTokenAuthentication +from rest_framework.serializers import ValidationError class ManifestViewSet(ReadOnlyModelViewSet): @@ -139,7 +140,12 @@ class LorawanKeysView(NodeOwnedObjectsMixin, ModelViewSet): def vsn_get_func(self, obj, request, foreign_key_name): model, field = foreign_key_name.split("__") lc_str = request.data.get(model) - node_vsn, lorawan_device_name, lorawan_device_deveui = lc_str.split("-") + try: + node_vsn, lorawan_device_name, lorawan_device_deveui = lc_str.split("-") + except ValueError: + raise ValidationError( + "Invalid lorawan_connection format. Use 'node-device_name-deveui'." + ) lc = LorawanConnection.objects.get( node__vsn=node_vsn, lorawan_device__name=lorawan_device_name, From 70178e596486885e81e0d5d3113c11dff8d488df Mon Sep 17 00:00:00 2001 From: FranciscoLozCoding Date: Fri, 26 Jan 2024 16:16:42 -0600 Subject: [PATCH 2/3] added test for creating duplicate lorawan device --- manifests/tests/test_lorawan_views.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/manifests/tests/test_lorawan_views.py b/manifests/tests/test_lorawan_views.py index ec3926a..e4c10ca 100644 --- a/manifests/tests/test_lorawan_views.py +++ b/manifests/tests/test_lorawan_views.py @@ -723,6 +723,27 @@ def test_create_lorawan_device_success(self): device = LorawanDevice.objects.get(deveui=deveui) self.assertIsNotNone(device) + @patch("manifests.views.LorawanDeviceView.permission_classes", [AllowAny]) + def test_create_lorawan_device_duplicate(self): + """Test creating a duplicate lorawan device""" + self.device = LorawanDevice.objects.create(deveui="451", name="test") + # Create a request to create a device + deveui = "451" + url = reverse("manifests:lorawandevices-list") + data = { + "deveui": deveui, + "name": "test", + } + request = self.factory.post(url, data, format="json") + + # Use the device view to handle the request + lorawan_device_view = LorawanDeviceView.as_view({"post": "create"}) + response = lorawan_device_view(request) + print(response) + + # Check the response status code and data + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + @patch("manifests.views.LorawanDeviceView.permission_classes", [AllowAny]) def test_create_lorawan_device_serializer_error(self): """Test for getting a serializer error when creating a lorawan device""" From ad7e674d4e345d87c78bf793cd4029f889ad4c6a Mon Sep 17 00:00:00 2001 From: FranciscoLozCoding Date: Fri, 26 Jan 2024 16:49:30 -0600 Subject: [PATCH 3/3] fixed bug where serializer was not detecting duplicate --- manifests/serializers.py | 19 ++++++++-- manifests/tests/test_lorawan_views.py | 52 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/manifests/serializers.py b/manifests/serializers.py index 7cc2ee9..a9f92d5 100644 --- a/manifests/serializers.py +++ b/manifests/serializers.py @@ -105,10 +105,17 @@ def get_lookup_records(self, validated_data): def create(self, validated_data): """ - Retrieve lookup field records cbased on validated data + Retrieve lookup field records based on validated data to then pass in to parent create function """ - return super().create(self.get_lookup_records(validated_data)) + validated_data = self.get_lookup_records(validated_data) + # this has to be added because serializer is checking for node pk and lorawan device pk so it passes since im using node vsn NOT pk + # serializer thinks a lc has not been created with this combination of node and lorawan device and causes a server error - FL 01/26/24 + if LorawanConnection.objects.filter(node=validated_data["node"], lorawan_device=validated_data["lorawan_device"]).exists(): + raise serializers.ValidationError( + {"node-lorawan_device": [f'Lorawan connection with this node and lorawan_device already exists']} + ) + return super().create(validated_data) def update(self, instance, validated_data): """ @@ -168,7 +175,13 @@ def create(self, validated_data): Retrieve lookup field records based on validated data to then pass in to parent create function """ - return super().create(self.get_lookup_records(validated_data)) + # same issue here as lorawan connection serializer - FL + validated_data = self.get_lookup_records(validated_data) + if LorawanKeys.objects.filter(lorawan_connection=validated_data["lorawan_connection"]).exists(): + raise serializers.ValidationError( + {"lorawan_connection": [f'Lorawan Key with this lorawan_connection already exists']} + ) + return super().create(validated_data) def update(self, instance, validated_data): """ diff --git a/manifests/tests/test_lorawan_views.py b/manifests/tests/test_lorawan_views.py index e4c10ca..45093e3 100644 --- a/manifests/tests/test_lorawan_views.py +++ b/manifests/tests/test_lorawan_views.py @@ -203,6 +203,27 @@ def test_create_lorawan_connection_serializer_error(self): node=self.nodedata, lorawan_device=self.device ) + @patch("manifests.views.LorawanConnectionView.permission_classes", [AllowAny]) + def test_create_lorawan_connection_duplicate(self): + """Test creating a duplicate lorawan connection (unique_together = ["node", "lorawan_device"])""" + LorawanConnection.objects.create(node=self.nodedata, lorawan_device=self.device) + + # Create a request to create a LorawanConnection + url = reverse("manifests:C_lorawan_connection") + data = { + "node": self.nodedata.vsn, + "lorawan_device": self.device.deveui, + "connection_type": "OTAA", + } + request = self.factory.post(url, data, format="json") + + # Use the LorawanConnectionView to handle the request + lorawan_connection_view = LorawanConnectionView.as_view({"post": "create"}) + response = lorawan_connection_view(request) + + #Check the response status code + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + @patch("manifests.views.LorawanConnectionView.permission_classes", [AllowAny]) def test_update_lorawan_connection_success(self): """Test correctly updating a lorawan connection""" @@ -467,6 +488,37 @@ def test_create_lorawan_key_success(self): lorawan_connection = LorawanKeys.objects.get(lorawan_connection=lc) self.assertIsNotNone(lorawan_connection) + @patch("manifests.views.LorawanKeysView.permission_classes", [AllowAny]) + def test_create_lorawan_key_duplicate(self): + """Test creating a duplicate lorawan key""" + # Create a LorawanConnection for testing + lc = LorawanConnection.objects.create( + node=self.nodedata, lorawan_device=self.device + ) + LorawanKeys.objects.create( + lorawan_connection=lc, + network_Key="123", + app_session_key="13", + dev_address="14" + ) + + # Create a request to create a key + url = reverse("manifests:C_lorawan_key") + data = { + "lorawan_connection": str(lc), + "network_Key": "123", + "app_session_key": "13", + "dev_address": "14", + } + request = self.factory.post(url, data, format="json") + + # Use the key view to handle the request + lorawan_key_view = LorawanKeysView.as_view({"post": "create"}) + response = lorawan_key_view(request) + + # Check the response status code and data + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + @patch("manifests.views.LorawanKeysView.permission_classes", [AllowAny]) def test_create_lorawan_key_invalid_lc(self): """Test creating a lorawan key with invalid node"""