Skip to content

Commit

Permalink
[fix] Fixed recovering deleted device with related location #936
Browse files Browse the repository at this point in the history
Fixes #936
  • Loading branch information
pandafy committed Jan 7, 2025
1 parent 4010183 commit facc8ce
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 5 deletions.
35 changes: 34 additions & 1 deletion openwisp_controller/geo/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ def _get_floorplan_instance(self):
floorplan.organization_id = self.data.get('organization')
return floorplan

def _get_initial_location(self):
"""
Returns initial location for the device.
Attempts to get the initial location by calling parent class method.
If location is not found (e.g. when recovering a deleted device),
returns None instead of raising Location.DoesNotExist.
Returns:
Location instance or None if location does not exist
"""
try:
return super()._get_initial_location()
except Location.DoesNotExist:
return None

def _get_initial_floorplan(self):
"""
Returns initial floorplan for the device.
Attempts to get the initial floorplan by calling parent class method.
If floorplan is not found (e.g. when recovering a deleted device),
returns None instead of raising FloorPlan.DoesNotExist.
Returns:
FloorPlan instance or None if floorplan does not exist
"""
try:
return super()._get_initial_floorplan()
except FloorPlan.DoesNotExist:
return None


class LocationForm(AbstractLocationForm):
class Meta(AbstractLocationForm.Meta):
Expand Down Expand Up @@ -83,6 +115,7 @@ class DeviceLocationInline(

admin.site.register(FloorPlan, FloorPlanAdmin)
admin.site.register(Location, LocationAdmin)
reversion.register(model=Location)


class DeviceLocationFilter(admin.SimpleListFilter):
Expand All @@ -105,5 +138,5 @@ def queryset(self, request, queryset):
DeviceAdminExportable.inlines.insert(1, DeviceLocationInline)
DeviceAdminExportable.list_filter.append(DeviceLocationFilter)
DeviceAdminExportable.resource_class = GeoDeviceResource
reversion.register(model=DeviceLocation, follow=['device'])
reversion.register(model=DeviceLocation, follow=['device', 'location'])
DeviceAdminExportable.add_reversion_following(follow=['devicelocation'])
23 changes: 19 additions & 4 deletions openwisp_controller/tests/test_selenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,18 @@
Device = load_model('config', 'Device')
DeviceConnection = load_model('connection', 'DeviceConnection')
Location = load_model('geo', 'Location')
FloorPlan = load_model('geo', 'FloorPlan')
DeviceLocation = load_model('geo', 'DeviceLocation')


@tag('selenium_tests')
class TestDeviceConnectionInlineAdmin(
class TestDevice(
CreateConnectionsMixin, TestGeoMixin, SeleniumTestMixin, StaticLiveServerTestCase
):
config_app_label = 'config'
location_model = Location
object_location_model = DeviceLocation
floorplan_model = FloorPlan

def setUp(self):
self.admin = self._create_admin(
Expand All @@ -40,10 +42,14 @@ def test_restoring_deleted_device(self, *args):
self._create_credentials(auto_add=True, organization=org)
config = self._create_config(organization=org)
device = config.device

location = self._create_location(organization=org, type='indoor')
floorplan = self._create_floorplan(
location=location,
)
self._create_object_location(
location=self._create_location(
organization=org,
),
location=location,
floorplan=floorplan,
content_object=device,
)
self.assertEqual(device.deviceconnection_set.count(), 1)
Expand All @@ -59,9 +65,13 @@ def test_restoring_deleted_device(self, *args):
self.web_driver.find_element(
by=By.XPATH, value='//*[@id="content"]/form/div/input[2]'
).click()
# Delete location object
location.delete()
self.assertEqual(Device.objects.count(), 0)
self.assertEqual(DeviceConnection.objects.count(), 0)
self.assertEqual(DeviceLocation.objects.count(), 0)
self.assertEqual(self.location_model.objects.count(), 0)
self.assertEqual(self.floorplan_model.objects.count(), 0)

version_obj = Version.objects.get_deleted(model=Device).first()

Expand Down Expand Up @@ -94,3 +104,8 @@ def test_restoring_deleted_device(self, *args):
self.assertEqual(Device.objects.count(), 1)
self.assertEqual(DeviceConnection.objects.count(), 1)
self.assertEqual(DeviceLocation.objects.count(), 1)
self.assertEqual(self.location_model.objects.count(), 1)
# The FloorPlan object is not recoverable because deleting it
# also removes the associated image from the filesystem,
# which cannot be restored.
self.assertEqual(self.floorplan_model.objects.count(), 0)

0 comments on commit facc8ce

Please sign in to comment.