2 require_relative "elements_test_helper"
5 class NodesControllerTest < ActionDispatch::IntegrationTest
6 include ElementsTestHelper
9 # test all routes which lead to this controller
12 { :path => "/api/0.6/nodes", :method => :get },
13 { :controller => "api/nodes", :action => "index" }
16 { :path => "/api/0.6/nodes.json", :method => :get },
17 { :controller => "api/nodes", :action => "index", :format => "json" }
20 { :path => "/api/0.6/nodes", :method => :post },
21 { :controller => "api/nodes", :action => "create" }
24 { :path => "/api/0.6/node/1", :method => :get },
25 { :controller => "api/nodes", :action => "show", :id => "1" }
28 { :path => "/api/0.6/node/1.json", :method => :get },
29 { :controller => "api/nodes", :action => "show", :id => "1", :format => "json" }
32 { :path => "/api/0.6/node/1", :method => :put },
33 { :controller => "api/nodes", :action => "update", :id => "1" }
36 { :path => "/api/0.6/node/1", :method => :delete },
37 { :controller => "api/nodes", :action => "destroy", :id => "1" }
41 { :controller => "api/nodes", :action => "create" },
42 { :path => "/api/0.6/node/create", :method => :put }
47 # test fetching multiple nodes
50 node2 = create(:node, :deleted)
52 node4 = create(:node, :with_history, :version => 2)
53 node5 = create(:node, :deleted, :with_history, :version => 2)
55 # check error when no parameter provided
57 assert_response :bad_request
59 # check error when no parameter value provided
60 get api_nodes_path(:nodes => "")
61 assert_response :bad_request
64 get api_nodes_path(:nodes => "#{node1.id},#{node2.id},#{node3.id},#{node4.id},#{node5.id}")
65 assert_response :success
66 assert_select "osm" do
67 assert_select "node", :count => 5
68 assert_select "node[id='#{node1.id}'][visible='true']", :count => 1
69 assert_select "node[id='#{node2.id}'][visible='false']", :count => 1
70 assert_select "node[id='#{node3.id}'][visible='true']", :count => 1
71 assert_select "node[id='#{node4.id}'][visible='true']", :count => 1
72 assert_select "node[id='#{node5.id}'][visible='false']", :count => 1
75 # test a working call with json format
76 get api_nodes_path(:nodes => "#{node1.id},#{node2.id},#{node3.id},#{node4.id},#{node5.id}", :format => "json")
78 js = ActiveSupport::JSON.decode(@response.body)
80 assert_equal 5, js["elements"].count
81 assert_equal(5, js["elements"].count { |a| a["type"] == "node" })
82 assert_equal(1, js["elements"].count { |a| a["id"] == node1.id && a["visible"].nil? })
83 assert_equal(1, js["elements"].count { |a| a["id"] == node2.id && a["visible"] == false })
84 assert_equal(1, js["elements"].count { |a| a["id"] == node3.id && a["visible"].nil? })
85 assert_equal(1, js["elements"].count { |a| a["id"] == node4.id && a["visible"].nil? })
86 assert_equal(1, js["elements"].count { |a| a["id"] == node5.id && a["visible"] == false })
88 # check error when a non-existent node is included
89 get api_nodes_path(:nodes => "#{node1.id},#{node2.id},#{node3.id},#{node4.id},#{node5.id},0")
90 assert_response :not_found
93 def test_create_when_unauthorized
94 with_unchanging_request do |_headers, changeset|
95 osm = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
97 post api_nodes_path, :params => osm
99 assert_response :unauthorized
103 def test_create_by_private_user
104 with_unchanging_request([:data_public => false]) do |headers, changeset|
105 osm = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
107 post api_nodes_path, :params => osm, :headers => headers
109 assert_require_public_data "node create did not return forbidden status"
114 with_request do |headers, changeset|
115 lat = rand(-50..50) + rand
116 lon = rand(-50..50) + rand
118 assert_difference "Node.count", 1 do
119 osm = "<osm><node lat='#{lat}' lon='#{lon}' changeset='#{changeset.id}'/></osm>"
121 post api_nodes_path, :params => osm, :headers => headers
123 assert_response :success, "node upload did not return success status"
126 created_node_id = @response.body
127 node = Node.find(created_node_id)
128 assert_in_delta lat * 10000000, node.latitude, 1, "saved node does not match requested latitude"
129 assert_in_delta lon * 10000000, node.longitude, 1, "saved node does not match requested longitude"
130 assert_equal changeset.id, node.changeset_id, "saved node does not belong to changeset that it was created in"
131 assert node.visible, "saved node is not visible"
134 assert_equal 1, changeset.num_changes
135 assert_predicate changeset, :num_type_changes_in_sync?
136 assert_equal 1, changeset.num_created_nodes
140 def test_create_in_missing_changeset
141 with_unchanging_request do |headers|
142 osm = "<osm><node lat='0' lon='0' changeset='0'/></osm>"
144 post api_nodes_path, :params => osm, :headers => headers
146 assert_response :conflict
150 def test_create_with_invalid_osm_structure
151 with_unchanging_request do |headers|
154 post api_nodes_path, :params => osm, :headers => headers
156 assert_response :bad_request, "node upload did not return bad_request status"
157 assert_equal "Cannot parse valid node from xml string <create/>. XML doesn't contain an osm/node element.", @response.body
161 def test_create_without_lat
162 with_unchanging_request do |headers, changeset|
163 osm = "<osm><node lon='3.23' changeset='#{changeset.id}'/></osm>"
165 post api_nodes_path, :params => osm, :headers => headers
167 assert_response :bad_request, "node upload did not return bad_request status"
168 assert_equal "Cannot parse valid node from xml string <node lon=\"3.23\" changeset=\"#{changeset.id}\"/>. lat missing", @response.body
172 def test_create_without_lon
173 with_unchanging_request do |headers, changeset|
174 osm = "<osm><node lat='3.434' changeset='#{changeset.id}'/></osm>"
176 post api_nodes_path, :params => osm, :headers => headers
178 assert_response :bad_request, "node upload did not return bad_request status"
179 assert_equal "Cannot parse valid node from xml string <node lat=\"3.434\" changeset=\"#{changeset.id}\"/>. lon missing", @response.body
183 def test_create_with_non_numeric_lat
184 with_unchanging_request do |headers, changeset|
185 osm = "<osm><node lat='abc' lon='3.23' changeset='#{changeset.id}'/></osm>"
187 post api_nodes_path, :params => osm, :headers => headers
189 assert_response :bad_request, "node upload did not return bad_request status"
190 assert_equal "Cannot parse valid node from xml string <node lat=\"abc\" lon=\"3.23\" changeset=\"#{changeset.id}\"/>. lat not a number", @response.body
194 def test_create_with_non_numeric_lon
195 with_unchanging_request do |headers, changeset|
196 osm = "<osm><node lat='3.434' lon='abc' changeset='#{changeset.id}'/></osm>"
198 post api_nodes_path, :params => osm, :headers => headers
200 assert_response :bad_request, "node upload did not return bad_request status"
201 assert_equal "Cannot parse valid node from xml string <node lat=\"3.434\" lon=\"abc\" changeset=\"#{changeset.id}\"/>. lon not a number", @response.body
205 def test_create_with_tag_too_long
206 with_unchanging_request do |headers, changeset|
207 osm = "<osm><node lat='3.434' lon='3.23' changeset='#{changeset.id}'><tag k='foo' v='#{'x' * 256}'/></node></osm>"
209 post api_nodes_path, :params => osm, :headers => headers
211 assert_response :bad_request, "node upload did not return bad_request status"
212 assert_match(/ v: is too long \(maximum is 255 characters\) /, @response.body)
217 # try and put something into a string that the API might
218 # use unquoted and therefore allow code injection
219 def test_create_with_string_injection_by_private_user
220 with_unchanging_request([:data_public => false]) do |headers, changeset|
223 <node lat='0' lon='0' changeset='#{changeset.id}'>
224 <tag k='\#{@user.inspect}' v='0'/>
229 post api_nodes_path, :params => osm, :headers => headers
231 assert_require_public_data "Shouldn't be able to create with non-public user"
236 # try and put something into a string that the API might
237 # use unquoted and therefore allow code injection
238 def test_create_with_string_injection
239 with_request do |headers, changeset|
240 assert_difference "Node.count", 1 do
243 <node lat='0' lon='0' changeset='#{changeset.id}'>
244 <tag k='\#{@user.inspect}' v='0'/>
249 post api_nodes_path, :params => osm, :headers => headers
251 assert_response :success
254 created_node_id = @response.body
255 db_node = Node.find(created_node_id)
257 get api_node_path(created_node_id)
259 assert_response :success
261 api_node = Node.from_xml(@response.body)
262 assert_not_nil api_node, "downloaded node is nil, but shouldn't be"
263 assert_equal db_node.tags, api_node.tags, "tags are corrupted"
264 assert_includes api_node.tags, "\#{@user.inspect}"
268 def test_show_not_found
270 assert_response :not_found
273 def test_show_deleted
274 get api_node_path(create(:node, :deleted))
275 assert_response :gone
279 node = create(:node, :timestamp => "2021-02-03T00:00:00Z")
281 get api_node_path(node)
283 assert_response :success
284 assert_not_nil @response.header["Last-Modified"]
285 assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
288 def test_show_lat_lon_decimal_format
289 node = create(:node, :latitude => (0.00004 * OldNode::SCALE).to_i, :longitude => (0.00008 * OldNode::SCALE).to_i)
291 get api_node_path(node)
293 assert_match(/lat="0.0000400"/, response.body)
294 assert_match(/lon="0.0000800"/, response.body)
297 def test_destroy_when_unauthorized
298 with_unchanging(:node) do |node|
299 delete api_node_path(node)
301 assert_response :unauthorized
305 def test_destroy_in_closed_changeset_by_private_user
306 with_unchanging(:node) do |node|
307 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
308 osm_xml = xml_for_node node
309 osm_xml = update_changeset osm_xml, changeset.id
311 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
313 assert_require_public_data "non-public user shouldn't be able to delete node"
318 def test_destroy_in_missing_changeset_by_private_user
319 with_unchanging(:node) do |node|
320 with_unchanging_request([:data_public => false]) do |headers|
321 osm_xml = xml_for_node node
322 osm_xml = update_changeset osm_xml, 0
324 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
326 assert_require_public_data "shouldn't be able to delete node, when user's data is private"
331 def test_destroy_by_private_user
332 with_unchanging(:node) do |node|
333 with_unchanging_request([:data_public => false]) do |headers, changeset|
334 osm_xml = xml_for_node node
335 osm_xml = update_changeset osm_xml, changeset.id
337 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
339 assert_require_public_data "shouldn't be able to delete node when user's data isn't public'"
344 def test_destroy_deleted_node_by_private_user
345 with_unchanging(:node, :deleted) do |node|
346 with_unchanging_request([:data_public => false]) do |headers, changeset|
347 osm_xml = "<osm><node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/></osm>"
349 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
351 assert_require_public_data
356 def test_destroy_missing_node_by_private_user
357 with_unchanging_request([:data_public => false]) do |headers|
358 delete api_node_path(0), :headers => headers
360 assert_require_public_data
364 def test_destroy_node_in_way_by_private_user
365 with_unchanging(:node) do |node|
366 create(:way_node, :node => node)
368 with_unchanging_request([:data_public => false]) do |headers, changeset|
369 osm_xml = xml_for_node node
370 osm_xml = update_changeset osm_xml, changeset.id
372 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
374 assert_require_public_data "shouldn't be able to delete a node used in a way (#{@response.body})"
379 def test_destroy_node_in_relation_by_private_user
380 with_unchanging(:node) do |node|
381 create(:relation_member, :member => node)
383 with_unchanging_request([:data_public => false]) do |headers, changeset|
384 osm_xml = xml_for_node node
385 osm_xml = update_changeset osm_xml, changeset.id
387 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
389 assert_require_public_data "shouldn't be able to delete a node used in a relation (#{@response.body})"
394 def test_destroy_in_closed_changeset
395 with_unchanging(:node) do |node|
396 with_unchanging_request([], [:closed]) do |headers, changeset|
397 osm_xml = xml_for_node node
398 osm_xml = update_changeset osm_xml, changeset.id
400 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
402 assert_response :conflict
407 def test_destroy_in_missing_changeset
408 with_unchanging(:node) do |node|
409 with_unchanging_request do |headers|
410 osm_xml = xml_for_node node
411 osm_xml = update_changeset osm_xml, 0
413 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
415 assert_response :conflict
420 def test_destroy_different_node
421 with_unchanging(:node) do |node|
422 with_unchanging(:node) do |other_node|
423 with_unchanging_request do |headers, changeset|
424 osm_xml = xml_for_node other_node
425 osm_xml = update_changeset osm_xml, changeset.id
427 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
429 assert_response :bad_request, "should not be able to delete a node with a different ID from the XML"
435 def test_destroy_invalid_osm_structure
436 with_unchanging(:node) do |node|
437 with_unchanging_request do |headers|
440 delete api_node_path(node), :params => osm, :headers => headers
442 assert_response :bad_request, "should not be able to delete a node without a valid XML payload"
448 with_request do |headers, changeset|
450 osm_xml = xml_for_node node
451 osm_xml = update_changeset osm_xml, changeset.id
453 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
455 assert_response :success
457 response_node_version = @response.body.to_i
458 assert_operator response_node_version, :>, node.version, "delete request should return a new version number for node"
460 assert_not_predicate node, :visible?
461 assert_equal response_node_version, node.version
464 assert_equal 1, changeset.num_changes
465 assert_predicate changeset, :num_type_changes_in_sync?
466 assert_equal 1, changeset.num_deleted_nodes
470 def test_destroy_twice
472 node = create(:node, :changeset => create(:changeset, :user => user))
473 osm_xml = xml_for_node node
475 delete api_node_path(node), :params => osm_xml.to_s, :headers => bearer_authorization_header(user)
477 assert_response :success
479 delete api_node_path(node), :params => osm_xml.to_s, :headers => bearer_authorization_header(user)
481 assert_response :gone
484 def test_destroy_deleted_node
485 with_unchanging(:node, :deleted) do |node|
486 with_unchanging_request do |headers, changeset|
487 osm = "<osm><node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/></osm>"
489 delete api_node_path(node), :params => osm, :headers => headers
491 assert_response :gone
496 def test_destroy_missing_node
497 with_unchanging_request do |headers|
498 delete api_node_path(0), :headers => headers
500 assert_response :not_found
504 def test_destroy_node_in_ways
505 with_unchanging(:node) do |node|
506 way_node = create(:way_node, :node => node)
507 way_node2 = create(:way_node, :node => node)
509 with_unchanging_request do |headers, changeset|
510 osm_xml = xml_for_node node
511 osm_xml = update_changeset osm_xml, changeset.id
513 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
515 assert_response :precondition_failed, "shouldn't be able to delete a node used in a way (#{@response.body})"
516 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way_node.way.id},#{way_node2.way.id}.", @response.body
521 def test_destroy_node_in_relations
522 with_unchanging(:node) do |node|
523 relation_member = create(:relation_member, :member => node)
524 relation_member2 = create(:relation_member, :member => node)
526 with_unchanging_request do |headers, changeset|
527 osm_xml = xml_for_node node
528 osm_xml = update_changeset osm_xml, changeset.id
530 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
532 assert_response :precondition_failed, "shouldn't be able to delete a node used in a relation (#{@response.body})"
533 assert_equal "Precondition failed: Node #{node.id} is still used by relations #{relation_member.relation.id},#{relation_member2.relation.id}.", @response.body
538 def test_update_when_unauthorized
539 with_unchanging(:node) do |node|
540 osm_xml = xml_for_node node
542 put api_node_path(node), :params => osm_xml.to_s
544 assert_response :unauthorized
548 def test_update_in_changeset_of_other_user_by_private_user
549 with_unchanging(:node) do |node|
550 other_user = create(:user)
552 with_unchanging_request([:data_public => false], [:user => other_user]) do |headers, changeset|
553 osm_xml = xml_for_node node
554 osm_xml = update_changeset osm_xml, changeset.id
556 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
558 assert_require_public_data "update with other user's changeset should be forbidden when data isn't public"
563 def test_update_in_closed_changeset_by_private_user
564 with_unchanging(:node) do |node|
565 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
566 osm_xml = xml_for_node node
567 osm_xml = update_changeset osm_xml, changeset.id
569 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
571 assert_require_public_data "update with closed changeset should be forbidden, when data isn't public"
576 def test_update_in_missing_changeset_by_private_user
577 with_unchanging(:node) do |node|
578 with_unchanging_request([:data_public => false]) do |headers|
579 osm_xml = xml_for_node node
580 osm_xml = update_changeset osm_xml, 0
582 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
584 assert_require_public_data "update with changeset=0 should be forbidden, when data isn't public"
589 def test_update_with_lat_too_large_by_private_user
590 check_update_with_invalid_attr_value "lat", 91.0, :data_public => false
593 def test_update_with_lat_too_small_by_private_user
594 check_update_with_invalid_attr_value "lat", -91.0, :data_public => false
597 def test_update_with_lon_too_large_by_private_user
598 check_update_with_invalid_attr_value "lon", 181.0, :data_public => false
601 def test_update_with_lon_too_small_by_private_user
602 check_update_with_invalid_attr_value "lon", -181.0, :data_public => false
605 def test_update_by_private_user
606 with_unchanging(:node) do |node|
607 with_unchanging_request([:data_public => false]) do |headers, changeset|
608 osm_xml = xml_for_node node
609 osm_xml = update_changeset osm_xml, changeset.id
611 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
613 assert_require_public_data "should have failed with a forbidden when data isn't public"
618 def test_update_in_changeset_of_other_user
619 with_unchanging(:node) do |node|
620 other_user = create(:user)
622 with_unchanging_request([], [:user => other_user]) do |headers, changeset|
623 osm_xml = xml_for_node node
624 osm_xml = update_changeset osm_xml, changeset.id
626 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
628 assert_response :conflict, "update with other user's changeset should be rejected"
633 def test_update_in_closed_changeset
634 with_unchanging(:node) do |node|
635 with_unchanging_request([], [:closed]) do |headers, changeset|
636 osm_xml = xml_for_node node
637 osm_xml = update_changeset osm_xml, changeset.id
639 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
641 assert_response :conflict, "update with closed changeset should be rejected"
646 def test_update_in_missing_changeset
647 with_unchanging(:node) do |node|
648 with_unchanging_request do |headers|
649 osm_xml = xml_for_node node
650 osm_xml = update_changeset osm_xml, 0
652 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
654 assert_response :conflict, "update with changeset=0 should be rejected"
659 def test_update_with_lat_too_large
660 check_update_with_invalid_attr_value "lat", 91.0
663 def test_update_with_lat_too_small
664 check_update_with_invalid_attr_value "lat", -91.0
667 def test_update_with_lon_too_large
668 check_update_with_invalid_attr_value "lon", 181.0
671 def test_update_with_lon_too_small
672 check_update_with_invalid_attr_value "lon", -181.0
675 def test_update_with_version_behind
676 with_unchanging(:node, :version => 2) do |node|
677 with_unchanging_request do |headers, changeset|
678 osm_xml = xml_for_node node
679 osm_xml = xml_attr_rewrite osm_xml, "version", node.version - 1
680 osm_xml = update_changeset osm_xml, changeset.id
682 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
684 assert_response :conflict, "should have failed on old version number"
689 def test_update_with_version_ahead
690 with_unchanging(:node, :version => 2) do |node|
691 with_unchanging_request do |headers, changeset|
692 osm_xml = xml_for_node node
693 osm_xml = xml_attr_rewrite osm_xml, "version", node.version + 1
694 osm_xml = update_changeset osm_xml, changeset.id
696 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
698 assert_response :conflict, "should have failed on skipped version number"
703 def test_update_with_invalid_version
704 with_unchanging(:node) do |node|
705 with_unchanging_request do |headers, changeset|
706 osm_xml = xml_for_node node
707 osm_xml = xml_attr_rewrite osm_xml, "version", "p1r4t3s!"
708 osm_xml = update_changeset osm_xml, changeset.id
710 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
712 assert_response :conflict, "should not be able to put 'p1r4at3s!' in the version field"
717 def test_update_other_node
718 with_unchanging(:node) do |node|
719 with_unchanging(:node) do |other_node|
720 with_unchanging_request do |headers, changeset|
721 osm_xml = xml_for_node other_node
722 osm_xml = update_changeset osm_xml, changeset.id
724 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
726 assert_response :bad_request, "should not be able to update a node with a different ID from the XML"
732 def test_update_with_invalid_osm_structure
733 with_unchanging(:node) do |node|
734 with_unchanging_request do |headers|
737 put api_node_path(node), :params => osm, :headers => headers
739 assert_response :bad_request, "should not be able to update a node with non-OSM XML doc."
745 with_request do |headers, changeset|
747 osm_xml = xml_for_node node
748 osm_xml = update_changeset osm_xml, changeset.id
750 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
752 assert_response :success, "a valid update request failed"
755 assert_equal 1, changeset.num_changes
756 assert_predicate changeset, :num_type_changes_in_sync?
757 assert_equal 1, changeset.num_modified_nodes
761 def test_update_with_duplicate_tags
762 with_unchanging(:node) do |node|
763 create(:node_tag, :node => node, :k => "key_to_duplicate", :v => "value_to_duplicate")
765 with_unchanging_request do |headers, changeset|
766 tag_xml = XML::Node.new("tag")
767 tag_xml["k"] = "key_to_duplicate"
768 tag_xml["v"] = "value_to_duplicate"
770 osm_xml = xml_for_node node
771 osm_xml.find("//osm/node").first << tag_xml
772 osm_xml = update_changeset osm_xml, changeset.id
774 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
776 assert_response :bad_request, "adding duplicate tags to a node should fail with 'bad request'"
777 assert_equal "Element node/#{node.id} has duplicate tags with key key_to_duplicate", @response.body
783 # test initial rate limit
784 def test_initial_rate_limit
788 # create a changeset that puts us near the initial rate limit
789 changeset = create(:changeset, :user => user,
790 :created_at => Time.now.utc - 5.minutes,
791 :num_changes => Settings.initial_changes_per_hour - 1)
793 # create authentication header
794 auth_header = bearer_authorization_header user
796 # try creating a node
797 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
798 post api_nodes_path, :params => xml, :headers => auth_header
799 assert_response :success, "node create did not return success status"
801 # get the id of the node we created
802 nodeid = @response.body
804 # try updating the node, which should be rate limited
805 xml = "<osm><node id='#{nodeid}' version='1' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
806 put api_node_path(nodeid), :params => xml, :headers => auth_header
807 assert_response :too_many_requests, "node update did not hit rate limit"
809 # try deleting the node, which should be rate limited
810 xml = "<osm><node id='#{nodeid}' version='2' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
811 delete api_node_path(nodeid), :params => xml, :headers => auth_header
812 assert_response :too_many_requests, "node delete did not hit rate limit"
814 # try creating a node, which should be rate limited
815 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
816 post api_nodes_path, :params => xml, :headers => auth_header
817 assert_response :too_many_requests, "node create did not hit rate limit"
821 # test maximum rate limit
822 def test_maximum_rate_limit
826 # create a changeset to establish our initial edit time
827 changeset = create(:changeset, :user => user,
828 :created_at => Time.now.utc - 28.days)
830 # create changeset to put us near the maximum rate limit
831 total_changes = Settings.max_changes_per_hour - 1
832 while total_changes.positive?
833 changes = [total_changes, Changeset::MAX_ELEMENTS].min
834 changeset = create(:changeset, :user => user,
835 :created_at => Time.now.utc - 5.minutes,
836 :num_changes => changes)
837 total_changes -= changes
840 # create authentication header
841 auth_header = bearer_authorization_header user
843 # try creating a node
844 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
845 post api_nodes_path, :params => xml, :headers => auth_header
846 assert_response :success, "node create did not return success status"
848 # get the id of the node we created
849 nodeid = @response.body
851 # try updating the node, which should be rate limited
852 xml = "<osm><node id='#{nodeid}' version='1' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
853 put api_node_path(nodeid), :params => xml, :headers => auth_header
854 assert_response :too_many_requests, "node update did not hit rate limit"
856 # try deleting the node, which should be rate limited
857 xml = "<osm><node id='#{nodeid}' version='2' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
858 delete api_node_path(nodeid), :params => xml, :headers => auth_header
859 assert_response :too_many_requests, "node delete did not hit rate limit"
861 # try creating a node, which should be rate limited
862 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
863 post api_nodes_path, :params => xml, :headers => auth_header
864 assert_response :too_many_requests, "node create did not hit rate limit"
869 def check_update_with_invalid_attr_value(name, value, data_public: true)
870 with_unchanging(:node) do |node|
871 with_unchanging_request([:data_public => data_public]) do |headers, changeset|
872 osm_xml = xml_for_node node
873 osm_xml = xml_attr_rewrite osm_xml, name, value
874 osm_xml = update_changeset osm_xml, changeset.id
876 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
879 assert_response :bad_request, "node at #{name}=#{value} should be rejected"
881 assert_require_public_data "node at #{name}=#{value} should be forbidden, when data isn't public"
893 # update an attribute in the node element
894 def xml_attr_rewrite(xml, name, value)
895 xml.find("//osm/node").first[name] = value.to_s