1 # frozen_string_literal: true
4 require_relative "elements_test_helper"
7 class NodesControllerTest < ActionDispatch::IntegrationTest
8 include ElementsTestHelper
11 # test all routes which lead to this controller
14 { :path => "/api/0.6/nodes", :method => :get },
15 { :controller => "api/nodes", :action => "index" }
18 { :path => "/api/0.6/nodes.json", :method => :get },
19 { :controller => "api/nodes", :action => "index", :format => "json" }
22 { :path => "/api/0.6/nodes", :method => :post },
23 { :controller => "api/nodes", :action => "create" }
26 { :path => "/api/0.6/node/1", :method => :get },
27 { :controller => "api/nodes", :action => "show", :id => "1" }
30 { :path => "/api/0.6/node/1.json", :method => :get },
31 { :controller => "api/nodes", :action => "show", :id => "1", :format => "json" }
34 { :path => "/api/0.6/node/1", :method => :put },
35 { :controller => "api/nodes", :action => "update", :id => "1" }
38 { :path => "/api/0.6/node/1", :method => :delete },
39 { :controller => "api/nodes", :action => "destroy", :id => "1" }
43 { :controller => "api/nodes", :action => "create" },
44 { :path => "/api/0.6/node/create", :method => :put }
49 # test fetching multiple nodes
52 node2 = create(:node, :deleted)
54 node4 = create(:node, :with_history, :version => 2)
55 node5 = create(:node, :deleted, :with_history, :version => 2)
57 # check error when no parameter provided
59 assert_response :bad_request
61 # check error when no parameter value provided
62 get api_nodes_path(:nodes => "")
63 assert_response :bad_request
66 get api_nodes_path(:nodes => "#{node1.id},#{node2.id},#{node3.id},#{node4.id},#{node5.id}")
67 assert_response :success
68 assert_select "osm" do
69 assert_select "node", :count => 5
70 assert_select "node[id='#{node1.id}'][visible='true']", :count => 1
71 assert_select "node[id='#{node2.id}'][visible='false']", :count => 1
72 assert_select "node[id='#{node3.id}'][visible='true']", :count => 1
73 assert_select "node[id='#{node4.id}'][visible='true']", :count => 1
74 assert_select "node[id='#{node5.id}'][visible='false']", :count => 1
77 # test a working call with json format
78 get api_nodes_path(:nodes => "#{node1.id},#{node2.id},#{node3.id},#{node4.id},#{node5.id}", :format => "json")
80 js = ActiveSupport::JSON.decode(@response.body)
82 assert_equal 5, js["elements"].count
83 assert_equal(5, js["elements"].count { |a| a["type"] == "node" })
84 assert_equal(1, js["elements"].count { |a| a["id"] == node1.id && a["visible"].nil? })
85 assert_equal(1, js["elements"].count { |a| a["id"] == node2.id && a["visible"] == false })
86 assert_equal(1, js["elements"].count { |a| a["id"] == node3.id && a["visible"].nil? })
87 assert_equal(1, js["elements"].count { |a| a["id"] == node4.id && a["visible"].nil? })
88 assert_equal(1, js["elements"].count { |a| a["id"] == node5.id && a["visible"] == false })
90 # check error when a non-existent node is included
91 get api_nodes_path(:nodes => "#{node1.id},#{node2.id},#{node3.id},#{node4.id},#{node5.id},0")
92 assert_response :not_found
95 def test_create_when_unauthorized
96 with_unchanging_request do |_headers, changeset|
97 osm = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
99 post api_nodes_path, :params => osm
101 assert_response :unauthorized
105 def test_create_by_private_user
106 with_unchanging_request([:data_public => false]) do |headers, changeset|
107 osm = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
109 post api_nodes_path, :params => osm, :headers => headers
111 assert_require_public_data "node create did not return forbidden status"
116 with_request do |headers, changeset|
117 lat = rand(-50..50) + rand
118 lon = rand(-50..50) + rand
120 assert_difference "Node.count", 1 do
121 osm = "<osm><node lat='#{lat}' lon='#{lon}' changeset='#{changeset.id}'/></osm>"
123 post api_nodes_path, :params => osm, :headers => headers
125 assert_response :success, "node upload did not return success status"
128 created_node_id = @response.body
129 node = Node.find(created_node_id)
130 assert_in_delta lat * 10000000, node.latitude, 1, "saved node does not match requested latitude"
131 assert_in_delta lon * 10000000, node.longitude, 1, "saved node does not match requested longitude"
132 assert_equal changeset.id, node.changeset_id, "saved node does not belong to changeset that it was created in"
133 assert node.visible, "saved node is not visible"
136 assert_equal 1, changeset.num_changes
137 assert_predicate changeset, :num_type_changes_in_sync?
138 assert_equal 1, changeset.num_created_nodes
142 def test_create_in_missing_changeset
143 with_unchanging_request do |headers|
144 osm = "<osm><node lat='0' lon='0' changeset='0'/></osm>"
146 post api_nodes_path, :params => osm, :headers => headers
148 assert_response :conflict
152 def test_create_with_invalid_osm_structure
153 with_unchanging_request do |headers|
156 post api_nodes_path, :params => osm, :headers => headers
158 assert_response :bad_request, "node upload did not return bad_request status"
159 assert_equal "Cannot parse valid node from xml string <create/>. XML doesn't contain an osm/node element.", @response.body
163 def test_create_without_lat
164 with_unchanging_request do |headers, changeset|
165 osm = "<osm><node lon='3.23' changeset='#{changeset.id}'/></osm>"
167 post api_nodes_path, :params => osm, :headers => headers
169 assert_response :bad_request, "node upload did not return bad_request status"
170 assert_equal "Cannot parse valid node from xml string <node lon=\"3.23\" changeset=\"#{changeset.id}\"/>. lat missing", @response.body
174 def test_create_without_lon
175 with_unchanging_request do |headers, changeset|
176 osm = "<osm><node lat='3.434' changeset='#{changeset.id}'/></osm>"
178 post api_nodes_path, :params => osm, :headers => headers
180 assert_response :bad_request, "node upload did not return bad_request status"
181 assert_equal "Cannot parse valid node from xml string <node lat=\"3.434\" changeset=\"#{changeset.id}\"/>. lon missing", @response.body
185 def test_create_with_non_numeric_lat
186 with_unchanging_request do |headers, changeset|
187 osm = "<osm><node lat='abc' lon='3.23' changeset='#{changeset.id}'/></osm>"
189 post api_nodes_path, :params => osm, :headers => headers
191 assert_response :bad_request, "node upload did not return bad_request status"
192 assert_equal "Cannot parse valid node from xml string <node lat=\"abc\" lon=\"3.23\" changeset=\"#{changeset.id}\"/>. lat not a number", @response.body
196 def test_create_with_non_numeric_lon
197 with_unchanging_request do |headers, changeset|
198 osm = "<osm><node lat='3.434' lon='abc' changeset='#{changeset.id}'/></osm>"
200 post api_nodes_path, :params => osm, :headers => headers
202 assert_response :bad_request, "node upload did not return bad_request status"
203 assert_equal "Cannot parse valid node from xml string <node lat=\"3.434\" lon=\"abc\" changeset=\"#{changeset.id}\"/>. lon not a number", @response.body
207 def test_create_with_tag_too_long
208 with_unchanging_request do |headers, changeset|
209 osm = "<osm><node lat='3.434' lon='3.23' changeset='#{changeset.id}'><tag k='foo' v='#{'x' * 256}'/></node></osm>"
211 post api_nodes_path, :params => osm, :headers => headers
213 assert_response :bad_request, "node upload did not return bad_request status"
214 assert_match(/ v: is too long \(maximum is 255 characters\) /, @response.body)
219 # try and put something into a string that the API might
220 # use unquoted and therefore allow code injection
221 def test_create_with_string_injection_by_private_user
222 with_unchanging_request([:data_public => false]) do |headers, changeset|
225 <node lat='0' lon='0' changeset='#{changeset.id}'>
226 <tag k='\#{@user.inspect}' v='0'/>
231 post api_nodes_path, :params => osm, :headers => headers
233 assert_require_public_data "Shouldn't be able to create with non-public user"
238 # try and put something into a string that the API might
239 # use unquoted and therefore allow code injection
240 def test_create_with_string_injection
241 with_request do |headers, changeset|
242 assert_difference "Node.count", 1 do
245 <node lat='0' lon='0' changeset='#{changeset.id}'>
246 <tag k='\#{@user.inspect}' v='0'/>
251 post api_nodes_path, :params => osm, :headers => headers
253 assert_response :success
256 created_node_id = @response.body
257 db_node = Node.find(created_node_id)
259 get api_node_path(created_node_id)
261 assert_response :success
263 api_node = Node.from_xml(@response.body)
264 assert_not_nil api_node, "downloaded node is nil, but shouldn't be"
265 assert_equal db_node.tags, api_node.tags, "tags are corrupted"
266 assert_includes api_node.tags, "\#{@user.inspect}"
270 def test_create_race_condition
272 changeset = create(:changeset, :user => user)
273 auth_header = bearer_authorization_header user
274 path = api_nodes_path
275 concurrency_level = 16
277 threads = Array.new(concurrency_level) do
279 osm = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
280 post path, :params => osm, :headers => auth_header
286 assert_equal concurrency_level, changeset.num_changes
287 assert_predicate changeset, :num_type_changes_in_sync?
288 assert_equal concurrency_level, changeset.num_created_nodes
291 def test_show_not_found
293 assert_response :not_found
296 def test_show_deleted
297 get api_node_path(create(:node, :deleted))
298 assert_response :gone
302 node = create(:node, :timestamp => "2021-02-03T00:00:00Z")
304 get api_node_path(node)
306 assert_response :success
307 assert_not_nil @response.header["Last-Modified"]
308 assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
311 def test_show_lat_lon_decimal_format
312 node = create(:node, :latitude => (0.00004 * OldNode::SCALE).to_i, :longitude => (0.00008 * OldNode::SCALE).to_i)
314 get api_node_path(node)
316 assert_match(/lat="0.0000400"/, response.body)
317 assert_match(/lon="0.0000800"/, response.body)
320 def test_destroy_when_unauthorized
321 with_unchanging(:node) do |node|
322 delete api_node_path(node)
324 assert_response :unauthorized
328 def test_destroy_in_closed_changeset_by_private_user
329 with_unchanging(:node) do |node|
330 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
331 osm_xml = xml_for_node node
332 osm_xml = update_changeset osm_xml, changeset.id
334 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
336 assert_require_public_data "non-public user shouldn't be able to delete node"
341 def test_destroy_in_missing_changeset_by_private_user
342 with_unchanging(:node) do |node|
343 with_unchanging_request([:data_public => false]) do |headers|
344 osm_xml = xml_for_node node
345 osm_xml = update_changeset osm_xml, 0
347 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
349 assert_require_public_data "shouldn't be able to delete node, when user's data is private"
354 def test_destroy_by_private_user
355 with_unchanging(:node) do |node|
356 with_unchanging_request([:data_public => false]) do |headers, changeset|
357 osm_xml = xml_for_node node
358 osm_xml = update_changeset osm_xml, changeset.id
360 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
362 assert_require_public_data "shouldn't be able to delete node when user's data isn't public'"
367 def test_destroy_deleted_node_by_private_user
368 with_unchanging(:node, :deleted) do |node|
369 with_unchanging_request([:data_public => false]) do |headers, changeset|
370 osm_xml = "<osm><node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/></osm>"
372 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
374 assert_require_public_data
379 def test_destroy_missing_node_by_private_user
380 with_unchanging_request([:data_public => false]) do |headers|
381 delete api_node_path(0), :headers => headers
383 assert_require_public_data
387 def test_destroy_node_in_way_by_private_user
388 with_unchanging(:node) do |node|
389 create(:way_node, :node => node)
391 with_unchanging_request([:data_public => false]) do |headers, changeset|
392 osm_xml = xml_for_node node
393 osm_xml = update_changeset osm_xml, changeset.id
395 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
397 assert_require_public_data "shouldn't be able to delete a node used in a way (#{@response.body})"
402 def test_destroy_node_in_relation_by_private_user
403 with_unchanging(:node) do |node|
404 create(:relation_member, :member => node)
406 with_unchanging_request([:data_public => false]) do |headers, changeset|
407 osm_xml = xml_for_node node
408 osm_xml = update_changeset osm_xml, changeset.id
410 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
412 assert_require_public_data "shouldn't be able to delete a node used in a relation (#{@response.body})"
417 def test_destroy_in_closed_changeset
418 with_unchanging(:node) do |node|
419 with_unchanging_request([], [:closed]) do |headers, changeset|
420 osm_xml = xml_for_node node
421 osm_xml = update_changeset osm_xml, changeset.id
423 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
425 assert_response :conflict
430 def test_destroy_in_missing_changeset
431 with_unchanging(:node) do |node|
432 with_unchanging_request do |headers|
433 osm_xml = xml_for_node node
434 osm_xml = update_changeset osm_xml, 0
436 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
438 assert_response :conflict
443 def test_destroy_different_node
444 with_unchanging(:node) do |node|
445 with_unchanging(:node) do |other_node|
446 with_unchanging_request do |headers, changeset|
447 osm_xml = xml_for_node other_node
448 osm_xml = update_changeset osm_xml, changeset.id
450 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
452 assert_response :bad_request, "should not be able to delete a node with a different ID from the XML"
458 def test_destroy_invalid_osm_structure
459 with_unchanging(:node) do |node|
460 with_unchanging_request do |headers|
463 delete api_node_path(node), :params => osm, :headers => headers
465 assert_response :bad_request, "should not be able to delete a node without a valid XML payload"
471 with_request do |headers, changeset|
473 osm_xml = xml_for_node node
474 osm_xml = update_changeset osm_xml, changeset.id
476 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
478 assert_response :success
480 response_node_version = @response.body.to_i
481 assert_operator response_node_version, :>, node.version, "delete request should return a new version number for node"
483 assert_not_predicate node, :visible?
484 assert_equal response_node_version, node.version
487 assert_equal 1, changeset.num_changes
488 assert_predicate changeset, :num_type_changes_in_sync?
489 assert_equal 1, changeset.num_deleted_nodes
493 def test_destroy_twice
495 node = create(:node, :changeset => create(:changeset, :user => user))
496 osm_xml = xml_for_node node
498 delete api_node_path(node), :params => osm_xml.to_s, :headers => bearer_authorization_header(user)
500 assert_response :success
502 delete api_node_path(node), :params => osm_xml.to_s, :headers => bearer_authorization_header(user)
504 assert_response :gone
507 def test_destroy_deleted_node
508 with_unchanging(:node, :deleted) do |node|
509 with_unchanging_request do |headers, changeset|
510 osm = "<osm><node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/></osm>"
512 delete api_node_path(node), :params => osm, :headers => headers
514 assert_response :gone
519 def test_destroy_missing_node
520 with_unchanging_request do |headers|
521 delete api_node_path(0), :headers => headers
523 assert_response :not_found
527 def test_destroy_node_in_ways
528 with_unchanging(:node) do |node|
529 way_node = create(:way_node, :node => node)
530 way_node2 = create(:way_node, :node => node)
532 with_unchanging_request do |headers, changeset|
533 osm_xml = xml_for_node node
534 osm_xml = update_changeset osm_xml, changeset.id
536 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
538 assert_response :precondition_failed, "shouldn't be able to delete a node used in a way (#{@response.body})"
539 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way_node.way.id},#{way_node2.way.id}.", @response.body
544 def test_destroy_node_in_relations
545 with_unchanging(:node) do |node|
546 relation_member = create(:relation_member, :member => node)
547 relation_member2 = create(:relation_member, :member => node)
549 with_unchanging_request do |headers, changeset|
550 osm_xml = xml_for_node node
551 osm_xml = update_changeset osm_xml, changeset.id
553 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
555 assert_response :precondition_failed, "shouldn't be able to delete a node used in a relation (#{@response.body})"
556 assert_equal "Precondition failed: Node #{node.id} is still used by relations #{relation_member.relation.id},#{relation_member2.relation.id}.", @response.body
561 def test_update_when_unauthorized
562 with_unchanging(:node) do |node|
563 osm_xml = xml_for_node node
565 put api_node_path(node), :params => osm_xml.to_s
567 assert_response :unauthorized
571 def test_update_in_changeset_of_other_user_by_private_user
572 with_unchanging(:node) do |node|
573 other_user = create(:user)
575 with_unchanging_request([:data_public => false], [:user => other_user]) do |headers, changeset|
576 osm_xml = xml_for_node node
577 osm_xml = update_changeset osm_xml, changeset.id
579 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
581 assert_require_public_data "update with other user's changeset should be forbidden when data isn't public"
586 def test_update_in_closed_changeset_by_private_user
587 with_unchanging(:node) do |node|
588 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
589 osm_xml = xml_for_node node
590 osm_xml = update_changeset osm_xml, changeset.id
592 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
594 assert_require_public_data "update with closed changeset should be forbidden, when data isn't public"
599 def test_update_in_missing_changeset_by_private_user
600 with_unchanging(:node) do |node|
601 with_unchanging_request([:data_public => false]) do |headers|
602 osm_xml = xml_for_node node
603 osm_xml = update_changeset osm_xml, 0
605 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
607 assert_require_public_data "update with changeset=0 should be forbidden, when data isn't public"
612 def test_update_with_lat_too_large_by_private_user
613 check_update_with_invalid_attr_value "lat", 91.0, :data_public => false
616 def test_update_with_lat_too_small_by_private_user
617 check_update_with_invalid_attr_value "lat", -91.0, :data_public => false
620 def test_update_with_lon_too_large_by_private_user
621 check_update_with_invalid_attr_value "lon", 181.0, :data_public => false
624 def test_update_with_lon_too_small_by_private_user
625 check_update_with_invalid_attr_value "lon", -181.0, :data_public => false
628 def test_update_by_private_user
629 with_unchanging(:node) do |node|
630 with_unchanging_request([:data_public => false]) do |headers, changeset|
631 osm_xml = xml_for_node node
632 osm_xml = update_changeset osm_xml, changeset.id
634 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
636 assert_require_public_data "should have failed with a forbidden when data isn't public"
641 def test_update_in_changeset_of_other_user
642 with_unchanging(:node) do |node|
643 other_user = create(:user)
645 with_unchanging_request([], [:user => other_user]) do |headers, changeset|
646 osm_xml = xml_for_node node
647 osm_xml = update_changeset osm_xml, changeset.id
649 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
651 assert_response :conflict, "update with other user's changeset should be rejected"
656 def test_update_in_closed_changeset
657 with_unchanging(:node) do |node|
658 with_unchanging_request([], [:closed]) do |headers, changeset|
659 osm_xml = xml_for_node node
660 osm_xml = update_changeset osm_xml, changeset.id
662 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
664 assert_response :conflict, "update with closed changeset should be rejected"
669 def test_update_in_missing_changeset
670 with_unchanging(:node) do |node|
671 with_unchanging_request do |headers|
672 osm_xml = xml_for_node node
673 osm_xml = update_changeset osm_xml, 0
675 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
677 assert_response :conflict, "update with changeset=0 should be rejected"
682 def test_update_with_lat_too_large
683 check_update_with_invalid_attr_value "lat", 91.0
686 def test_update_with_lat_too_small
687 check_update_with_invalid_attr_value "lat", -91.0
690 def test_update_with_lon_too_large
691 check_update_with_invalid_attr_value "lon", 181.0
694 def test_update_with_lon_too_small
695 check_update_with_invalid_attr_value "lon", -181.0
698 def test_update_with_version_behind
699 with_unchanging(:node, :version => 2) do |node|
700 with_unchanging_request do |headers, changeset|
701 osm_xml = xml_for_node node
702 osm_xml = xml_attr_rewrite osm_xml, "version", node.version - 1
703 osm_xml = update_changeset osm_xml, changeset.id
705 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
707 assert_response :conflict, "should have failed on old version number"
712 def test_update_with_version_ahead
713 with_unchanging(:node, :version => 2) do |node|
714 with_unchanging_request do |headers, changeset|
715 osm_xml = xml_for_node node
716 osm_xml = xml_attr_rewrite osm_xml, "version", node.version + 1
717 osm_xml = update_changeset osm_xml, changeset.id
719 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
721 assert_response :conflict, "should have failed on skipped version number"
726 def test_update_with_invalid_version
727 with_unchanging(:node) do |node|
728 with_unchanging_request do |headers, changeset|
729 osm_xml = xml_for_node node
730 osm_xml = xml_attr_rewrite osm_xml, "version", "p1r4t3s!"
731 osm_xml = update_changeset osm_xml, changeset.id
733 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
735 assert_response :conflict, "should not be able to put 'p1r4at3s!' in the version field"
740 def test_update_other_node
741 with_unchanging(:node) do |node|
742 with_unchanging(:node) do |other_node|
743 with_unchanging_request do |headers, changeset|
744 osm_xml = xml_for_node other_node
745 osm_xml = update_changeset osm_xml, changeset.id
747 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
749 assert_response :bad_request, "should not be able to update a node with a different ID from the XML"
755 def test_update_with_invalid_osm_structure
756 with_unchanging(:node) do |node|
757 with_unchanging_request do |headers|
760 put api_node_path(node), :params => osm, :headers => headers
762 assert_response :bad_request, "should not be able to update a node with non-OSM XML doc."
768 with_request do |headers, changeset|
770 osm_xml = xml_for_node node
771 osm_xml = update_changeset osm_xml, changeset.id
773 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
775 assert_response :success, "a valid update request failed"
778 assert_equal 1, changeset.num_changes
779 assert_predicate changeset, :num_type_changes_in_sync?
780 assert_equal 1, changeset.num_modified_nodes
784 def test_update_with_duplicate_tags
785 with_unchanging(:node) do |node|
786 create(:node_tag, :node => node, :k => "key_to_duplicate", :v => "value_to_duplicate")
788 with_unchanging_request do |headers, changeset|
789 tag_xml = XML::Node.new("tag")
790 tag_xml["k"] = "key_to_duplicate"
791 tag_xml["v"] = "value_to_duplicate"
793 osm_xml = xml_for_node node
794 osm_xml.find("//osm/node").first << tag_xml
795 osm_xml = update_changeset osm_xml, changeset.id
797 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
799 assert_response :bad_request, "adding duplicate tags to a node should fail with 'bad request'"
800 assert_equal "Element node/#{node.id} has duplicate tags with key key_to_duplicate", @response.body
806 # test initial rate limit
807 def test_initial_rate_limit
811 # create a changeset that puts us near the initial rate limit
812 changeset = create(:changeset, :user => user,
813 :created_at => Time.now.utc - 5.minutes,
814 :num_changes => Settings.initial_changes_per_hour - 1)
816 # create authentication header
817 auth_header = bearer_authorization_header user
819 # try creating a node
820 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
821 post api_nodes_path, :params => xml, :headers => auth_header
822 assert_response :success, "node create did not return success status"
824 # get the id of the node we created
825 nodeid = @response.body
827 # try updating the node, which should be rate limited
828 xml = "<osm><node id='#{nodeid}' version='1' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
829 put api_node_path(nodeid), :params => xml, :headers => auth_header
830 assert_response :too_many_requests, "node update did not hit rate limit"
832 # try deleting the node, which should be rate limited
833 xml = "<osm><node id='#{nodeid}' version='2' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
834 delete api_node_path(nodeid), :params => xml, :headers => auth_header
835 assert_response :too_many_requests, "node delete did not hit rate limit"
837 # try creating a node, which should be rate limited
838 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
839 post api_nodes_path, :params => xml, :headers => auth_header
840 assert_response :too_many_requests, "node create did not hit rate limit"
844 # test maximum rate limit
845 def test_maximum_rate_limit
849 # create a changeset to establish our initial edit time
850 changeset = create(:changeset, :user => user,
851 :created_at => Time.now.utc - 28.days)
853 # create changeset to put us near the maximum rate limit
854 total_changes = Settings.max_changes_per_hour - 1
855 while total_changes.positive?
856 changes = [total_changes, Changeset::MAX_ELEMENTS].min
857 changeset = create(:changeset, :user => user,
858 :created_at => Time.now.utc - 5.minutes,
859 :num_changes => changes)
860 total_changes -= changes
863 # create authentication header
864 auth_header = bearer_authorization_header user
866 # try creating a node
867 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
868 post api_nodes_path, :params => xml, :headers => auth_header
869 assert_response :success, "node create did not return success status"
871 # get the id of the node we created
872 nodeid = @response.body
874 # try updating the node, which should be rate limited
875 xml = "<osm><node id='#{nodeid}' version='1' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
876 put api_node_path(nodeid), :params => xml, :headers => auth_header
877 assert_response :too_many_requests, "node update did not hit rate limit"
879 # try deleting the node, which should be rate limited
880 xml = "<osm><node id='#{nodeid}' version='2' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
881 delete api_node_path(nodeid), :params => xml, :headers => auth_header
882 assert_response :too_many_requests, "node delete did not hit rate limit"
884 # try creating a node, which should be rate limited
885 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
886 post api_nodes_path, :params => xml, :headers => auth_header
887 assert_response :too_many_requests, "node create did not hit rate limit"
892 def check_update_with_invalid_attr_value(name, value, data_public: true)
893 with_unchanging(:node) do |node|
894 with_unchanging_request([:data_public => data_public]) do |headers, changeset|
895 osm_xml = xml_for_node node
896 osm_xml = xml_attr_rewrite osm_xml, name, value
897 osm_xml = update_changeset osm_xml, changeset.id
899 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
902 assert_response :bad_request, "node at #{name}=#{value} should be rejected"
904 assert_require_public_data "node at #{name}=#{value} should be forbidden, when data isn't public"
916 # update an attribute in the node element
917 def xml_attr_rewrite(xml, name, value)
918 xml.find("//osm/node").first[name] = value.to_s