diff --git a/app/javascript/maps/location_search.js b/app/javascript/maps/location_search.js
index b3118124..b3959bb5 100644
--- a/app/javascript/maps/location_search.js
+++ b/app/javascript/maps/location_search.js
@@ -321,7 +321,7 @@ class LocationSearch {
this.resultsContainer.innerHTML = `
-
Searching for "${this.currentSearchQuery}"...
+
Searching for "${this.escapeHtml(this.currentSearchQuery)}"...
`;
}
@@ -335,7 +335,7 @@ class LocationSearch {
⚠️
Search Failed
-
${message}
+
${this.escapeHtml(message)}
`;
}
@@ -350,7 +350,7 @@ class LocationSearch {
📍
No visits found
-
No visits found for "${this.currentSearchQuery}"
+
No visits found for "${this.escapeHtml(this.currentSearchQuery)}"
`;
return;
@@ -362,7 +362,7 @@ class LocationSearch {
let resultsHtml = `
Found ${data.total_locations} location(s)
-
for "${this.currentSearchQuery}"
+
for "${this.escapeHtml(this.currentSearchQuery)}"
`;
diff --git a/app/services/location_search/geocoding_service.rb b/app/services/location_search/geocoding_service.rb
index 4cd4ebc3..c8b42833 100644
--- a/app/services/location_search/geocoding_service.rb
+++ b/app/services/location_search/geocoding_service.rb
@@ -33,10 +33,15 @@ module LocationSearch
end
def normalize_geocoding_results(results)
- normalized_results = results.map do |result|
+ normalized_results = results.filter_map do |result|
+ lat = result.latitude.to_f
+ lon = result.longitude.to_f
+
+ next unless valid_coordinates?(lat, lon)
+
{
- lat: result.latitude.to_f,
- lon: result.longitude.to_f,
+ lat: lat,
+ lon: lon,
name: result.address&.split(',')&.first || 'Unknown location',
address: result.address || '',
type: result.data&.dig('type') || result.data&.dig('class') || 'unknown',
@@ -83,5 +88,9 @@ module LocationSearch
distance_km * 1000 # Convert km to meters
end
+
+ def valid_coordinates?(lat, lon)
+ lat.between?(-90, 90) && lon.between?(-180, 180)
+ end
end
end
diff --git a/app/services/location_search/point_finder.rb b/app/services/location_search/point_finder.rb
index 7b9a2d01..63cb695d 100644
--- a/app/services/location_search/point_finder.rb
+++ b/app/services/location_search/point_finder.rb
@@ -13,6 +13,8 @@ module LocationSearch
end
def call
+ return empty_result unless valid_coordinates?
+
location = {
lat: @latitude,
lon: @longitude,
@@ -103,5 +105,18 @@ module LocationSearch
500 # Default radius for unknown types
end
end
+
+ def valid_coordinates?
+ @latitude.present? && @longitude.present? &&
+ @latitude.to_f.between?(-90, 90) && @longitude.to_f.between?(-180, 180)
+ end
+
+ def empty_result
+ {
+ locations: [],
+ total_locations: 0,
+ search_metadata: {}
+ }
+ end
end
end
diff --git a/spec/jobs/data_migrations/migrate_points_latlon_job_spec.rb b/spec/jobs/data_migrations/migrate_points_latlon_job_spec.rb
index 2bb19f2a..5fb3e701 100644
--- a/spec/jobs/data_migrations/migrate_points_latlon_job_spec.rb
+++ b/spec/jobs/data_migrations/migrate_points_latlon_job_spec.rb
@@ -7,10 +7,13 @@ RSpec.describe DataMigrations::MigratePointsLatlonJob, type: :job do
it 'updates the lonlat column for all tracked points' do
user = create(:user)
point = create(:point, latitude: 2.0, longitude: 1.0, user: user)
+
+ # Clear the lonlat to simulate points that need migration
+ point.update_column(:lonlat, nil)
expect { subject.perform(user.id) }.to change {
point.reload.lonlat
- }.to(RGeo::Geographic.spherical_factory.point(1.0, 2.0))
+ }.from(nil).to(RGeo::Geographic.spherical_factory.point(1.0, 2.0))
end
end
end
diff --git a/spec/services/location_search/point_finder_spec.rb b/spec/services/location_search/point_finder_spec.rb
index 14750916..bd74f5da 100644
--- a/spec/services/location_search/point_finder_spec.rb
+++ b/spec/services/location_search/point_finder_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe LocationSearch::PointFinder do
before do
allow_any_instance_of(LocationSearch::SpatialMatcher)
.to receive(:find_points_near).and_return(mock_matching_points)
-
+
allow_any_instance_of(LocationSearch::ResultAggregator)
.to receive(:group_points_into_visits).and_return(mock_visits)
end
@@ -62,7 +62,7 @@ RSpec.describe LocationSearch::PointFinder do
context 'with custom radius override' do
let(:search_params) { { latitude: 52.5200, longitude: 13.4050, radius_override: 150 } }
-
+
it 'uses custom radius when override provided' do
expect_any_instance_of(LocationSearch::SpatialMatcher)
.to receive(:find_points_near)
@@ -101,7 +101,7 @@ RSpec.describe LocationSearch::PointFinder do
before do
allow_any_instance_of(LocationSearch::SpatialMatcher)
.to receive(:find_points_near).and_return([{}])
-
+
allow_any_instance_of(LocationSearch::ResultAggregator)
.to receive(:group_points_into_visits).and_return(many_visits)
end
@@ -116,7 +116,7 @@ RSpec.describe LocationSearch::PointFinder do
context 'when no matching points found' do
let(:search_params) { { latitude: 52.5200, longitude: 13.4050 } }
-
+
before do
allow_any_instance_of(LocationSearch::SpatialMatcher)
.to receive(:find_points_near).and_return([])
@@ -137,7 +137,7 @@ RSpec.describe LocationSearch::PointFinder do
expect(LocationSearch::SpatialMatcher).not_to receive(:new)
result = service.call
-
+
expect(result[:locations]).to be_empty
end
end
@@ -147,7 +147,7 @@ RSpec.describe LocationSearch::PointFinder do
it 'returns empty result' do
result = service.call
-
+
expect(result[:locations]).to be_empty
end
end
@@ -157,9 +157,9 @@ RSpec.describe LocationSearch::PointFinder do
it 'returns empty result' do
result = service.call
-
+
expect(result[:locations]).to be_empty
end
end
end
-end
\ No newline at end of file
+end