Skip to content

Commit

Permalink
Enforce rate limit for API calls which make changes
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhughes committed Oct 30, 2023
1 parent 60fa476 commit bf0eba2
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 1 deletion.
4 changes: 4 additions & 0 deletions app/controllers/api/changesets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ def upload
diff_reader = DiffReader.new(request.raw_post, changeset)
Changeset.transaction do
result = diff_reader.commit
# the number of changes in this changeset has already been
# updated and is visible in this transaction so we don't need
# to allow for any more when checking the limit
check_rate_limit(0)
render :xml => result.to_s
end
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/nodes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class NodesController < ApiController
around_action :api_call_handle_error, :api_call_timeout

before_action :set_request_formats, :except => [:create, :update, :delete]
before_action :check_rate_limit, :only => [:create, :update, :delete]

# Dump the details on many nodes whose ids are given in the "nodes" parameter.
def index
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/relations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class RelationsController < ApiController
around_action :api_call_handle_error, :api_call_timeout

before_action :set_request_formats, :except => [:create, :update, :delete]
before_action :check_rate_limit, :only => [:create, :update, :delete]

def index
raise OSM::APIBadUserInput, "The parameter relations is required, and must be of the form relations=id[,id[,id...]]" unless params["relations"]
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/ways_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class WaysController < ApiController
around_action :api_call_handle_error, :api_call_timeout

before_action :set_request_formats, :except => [:create, :update, :delete]
before_action :check_rate_limit, :only => [:create, :update, :delete]

def index
raise OSM::APIBadUserInput, "The parameter ways is required, and must be of the form ways=id[,id[,id...]]" unless params["ways"]
Expand Down
7 changes: 7 additions & 0 deletions app/controllers/api_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,11 @@ def api_call_timeout(&block)
ActiveRecord::Base.connection.raw_connection.cancel
raise OSM::APITimeoutError
end

##
# check the api change rate limit
def check_rate_limit(new_changes = 1)
recent_changes = current_user.changesets.where("created_at > ?", Time.now.utc - 1.hour).sum(:num_changes)
raise OSM::APIRateLimitExceeded if recent_changes + new_changes > current_user.max_changes_per_hour
end
end
6 changes: 5 additions & 1 deletion test/controllers/api/changesets_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,11 @@ def test_changeset_update_invalid
# check that a changeset can contain a certain max number of changes.
## FIXME should be changed to an integration test due to the with_controller
def test_changeset_limits
auth_header = basic_authorization_header create(:user).email, "test"
user = create(:user)
auth_header = basic_authorization_header user.email, "test"

# create an old changeset to ensure we have the maximum rate limit
create(:changeset, :user => user, :created_at => Time.now.utc - 28.days)

# open a new changeset
xml = "<osm><changeset/></osm>"
Expand Down

0 comments on commit bf0eba2

Please sign in to comment.