From c38e3d61444d53ce24aea0495ae93a0ccc395c7d Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 18 Jun 2024 20:45:00 +0100 Subject: [PATCH] Enforce changeset size limit for API calls which make changes --- app/models/changeset.rb | 8 ++++++++ lib/bounding_box.rb | 8 ++++++++ lib/osm.rb | 11 +++++++++++ 3 files changed, 27 insertions(+) diff --git a/app/models/changeset.rb b/app/models/changeset.rb index abb494de6..e6bde19a5 100644 --- a/app/models/changeset.rb +++ b/app/models/changeset.rb @@ -130,6 +130,8 @@ class Changeset < ApplicationRecord def update_bbox!(bbox_update) bbox.expand!(bbox_update) + raise OSM::APISizeLimitExceeded if bbox.linear_size > size_limit + # update active record. rails 2.1's dirty handling should take care of # whether this object needs saving or not. self.min_lon, self.min_lat, self.max_lon, self.max_lat = @bbox.to_a.collect(&:round) if bbox.complete? @@ -225,4 +227,10 @@ class Changeset < ApplicationRecord def subscribed?(user) subscribers.exists?(user.id) end + + def size_limit + @size_limit ||= ActiveRecord::Base.connection.select_value( + "SELECT api_size_limit($1)", "api_size_limit", [user_id] + ) + end end diff --git a/lib/bounding_box.rb b/lib/bounding_box.rb index 0cc4c5fd4..462f45a9f 100644 --- a/lib/bounding_box.rb +++ b/lib/bounding_box.rb @@ -88,6 +88,14 @@ class BoundingBox end end + def linear_size + if complete? + (max_lon - min_lon) + (max_lat - min_lat) + else + 0 + end + end + def complete? to_a.exclude?(nil) end diff --git a/lib/osm.rb b/lib/osm.rb index a0fcef8b9..dd273418e 100644 --- a/lib/osm.rb +++ b/lib/osm.rb @@ -364,6 +364,17 @@ module OSM end end + # Raised when a size limit is exceeded + class APISizeLimitExceeded < APIError + def initialize + super("Size limit exceeded") + end + + def status + :payload_too_large + end + end + # Helper methods for going to/from mercator and lat/lng. class Mercator include Math -- 2.39.5