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