]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5615'
authorTom Hughes <tom@compton.nu>
Wed, 5 Feb 2025 18:07:24 +0000 (18:07 +0000)
committerTom Hughes <tom@compton.nu>
Wed, 5 Feb 2025 18:07:24 +0000 (18:07 +0000)
app/abilities/api_ability.rb
app/assets/javascripts/user.js
app/controllers/api/nodes_controller.rb
app/controllers/api/relations_controller.rb
app/controllers/api/ways_controller.rb
app/views/notes/show.html.erb
config/routes.rb
test/controllers/api/nodes_controller_test.rb
test/controllers/api/relations_controller_test.rb
test/controllers/api/ways_controller_test.rb

index 13a453eb59305e2a8b485994abd19ea66f0bbf8c..c74a4d0996adedcebd66ec59d47d696b01ddd28c 100644 (file)
@@ -38,7 +38,7 @@ class ApiAbility
         if user.terms_agreed?
           can [:create, :update, :upload, :close, :subscribe, :unsubscribe], Changeset if scope?(token, :write_api)
           can :create, ChangesetComment if scope?(token, :write_api)
-          can [:create, :update, :delete], [Node, Way, Relation] if scope?(token, :write_api)
+          can [:create, :update, :destroy], [Node, Way, Relation] if scope?(token, :write_api)
         end
 
         if user.moderator?
index 1d167d977fb70e85481179b0671e963c9bc1c08a..9366115cecb730d4465711bca85d71f7f2ccf45c 100644 (file)
@@ -64,7 +64,7 @@ $(document).ready(function () {
       map.on("click", function (e) {
         if (!$("#updatehome").is(":checked")) return;
 
-        const [lat, lon] = OSM.cropLocation(e.latlng);
+        const [lat, lon] = OSM.cropLocation(e.latlng, map.getZoom());
 
         $("#home_lat").val(lat);
         $("#home_lon").val(lon);
index 6477271d4e890788f3c260775cd27a3c3ad53a88..b7165b2fe69039342a3594f6bd4c5126075a8101 100644 (file)
@@ -2,14 +2,14 @@
 
 module Api
   class NodesController < ApiController
-    before_action :check_api_writable, :only => [:create, :update, :delete]
-    before_action :authorize, :only => [:create, :update, :delete]
+    before_action :check_api_writable, :only => [:create, :update, :destroy]
+    before_action :authorize, :only => [:create, :update, :destroy]
 
     authorize_resource
 
-    before_action :require_public_data, :only => [:create, :update, :delete]
-    before_action :set_request_formats, :except => [:create, :update, :delete]
-    before_action :check_rate_limit, :only => [:create, :update, :delete]
+    before_action :require_public_data, :only => [:create, :update, :destroy]
+    before_action :set_request_formats, :except => [:create, :update, :destroy]
+    before_action :check_rate_limit, :only => [:create, :update, :destroy]
 
     # Dump the details on many nodes whose ids are given in the "nodes" parameter.
     def index
@@ -68,7 +68,7 @@ module Api
     # Delete a node. Doesn't actually delete it, but retains its history
     # in a wiki-like way. We therefore treat it like an update, so the delete
     # method returns the new version number.
-    def delete
+    def destroy
       node = Node.find(params[:id])
       new_node = Node.from_xml(request.raw_post)
 
index ae101f373762b0c282ed1b6218b1bbe875cfc5b7..f712534f001aebdb747234abf27d1f68a87ce982 100644 (file)
@@ -1,13 +1,13 @@
 module Api
   class RelationsController < ApiController
-    before_action :check_api_writable, :only => [:create, :update, :delete]
-    before_action :authorize, :only => [:create, :update, :delete]
+    before_action :check_api_writable, :only => [:create, :update, :destroy]
+    before_action :authorize, :only => [:create, :update, :destroy]
 
     authorize_resource
 
-    before_action :require_public_data, :only => [:create, :update, :delete]
-    before_action :set_request_formats, :except => [:create, :update, :delete]
-    before_action :check_rate_limit, :only => [:create, :update, :delete]
+    before_action :require_public_data, :only => [:create, :update, :destroy]
+    before_action :set_request_formats, :except => [:create, :update, :destroy]
+    before_action :check_rate_limit, :only => [:create, :update, :destroy]
 
     def index
       raise OSM::APIBadUserInput, "The parameter relations is required, and must be of the form relations=id[,id[,id...]]" unless params["relations"]
@@ -57,7 +57,7 @@ module Api
       render :plain => relation.version.to_s
     end
 
-    def delete
+    def destroy
       relation = Relation.find(params[:id])
       new_relation = Relation.from_xml(request.raw_post)
       if new_relation && new_relation.id == relation.id
index 632fdb9a629637d1112831012e803e3f145605ba..285ed46046041af296b1dc223e9320293fcd14d5 100644 (file)
@@ -1,13 +1,13 @@
 module Api
   class WaysController < ApiController
-    before_action :check_api_writable, :only => [:create, :update, :delete]
-    before_action :authorize, :only => [:create, :update, :delete]
+    before_action :check_api_writable, :only => [:create, :update, :destroy]
+    before_action :authorize, :only => [:create, :update, :destroy]
 
     authorize_resource
 
-    before_action :require_public_data, :only => [:create, :update, :delete]
-    before_action :set_request_formats, :except => [:create, :update, :delete]
-    before_action :check_rate_limit, :only => [:create, :update, :delete]
+    before_action :require_public_data, :only => [:create, :update, :destroy]
+    before_action :set_request_formats, :except => [:create, :update, :destroy]
+    before_action :check_rate_limit, :only => [:create, :update, :destroy]
 
     def index
       raise OSM::APIBadUserInput, "The parameter ways is required, and must be of the form ways=id[,id[,id...]]" unless params["ways"]
@@ -60,7 +60,7 @@ module Api
     end
 
     # This is the API call to delete a way
-    def delete
+    def destroy
       way = Way.find(params[:id])
       new_way = Way.from_xml(request.raw_post)
 
index 3d9b4a9bace5aafa7d1a378abc6da3ed1a0bf54e..4f20cdd441a227329bc4fca28bcf572c3ad5d016 100644 (file)
@@ -5,7 +5,7 @@
 <div>
   <h4><%= t(".description") %></h4>
   <div class="overflow-hidden ms-2">
-    <%= h(note_description(@note.author, @note.description).to_html) %>
+    <%= note_description(@note.author, @note.description).to_html %>
   </div>
 
   <div class="details" data-coordinates="<%= @note.lat %>,<%= @note.lon %>" data-status="<%= @note.status %>">
index 2ba9bdb932bff078826ee89e335746f8daf3589a..b562ca9f4a0c60b6d1984b5db21acf80aec0153a 100644 (file)
@@ -35,37 +35,31 @@ OpenStreetMap::Application.routes.draw do
     get "node/:id/history" => "old_nodes#history", :as => :api_node_history, :id => /\d+/
     post "node/:id/:version/redact" => "old_nodes#redact", :as => :node_version_redact, :version => /\d+/, :id => /\d+/
     get "node/:id/:version" => "old_nodes#show", :as => :api_old_node, :id => /\d+/, :version => /\d+/
-    get "node/:id" => "nodes#show", :as => :api_node, :id => /\d+/
-    put "node/:id" => "nodes#update", :id => /\d+/
-    delete "node/:id" => "nodes#delete", :id => /\d+/
 
     get "way/:id/history" => "old_ways#history", :as => :api_way_history, :id => /\d+/
     get "way/:id/full" => "ways#full", :as => :way_full, :id => /\d+/
     get "way/:id/relations" => "relations#relations_for_way", :as => :way_relations, :id => /\d+/
     post "way/:id/:version/redact" => "old_ways#redact", :as => :way_version_redact, :version => /\d+/, :id => /\d+/
     get "way/:id/:version" => "old_ways#show", :as => :api_old_way, :id => /\d+/, :version => /\d+/
-    get "way/:id" => "ways#show", :as => :api_way, :id => /\d+/
-    put "way/:id" => "ways#update", :id => /\d+/
-    delete "way/:id" => "ways#delete", :id => /\d+/
 
     get "relation/:id/relations" => "relations#relations_for_relation", :as => :relation_relations, :id => /\d+/
     get "relation/:id/history" => "old_relations#history", :as => :api_relation_history, :id => /\d+/
     get "relation/:id/full" => "relations#full", :as => :relation_full, :id => /\d+/
     post "relation/:id/:version/redact" => "old_relations#redact", :as => :relation_version_redact, :version => /\d+/, :id => /\d+/
     get "relation/:id/:version" => "old_relations#show", :as => :api_old_relation, :id => /\d+/, :version => /\d+/
-    get "relation/:id" => "relations#show", :as => :api_relation, :id => /\d+/
-    put "relation/:id" => "relations#update", :id => /\d+/
-    delete "relation/:id" => "relations#delete", :id => /\d+/
   end
 
   namespace :api, :path => "api/0.6" do
     resources :nodes, :only => [:index, :create]
+    resources :nodes, :path => "node", :id => /\d+/, :only => [:show, :update, :destroy]
     put "node/create" => "nodes#create", :as => nil
 
     resources :ways, :only => [:index, :create]
+    resources :ways, :path => "way", :id => /\d+/, :only => [:show, :update, :destroy]
     put "way/create" => "ways#create", :as => nil
 
     resources :relations, :only => [:index, :create]
+    resources :relations, :path => "relation", :id => /\d+/, :only => [:show, :update, :destroy]
     put "relation/create" => "relations#create", :as => nil
 
     resource :map, :only => :show
index 04120dace129af8b096b11f2a273b9384f080dcd..523498216884c42925739dddc5fda1d1e86faf14 100644 (file)
@@ -31,7 +31,7 @@ module Api
       )
       assert_routing(
         { :path => "/api/0.6/node/1", :method => :delete },
-        { :controller => "api/nodes", :action => "delete", :id => "1" }
+        { :controller => "api/nodes", :action => "destroy", :id => "1" }
       )
 
       assert_recognizes(
@@ -193,18 +193,24 @@ module Api
       assert_match(/ v: is too long \(maximum is 255 characters\) /, @response.body)
     end
 
-    def test_show
-      # check that a visible node is returned properly
-      get api_node_path(create(:node))
-      assert_response :success
+    def test_show_not_found
+      get api_node_path(0)
+      assert_response :not_found
+    end
 
-      # check that an deleted node is not returned
+    def test_show_deleted
       get api_node_path(create(:node, :deleted))
       assert_response :gone
+    end
 
-      # check chat a non-existent node is not returned
-      get api_node_path(0)
-      assert_response :not_found
+    def test_show
+      node = create(:node, :timestamp => "2021-02-03T00:00:00Z")
+
+      get api_node_path(node)
+
+      assert_response :success
+      assert_not_nil @response.header["Last-Modified"]
+      assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
     end
 
     # Ensure the lat/lon is formatted as a decimal e.g. not 4.0e-05
@@ -218,7 +224,7 @@ module Api
 
     # this tests deletion restrictions - basic deletion is tested in the unit
     # tests for node!
-    def test_delete
+    def test_destroy
       private_user = create(:user, :data_public => false)
       private_user_changeset = create(:changeset, :user => private_user)
       private_user_closed_changeset = create(:changeset, :closed, :user => private_user)
index 5147d851f2a5bcddbc1108abedb45ee6b00eaf56..34953f7b7ac62841a1e27002ab383a9130393574 100644 (file)
@@ -17,14 +17,6 @@ module Api
         { :path => "/api/0.6/relations", :method => :post },
         { :controller => "api/relations", :action => "create" }
       )
-      assert_routing(
-        { :path => "/api/0.6/relation/1/full", :method => :get },
-        { :controller => "api/relations", :action => "full", :id => "1" }
-      )
-      assert_routing(
-        { :path => "/api/0.6/relation/1/full.json", :method => :get },
-        { :controller => "api/relations", :action => "full", :id => "1", :format => "json" }
-      )
       assert_routing(
         { :path => "/api/0.6/relation/1", :method => :get },
         { :controller => "api/relations", :action => "show", :id => "1" }
@@ -33,13 +25,21 @@ module Api
         { :path => "/api/0.6/relation/1.json", :method => :get },
         { :controller => "api/relations", :action => "show", :id => "1", :format => "json" }
       )
+      assert_routing(
+        { :path => "/api/0.6/relation/1/full", :method => :get },
+        { :controller => "api/relations", :action => "full", :id => "1" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/relation/1/full.json", :method => :get },
+        { :controller => "api/relations", :action => "full", :id => "1", :format => "json" }
+      )
       assert_routing(
         { :path => "/api/0.6/relation/1", :method => :put },
         { :controller => "api/relations", :action => "update", :id => "1" }
       )
       assert_routing(
         { :path => "/api/0.6/relation/1", :method => :delete },
-        { :controller => "api/relations", :action => "delete", :id => "1" }
+        { :controller => "api/relations", :action => "destroy", :id => "1" }
       )
 
       assert_routing(
@@ -122,20 +122,88 @@ module Api
     # Test showing relations.
     # -------------------------------------
 
-    def test_show
-      # check that a visible relation is returned properly
-      get api_relation_path(create(:relation))
-      assert_response :success
+    def test_show_not_found
+      get api_relation_path(0)
+      assert_response :not_found
+    end
 
-      # check that an invisible relation is not returned
+    def test_show_deleted
       get api_relation_path(create(:relation, :deleted))
       assert_response :gone
+    end
 
-      # check chat a non-existent relation is not returned
-      get api_relation_path(0)
+    def test_show
+      relation = create(:relation, :timestamp => "2021-02-03T00:00:00Z")
+      node = create(:node, :timestamp => "2021-04-05T00:00:00Z")
+      create(:relation_member, :relation => relation, :member => node)
+
+      get api_relation_path(relation)
+
+      assert_response :success
+      assert_not_nil @response.header["Last-Modified"]
+      assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
+      assert_dom "node", :count => 0
+      assert_dom "relation", :count => 1 do
+        assert_dom "> @id", :text => relation.id.to_s
+      end
+    end
+
+    def test_full_not_found
+      get relation_full_path(999999)
       assert_response :not_found
     end
 
+    def test_full_deleted
+      get relation_full_path(create(:relation, :deleted))
+      assert_response :gone
+    end
+
+    def test_full_empty
+      relation = create(:relation)
+
+      get relation_full_path(relation)
+
+      assert_response :success
+      assert_dom "relation", :count => 1 do
+        assert_dom "> @id", :text => relation.id.to_s
+      end
+    end
+
+    def test_full_with_node_member
+      relation = create(:relation)
+      node = create(:node)
+      create(:relation_member, :relation => relation, :member => node)
+
+      get relation_full_path(relation)
+
+      assert_response :success
+      assert_dom "node", :count => 1 do
+        assert_dom "> @id", :text => node.id.to_s
+      end
+      assert_dom "relation", :count => 1 do
+        assert_dom "> @id", :text => relation.id.to_s
+      end
+    end
+
+    def test_full_with_way_member
+      relation = create(:relation)
+      way = create(:way_with_nodes)
+      create(:relation_member, :relation => relation, :member => way)
+
+      get relation_full_path(relation)
+
+      assert_response :success
+      assert_dom "node", :count => 1 do
+        assert_dom "> @id", :text => way.nodes[0].id.to_s
+      end
+      assert_dom "way", :count => 1 do
+        assert_dom "> @id", :text => way.id.to_s
+      end
+      assert_dom "relation", :count => 1 do
+        assert_dom "> @id", :text => relation.id.to_s
+      end
+    end
+
     ##
     # check that all relations containing a particular node, and no extra
     # relations, are returned from the relations_for_node call.
@@ -201,19 +269,6 @@ module Api
                                   [relation_with_relation, second_relation])
     end
 
-    def test_full
-      # check the "full" mode
-      get relation_full_path(:id => 999999)
-      assert_response :not_found
-
-      get relation_full_path(:id => create(:relation, :deleted).id)
-      assert_response :gone
-
-      get relation_full_path(:id => create(:relation).id)
-      assert_response :success
-      # FIXME: check whether this contains the stuff we want!
-    end
-
     # -------------------------------------
     # Test simple relation creation.
     # -------------------------------------
@@ -509,7 +564,7 @@ module Api
     # Test deleting relations.
     # -------------------------------------
 
-    def test_delete
+    def test_destroy
       private_user = create(:user, :data_public => false)
       private_user_closed_changeset = create(:changeset, :closed, :user => private_user)
       user = create(:user)
index e81b49b81da45f0762b8730cf69576aa24fb3a01..2ff5e6f29f786a94b3c7080535fcc371ce9150d3 100644 (file)
@@ -17,14 +17,6 @@ module Api
         { :path => "/api/0.6/ways", :method => :post },
         { :controller => "api/ways", :action => "create" }
       )
-      assert_routing(
-        { :path => "/api/0.6/way/1/full", :method => :get },
-        { :controller => "api/ways", :action => "full", :id => "1" }
-      )
-      assert_routing(
-        { :path => "/api/0.6/way/1/full.json", :method => :get },
-        { :controller => "api/ways", :action => "full", :id => "1", :format => "json" }
-      )
       assert_routing(
         { :path => "/api/0.6/way/1", :method => :get },
         { :controller => "api/ways", :action => "show", :id => "1" }
@@ -33,13 +25,21 @@ module Api
         { :path => "/api/0.6/way/1.json", :method => :get },
         { :controller => "api/ways", :action => "show", :id => "1", :format => "json" }
       )
+      assert_routing(
+        { :path => "/api/0.6/way/1/full", :method => :get },
+        { :controller => "api/ways", :action => "full", :id => "1" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/way/1/full.json", :method => :get },
+        { :controller => "api/ways", :action => "full", :id => "1", :format => "json" }
+      )
       assert_routing(
         { :path => "/api/0.6/way/1", :method => :put },
         { :controller => "api/ways", :action => "update", :id => "1" }
       )
       assert_routing(
         { :path => "/api/0.6/way/1", :method => :delete },
-        { :controller => "api/ways", :action => "delete", :id => "1" }
+        { :controller => "api/ways", :action => "destroy", :id => "1" }
       )
 
       assert_recognizes(
@@ -96,18 +96,42 @@ module Api
     # Test showing ways.
     # -------------------------------------
 
-    def test_show
-      # check that a visible way is returned properly
-      get api_way_path(create(:way))
-      assert_response :success
+    def test_show_not_found
+      get api_way_path(0)
+      assert_response :not_found
+    end
 
-      # check that an invisible way is not returned
+    def test_show_deleted
       get api_way_path(create(:way, :deleted))
       assert_response :gone
+    end
 
-      # check chat a non-existent way is not returned
-      get api_way_path(0)
-      assert_response :not_found
+    def test_show
+      way = create(:way, :timestamp => "2021-02-03T00:00:00Z")
+      node = create(:node, :timestamp => "2021-04-05T00:00:00Z")
+      create(:way_node, :way => way, :node => node)
+
+      get api_way_path(way)
+
+      assert_response :success
+      assert_not_nil @response.header["Last-Modified"]
+      assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
+    end
+
+    def test_show_json
+      way = create(:way_with_nodes, :nodes_count => 3)
+
+      get api_way_path(way, :format => "json")
+
+      assert_response :success
+
+      js = ActiveSupport::JSON.decode(@response.body)
+      assert_not_nil js
+      assert_equal 1, js["elements"].count
+      js_ways = js["elements"].filter { |e| e["type"] == "way" }
+      assert_equal 1, js_ways.count
+      assert_equal way.id, js_ways[0]["id"]
+      assert_equal 1, js_ways[0]["version"]
     end
 
     ##
@@ -284,7 +308,7 @@ module Api
     # Test deleting ways.
     # -------------------------------------
 
-    def test_delete
+    def test_destroy
       private_user = create(:user, :data_public => false)
       private_open_changeset = create(:changeset, :user => private_user)
       private_closed_changeset = create(:changeset, :closed, :user => private_user)