From 897825880431c15bcdaf57cadfe2fc05419371be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 12:52:49 +0000 Subject: [PATCH 1/3] Initial plan From 695f53c968e31b099afcac6bfed867635e087c8b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:03:47 +0000 Subject: [PATCH 2/3] Fix location API lat/lng update by changing model casts to decimal Co-authored-by: bonzo81 <2754635+bonzo81@users.noreply.github.com> --- app/Models/Location.php | 6 +- tests/Feature/ApiLocationTest.php | 148 ++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 tests/Feature/ApiLocationTest.php diff --git a/app/Models/Location.php b/app/Models/Location.php index 1acc71725f7c..190f67537880 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -48,13 +48,13 @@ class Location extends Model private $location_ignore_regex = '/\(.*?\)/'; /** - * @return array{lat: 'float', lng: 'float', fixed_coordinates: 'bool'} + * @return array{lat: 'decimal:8', lng: 'decimal:8', fixed_coordinates: 'bool'} */ protected function casts(): array { return [ - 'lat' => 'float', - 'lng' => 'float', + 'lat' => 'decimal:8', + 'lng' => 'decimal:8', 'fixed_coordinates' => 'bool', ]; } diff --git a/tests/Feature/ApiLocationTest.php b/tests/Feature/ApiLocationTest.php new file mode 100644 index 000000000000..30c862dd016a --- /dev/null +++ b/tests/Feature/ApiLocationTest.php @@ -0,0 +1,148 @@ +. + * + * @link https://www.librenms.org + * + * @copyright 2025 LibreNMS + * @author LibreNMS Contributors + */ + +namespace Tests\Feature; + +use App\Models\ApiToken; +use App\Models\Location; +use App\Models\User; +use Illuminate\Foundation\Testing\DatabaseTransactions; +use LibreNMS\Tests\DBTestCase; + +final class ApiLocationTest extends DBTestCase +{ + use DatabaseTransactions; + + public function testEditLocationWithDecimalCoordinates(): void + { + /** @var User $user */ + $user = User::factory()->admin()->create(); + $token = ApiToken::generateToken($user); + + /** @var Location $location */ + $location = Location::factory()->create([ + 'location' => 'Test Location', + 'lat' => '51.50354111', + 'lng' => '-0.12766972', + ]); + + // Update the location with new coordinates + $newLat = '40.71277800'; + $newLng = '-74.00597200'; + + $response = $this->json( + 'PATCH', + "/api/v0/locations/{$location->id}", + [ + 'lat' => $newLat, + 'lng' => $newLng, + ], + ['X-Auth-Token' => $token->token_hash] + ); + + $response->assertStatus(201) + ->assertJson([ + 'status' => 'ok', + 'message' => 'Location updated successfully', + ]); + + // Verify the database was updated correctly + $location->refresh(); + $this->assertEquals($newLat, $location->lat); + $this->assertEquals($newLng, $location->lng); + } + + public function testEditLocationByName(): void + { + /** @var User $user */ + $user = User::factory()->admin()->create(); + $token = ApiToken::generateToken($user); + + /** @var Location $location */ + $location = Location::factory()->create([ + 'location' => 'Test Location Name', + 'lat' => '51.50354111', + 'lng' => '-0.12766972', + ]); + + // Update the location by name with new coordinates + $newLat = '48.85661400'; + $newLng = '2.35222190'; + + $response = $this->json( + 'PATCH', + '/api/v0/locations/' . urlencode($location->location), + [ + 'lat' => $newLat, + 'lng' => $newLng, + ], + ['X-Auth-Token' => $token->token_hash] + ); + + $response->assertStatus(201) + ->assertJson([ + 'status' => 'ok', + 'message' => 'Location updated successfully', + ]); + + // Verify the database was updated correctly + $location->refresh(); + $this->assertEquals($newLat, $location->lat); + $this->assertEquals($newLng, $location->lng); + } + + public function testEditLocationWithNullCoordinates(): void + { + /** @var User $user */ + $user = User::factory()->admin()->create(); + $token = ApiToken::generateToken($user); + + /** @var Location $location */ + $location = Location::factory()->create([ + 'location' => 'Test Location Null', + 'lat' => '51.50354111', + 'lng' => '-0.12766972', + ]); + + // Update the location with null coordinates + $response = $this->json( + 'PATCH', + "/api/v0/locations/{$location->id}", + [ + 'lat' => null, + 'lng' => null, + ], + ['X-Auth-Token' => $token->token_hash] + ); + + $response->assertStatus(201); + + // Verify the database was updated correctly + $location->refresh(); + $this->assertNull($location->lat); + $this->assertNull($location->lng); + } +} From 37db6e6079432bbe39d1e95d34e7daa3d6933410 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:08:46 +0000 Subject: [PATCH 3/3] Fix coordinatesValid to work with decimal cast Co-authored-by: bonzo81 <2754635+bonzo81@users.noreply.github.com> --- app/Models/Location.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Location.php b/app/Models/Location.php index 190f67537880..84e1abc6ee88 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -77,7 +77,7 @@ public function hasCoordinates() */ public function coordinatesValid() { - return $this->lat && $this->lng && + return $this->lat != 0 && $this->lng != 0 && abs($this->lat) <= 90 && abs($this->lng) <= 180; }