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_create_race_condition
270 changeset = create(:changeset, :user => user)
271 auth_header = bearer_authorization_header user
272 path = api_nodes_path
273 concurrency_level = 16
275 threads = Array.new(concurrency_level) do
277 osm = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
278 post path, :params => osm, :headers => auth_header
284 assert_equal concurrency_level, changeset.num_changes
285 assert_predicate changeset, :num_type_changes_in_sync?
286 assert_equal concurrency_level, changeset.num_created_nodes
289 def test_show_not_found
291 assert_response :not_found
294 def test_show_deleted
295 get api_node_path(create(:node, :deleted))
296 assert_response :gone
300 node = create(:node, :timestamp => "2021-02-03T00:00:00Z")
302 get api_node_path(node)
304 assert_response :success
305 assert_not_nil @response.header["Last-Modified"]
306 assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
309 def test_show_lat_lon_decimal_format
310 node = create(:node, :latitude => (0.00004 * OldNode::SCALE).to_i, :longitude => (0.00008 * OldNode::SCALE).to_i)
312 get api_node_path(node)
314 assert_match(/lat="0.0000400"/, response.body)
315 assert_match(/lon="0.0000800"/, response.body)
318 def test_destroy_when_unauthorized
319 with_unchanging(:node) do |node|
320 delete api_node_path(node)
322 assert_response :unauthorized
326 def test_destroy_in_closed_changeset_by_private_user
327 with_unchanging(:node) do |node|
328 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
329 osm_xml = xml_for_node node
330 osm_xml = update_changeset osm_xml, changeset.id
332 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
334 assert_require_public_data "non-public user shouldn't be able to delete node"
339 def test_destroy_in_missing_changeset_by_private_user
340 with_unchanging(:node) do |node|
341 with_unchanging_request([:data_public => false]) do |headers|
342 osm_xml = xml_for_node node
343 osm_xml = update_changeset osm_xml, 0
345 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
347 assert_require_public_data "shouldn't be able to delete node, when user's data is private"
352 def test_destroy_by_private_user
353 with_unchanging(:node) do |node|
354 with_unchanging_request([:data_public => false]) do |headers, changeset|
355 osm_xml = xml_for_node node
356 osm_xml = update_changeset osm_xml, changeset.id
358 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
360 assert_require_public_data "shouldn't be able to delete node when user's data isn't public'"
365 def test_destroy_deleted_node_by_private_user
366 with_unchanging(:node, :deleted) do |node|
367 with_unchanging_request([:data_public => false]) do |headers, changeset|
368 osm_xml = "<osm><node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/></osm>"
370 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
372 assert_require_public_data
377 def test_destroy_missing_node_by_private_user
378 with_unchanging_request([:data_public => false]) do |headers|
379 delete api_node_path(0), :headers => headers
381 assert_require_public_data
385 def test_destroy_node_in_way_by_private_user
386 with_unchanging(:node) do |node|
387 create(:way_node, :node => node)
389 with_unchanging_request([:data_public => false]) do |headers, changeset|
390 osm_xml = xml_for_node node
391 osm_xml = update_changeset osm_xml, changeset.id
393 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
395 assert_require_public_data "shouldn't be able to delete a node used in a way (#{@response.body})"
400 def test_destroy_node_in_relation_by_private_user
401 with_unchanging(:node) do |node|
402 create(:relation_member, :member => node)
404 with_unchanging_request([:data_public => false]) do |headers, changeset|
405 osm_xml = xml_for_node node
406 osm_xml = update_changeset osm_xml, changeset.id
408 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
410 assert_require_public_data "shouldn't be able to delete a node used in a relation (#{@response.body})"
415 def test_destroy_in_closed_changeset
416 with_unchanging(:node) do |node|
417 with_unchanging_request([], [:closed]) do |headers, changeset|
418 osm_xml = xml_for_node node
419 osm_xml = update_changeset osm_xml, changeset.id
421 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
423 assert_response :conflict
428 def test_destroy_in_missing_changeset
429 with_unchanging(:node) do |node|
430 with_unchanging_request do |headers|
431 osm_xml = xml_for_node node
432 osm_xml = update_changeset osm_xml, 0
434 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
436 assert_response :conflict
441 def test_destroy_different_node
442 with_unchanging(:node) do |node|
443 with_unchanging(:node) do |other_node|
444 with_unchanging_request do |headers, changeset|
445 osm_xml = xml_for_node other_node
446 osm_xml = update_changeset osm_xml, changeset.id
448 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
450 assert_response :bad_request, "should not be able to delete a node with a different ID from the XML"
456 def test_destroy_invalid_osm_structure
457 with_unchanging(:node) do |node|
458 with_unchanging_request do |headers|
461 delete api_node_path(node), :params => osm, :headers => headers
463 assert_response :bad_request, "should not be able to delete a node without a valid XML payload"
469 with_request do |headers, changeset|
471 osm_xml = xml_for_node node
472 osm_xml = update_changeset osm_xml, changeset.id
474 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
476 assert_response :success
478 response_node_version = @response.body.to_i
479 assert_operator response_node_version, :>, node.version, "delete request should return a new version number for node"
481 assert_not_predicate node, :visible?
482 assert_equal response_node_version, node.version
485 assert_equal 1, changeset.num_changes
486 assert_predicate changeset, :num_type_changes_in_sync?
487 assert_equal 1, changeset.num_deleted_nodes
491 def test_destroy_twice
493 node = create(:node, :changeset => create(:changeset, :user => user))
494 osm_xml = xml_for_node node
496 delete api_node_path(node), :params => osm_xml.to_s, :headers => bearer_authorization_header(user)
498 assert_response :success
500 delete api_node_path(node), :params => osm_xml.to_s, :headers => bearer_authorization_header(user)
502 assert_response :gone
505 def test_destroy_deleted_node
506 with_unchanging(:node, :deleted) do |node|
507 with_unchanging_request do |headers, changeset|
508 osm = "<osm><node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/></osm>"
510 delete api_node_path(node), :params => osm, :headers => headers
512 assert_response :gone
517 def test_destroy_missing_node
518 with_unchanging_request do |headers|
519 delete api_node_path(0), :headers => headers
521 assert_response :not_found
525 def test_destroy_node_in_ways
526 with_unchanging(:node) do |node|
527 way_node = create(:way_node, :node => node)
528 way_node2 = create(:way_node, :node => node)
530 with_unchanging_request do |headers, changeset|
531 osm_xml = xml_for_node node
532 osm_xml = update_changeset osm_xml, changeset.id
534 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
536 assert_response :precondition_failed, "shouldn't be able to delete a node used in a way (#{@response.body})"
537 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way_node.way.id},#{way_node2.way.id}.", @response.body
542 def test_destroy_node_in_relations
543 with_unchanging(:node) do |node|
544 relation_member = create(:relation_member, :member => node)
545 relation_member2 = create(:relation_member, :member => node)
547 with_unchanging_request do |headers, changeset|
548 osm_xml = xml_for_node node
549 osm_xml = update_changeset osm_xml, changeset.id
551 delete api_node_path(node), :params => osm_xml.to_s, :headers => headers
553 assert_response :precondition_failed, "shouldn't be able to delete a node used in a relation (#{@response.body})"
554 assert_equal "Precondition failed: Node #{node.id} is still used by relations #{relation_member.relation.id},#{relation_member2.relation.id}.", @response.body
559 def test_update_when_unauthorized
560 with_unchanging(:node) do |node|
561 osm_xml = xml_for_node node
563 put api_node_path(node), :params => osm_xml.to_s
565 assert_response :unauthorized
569 def test_update_in_changeset_of_other_user_by_private_user
570 with_unchanging(:node) do |node|
571 other_user = create(:user)
573 with_unchanging_request([:data_public => false], [:user => other_user]) do |headers, changeset|
574 osm_xml = xml_for_node node
575 osm_xml = update_changeset osm_xml, changeset.id
577 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
579 assert_require_public_data "update with other user's changeset should be forbidden when data isn't public"
584 def test_update_in_closed_changeset_by_private_user
585 with_unchanging(:node) do |node|
586 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
587 osm_xml = xml_for_node node
588 osm_xml = update_changeset osm_xml, changeset.id
590 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
592 assert_require_public_data "update with closed changeset should be forbidden, when data isn't public"
597 def test_update_in_missing_changeset_by_private_user
598 with_unchanging(:node) do |node|
599 with_unchanging_request([:data_public => false]) do |headers|
600 osm_xml = xml_for_node node
601 osm_xml = update_changeset osm_xml, 0
603 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
605 assert_require_public_data "update with changeset=0 should be forbidden, when data isn't public"
610 def test_update_with_lat_too_large_by_private_user
611 check_update_with_invalid_attr_value "lat", 91.0, :data_public => false
614 def test_update_with_lat_too_small_by_private_user
615 check_update_with_invalid_attr_value "lat", -91.0, :data_public => false
618 def test_update_with_lon_too_large_by_private_user
619 check_update_with_invalid_attr_value "lon", 181.0, :data_public => false
622 def test_update_with_lon_too_small_by_private_user
623 check_update_with_invalid_attr_value "lon", -181.0, :data_public => false
626 def test_update_by_private_user
627 with_unchanging(:node) do |node|
628 with_unchanging_request([:data_public => false]) do |headers, changeset|
629 osm_xml = xml_for_node node
630 osm_xml = update_changeset osm_xml, changeset.id
632 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
634 assert_require_public_data "should have failed with a forbidden when data isn't public"
639 def test_update_in_changeset_of_other_user
640 with_unchanging(:node) do |node|
641 other_user = create(:user)
643 with_unchanging_request([], [:user => other_user]) do |headers, changeset|
644 osm_xml = xml_for_node node
645 osm_xml = update_changeset osm_xml, changeset.id
647 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
649 assert_response :conflict, "update with other user's changeset should be rejected"
654 def test_update_in_closed_changeset
655 with_unchanging(:node) do |node|
656 with_unchanging_request([], [:closed]) do |headers, changeset|
657 osm_xml = xml_for_node node
658 osm_xml = update_changeset osm_xml, changeset.id
660 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
662 assert_response :conflict, "update with closed changeset should be rejected"
667 def test_update_in_missing_changeset
668 with_unchanging(:node) do |node|
669 with_unchanging_request do |headers|
670 osm_xml = xml_for_node node
671 osm_xml = update_changeset osm_xml, 0
673 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
675 assert_response :conflict, "update with changeset=0 should be rejected"
680 def test_update_with_lat_too_large
681 check_update_with_invalid_attr_value "lat", 91.0
684 def test_update_with_lat_too_small
685 check_update_with_invalid_attr_value "lat", -91.0
688 def test_update_with_lon_too_large
689 check_update_with_invalid_attr_value "lon", 181.0
692 def test_update_with_lon_too_small
693 check_update_with_invalid_attr_value "lon", -181.0
696 def test_update_with_version_behind
697 with_unchanging(:node, :version => 2) do |node|
698 with_unchanging_request do |headers, changeset|
699 osm_xml = xml_for_node node
700 osm_xml = xml_attr_rewrite osm_xml, "version", node.version - 1
701 osm_xml = update_changeset osm_xml, changeset.id
703 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
705 assert_response :conflict, "should have failed on old version number"
710 def test_update_with_version_ahead
711 with_unchanging(:node, :version => 2) do |node|
712 with_unchanging_request do |headers, changeset|
713 osm_xml = xml_for_node node
714 osm_xml = xml_attr_rewrite osm_xml, "version", node.version + 1
715 osm_xml = update_changeset osm_xml, changeset.id
717 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
719 assert_response :conflict, "should have failed on skipped version number"
724 def test_update_with_invalid_version
725 with_unchanging(:node) do |node|
726 with_unchanging_request do |headers, changeset|
727 osm_xml = xml_for_node node
728 osm_xml = xml_attr_rewrite osm_xml, "version", "p1r4t3s!"
729 osm_xml = update_changeset osm_xml, changeset.id
731 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
733 assert_response :conflict, "should not be able to put 'p1r4at3s!' in the version field"
738 def test_update_other_node
739 with_unchanging(:node) do |node|
740 with_unchanging(:node) do |other_node|
741 with_unchanging_request do |headers, changeset|
742 osm_xml = xml_for_node other_node
743 osm_xml = update_changeset osm_xml, changeset.id
745 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
747 assert_response :bad_request, "should not be able to update a node with a different ID from the XML"
753 def test_update_with_invalid_osm_structure
754 with_unchanging(:node) do |node|
755 with_unchanging_request do |headers|
758 put api_node_path(node), :params => osm, :headers => headers
760 assert_response :bad_request, "should not be able to update a node with non-OSM XML doc."
766 with_request do |headers, changeset|
768 osm_xml = xml_for_node node
769 osm_xml = update_changeset osm_xml, changeset.id
771 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
773 assert_response :success, "a valid update request failed"
776 assert_equal 1, changeset.num_changes
777 assert_predicate changeset, :num_type_changes_in_sync?
778 assert_equal 1, changeset.num_modified_nodes
782 def test_update_with_duplicate_tags
783 with_unchanging(:node) do |node|
784 create(:node_tag, :node => node, :k => "key_to_duplicate", :v => "value_to_duplicate")
786 with_unchanging_request do |headers, changeset|
787 tag_xml = XML::Node.new("tag")
788 tag_xml["k"] = "key_to_duplicate"
789 tag_xml["v"] = "value_to_duplicate"
791 osm_xml = xml_for_node node
792 osm_xml.find("//osm/node").first << tag_xml
793 osm_xml = update_changeset osm_xml, changeset.id
795 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
797 assert_response :bad_request, "adding duplicate tags to a node should fail with 'bad request'"
798 assert_equal "Element node/#{node.id} has duplicate tags with key key_to_duplicate", @response.body
804 # test initial rate limit
805 def test_initial_rate_limit
809 # create a changeset that puts us near the initial rate limit
810 changeset = create(:changeset, :user => user,
811 :created_at => Time.now.utc - 5.minutes,
812 :num_changes => Settings.initial_changes_per_hour - 1)
814 # create authentication header
815 auth_header = bearer_authorization_header user
817 # try creating a node
818 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
819 post api_nodes_path, :params => xml, :headers => auth_header
820 assert_response :success, "node create did not return success status"
822 # get the id of the node we created
823 nodeid = @response.body
825 # try updating the node, which should be rate limited
826 xml = "<osm><node id='#{nodeid}' version='1' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
827 put api_node_path(nodeid), :params => xml, :headers => auth_header
828 assert_response :too_many_requests, "node update did not hit rate limit"
830 # try deleting the node, which should be rate limited
831 xml = "<osm><node id='#{nodeid}' version='2' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
832 delete api_node_path(nodeid), :params => xml, :headers => auth_header
833 assert_response :too_many_requests, "node delete did not hit rate limit"
835 # try creating a node, which should be rate limited
836 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
837 post api_nodes_path, :params => xml, :headers => auth_header
838 assert_response :too_many_requests, "node create did not hit rate limit"
842 # test maximum rate limit
843 def test_maximum_rate_limit
847 # create a changeset to establish our initial edit time
848 changeset = create(:changeset, :user => user,
849 :created_at => Time.now.utc - 28.days)
851 # create changeset to put us near the maximum rate limit
852 total_changes = Settings.max_changes_per_hour - 1
853 while total_changes.positive?
854 changes = [total_changes, Changeset::MAX_ELEMENTS].min
855 changeset = create(:changeset, :user => user,
856 :created_at => Time.now.utc - 5.minutes,
857 :num_changes => changes)
858 total_changes -= changes
861 # create authentication header
862 auth_header = bearer_authorization_header user
864 # try creating a node
865 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
866 post api_nodes_path, :params => xml, :headers => auth_header
867 assert_response :success, "node create did not return success status"
869 # get the id of the node we created
870 nodeid = @response.body
872 # try updating the node, which should be rate limited
873 xml = "<osm><node id='#{nodeid}' version='1' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
874 put api_node_path(nodeid), :params => xml, :headers => auth_header
875 assert_response :too_many_requests, "node update did not hit rate limit"
877 # try deleting the node, which should be rate limited
878 xml = "<osm><node id='#{nodeid}' version='2' lat='1' lon='1' changeset='#{changeset.id}'/></osm>"
879 delete api_node_path(nodeid), :params => xml, :headers => auth_header
880 assert_response :too_many_requests, "node delete did not hit rate limit"
882 # try creating a node, which should be rate limited
883 xml = "<osm><node lat='0' lon='0' changeset='#{changeset.id}'/></osm>"
884 post api_nodes_path, :params => xml, :headers => auth_header
885 assert_response :too_many_requests, "node create did not hit rate limit"
890 def check_update_with_invalid_attr_value(name, value, data_public: true)
891 with_unchanging(:node) do |node|
892 with_unchanging_request([:data_public => data_public]) do |headers, changeset|
893 osm_xml = xml_for_node node
894 osm_xml = xml_attr_rewrite osm_xml, name, value
895 osm_xml = update_changeset osm_xml, changeset.id
897 put api_node_path(node), :params => osm_xml.to_s, :headers => headers
900 assert_response :bad_request, "node at #{name}=#{value} should be rejected"
902 assert_require_public_data "node at #{name}=#{value} should be forbidden, when data isn't public"
914 # update an attribute in the node element
915 def xml_attr_rewrite(xml, name, value)
916 xml.find("//osm/node").first[name] = value.to_s