]> git.openstreetmap.org Git - rails.git/commitdiff
Add changeset comment search api with filtering by author and time
authorAnton Khorev <tony29@yandex.ru>
Thu, 16 Nov 2023 07:03:26 +0000 (10:03 +0300)
committerAnton Khorev <tony29@yandex.ru>
Sat, 15 Feb 2025 16:35:24 +0000 (19:35 +0300)
app/abilities/api_ability.rb
app/controllers/api/changeset_comments_controller.rb
app/views/api/changeset_comments/_changeset_comment.xml.builder [new file with mode: 0644]
app/views/api/changeset_comments/index.xml.builder [new file with mode: 0644]
app/views/api/changesets/_changeset.xml.builder
config/routes.rb
config/settings.yml
test/controllers/api/changeset_comments_controller_test.rb

index 7bbd9889ad53fbbb6d064b115f79eca7a54cad75..d183aca74bb10ee7a90420c52fe29fa2fd53fdb3 100644 (file)
@@ -11,6 +11,7 @@ class ApiAbility
       can :create, Note unless user
 
       can [:read, :download], Changeset
+      can :read, ChangesetComment
       can :read, Tracepoint
       can :read, User
       can :read, [Node, Way, Relation, OldNode, OldWay, OldRelation]
index c180571c58b10b0184e1f3dd98ab86f4fb5d8d27..808ac97ea3418257445177caeb8615cc2574ff78 100644 (file)
@@ -1,7 +1,9 @@
 module Api
   class ChangesetCommentsController < ApiController
-    before_action :check_api_writable
-    before_action :authorize
+    include QueryMethods
+
+    before_action :check_api_writable, :except => [:index]
+    before_action :authorize, :except => [:index]
 
     authorize_resource
 
@@ -9,6 +11,15 @@ module Api
 
     before_action :set_request_formats
 
+    ##
+    # show all comments or search for a subset
+    def index
+      @comments = ChangesetComment.includes(:author).where(:visible => true).order("created_at DESC")
+      @comments = query_conditions_time(@comments)
+      @comments = query_conditions_user(@comments, :author)
+      @comments = query_limit(@comments)
+    end
+
     ##
     # Add a comment to a changeset
     def create
diff --git a/app/views/api/changeset_comments/_changeset_comment.xml.builder b/app/views/api/changeset_comments/_changeset_comment.xml.builder
new file mode 100644 (file)
index 0000000..951556f
--- /dev/null
@@ -0,0 +1,12 @@
+cattrs = {
+  "id" => changeset_comment.id,
+  "date" => changeset_comment.created_at.xmlschema,
+  "visible" => changeset_comment.visible
+}
+if changeset_comment.author.data_public?
+  cattrs["uid"] = changeset_comment.author.id
+  cattrs["user"] = changeset_comment.author.display_name
+end
+xml.comment(cattrs) do |comment_xml_node|
+  comment_xml_node.text(changeset_comment.body)
+end
diff --git a/app/views/api/changeset_comments/index.xml.builder b/app/views/api/changeset_comments/index.xml.builder
new file mode 100644 (file)
index 0000000..cfa59c9
--- /dev/null
@@ -0,0 +1,7 @@
+xml.instruct! :xml, :version => "1.0"
+
+xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  @comments.includes(:author).each do |comment|
+    osm << render(comment)
+  end
+end
index 08cfbbc79bc9d66065ef6b6ca3362502fe32ecae..072f8fc5d613fc26b011b4b3b4b17ab9a2598c21 100644 (file)
@@ -27,18 +27,7 @@ xml.changeset(attrs) do |changeset_xml_node|
   if @comments
     changeset_xml_node.discussion do |discussion_xml_node|
       @comments.each do |comment|
-        cattrs = {
-          "id" => comment.id,
-          "date" => comment.created_at.xmlschema,
-          "visible" => comment.visible
-        }
-        if comment.author.data_public?
-          cattrs["uid"] = comment.author.id
-          cattrs["user"] = comment.author.display_name
-        end
-        discussion_xml_node.comment(cattrs) do |comment_xml_node|
-          comment_xml_node.text(comment.body)
-        end
+        discussion_xml_node << render(comment)
       end
     end
   end
index 3971494aa155d1851cb63164283ee124d4bd54ec..0a6ab0356f855e4fe3190fc808f619fca53693a6 100644 (file)
@@ -38,6 +38,8 @@ OpenStreetMap::Application.routes.draw do
   end
 
   namespace :api, :path => "api/0.6" do
+    resources :changeset_comments, :only => :index
+
     resources :nodes, :only => [:index, :create]
     resources :nodes, :path => "node", :id => /\d+/, :only => [:show, :update, :destroy] do
       scope :module => :nodes do
index 33b5bfb3246b4552ea7b77302997efb7f7b82e92..51f4444c4802edce9b6cc2c5869a8f0c4f8a33ed 100644 (file)
@@ -35,6 +35,10 @@ tracepoints_per_page: 5000
 default_changeset_query_limit: 100
 # Maximum limit on the number of changesets returned by the changeset query api method
 max_changeset_query_limit: 100
+# Default limit on the number of changeset comments returned by the api
+default_changeset_comment_query_limit: 100
+# Maximum limit on the number of changesets comments returned by the api
+max_changeset_comment_query_limit: 10000
 # Default limit on the number of changeset comments in feeds
 default_changeset_comments_feed_query_limit: 100
 # Maximum limit on the number of changesets comments in feeds
index e456a3ca416f4cf25113827d0dd7c6b302c7746b..2d8818986ecec3f8f75b18fd7a51bc619203e6b7 100644 (file)
@@ -5,6 +5,10 @@ module Api
     ##
     # test all routes which lead to this controller
     def test_routes
+      assert_routing(
+        { :path => "/api/0.6/changeset_comments", :method => :get },
+        { :controller => "api/changeset_comments", :action => "index" }
+      )
       assert_routing(
         { :path => "/api/0.6/changeset/1/comment", :method => :post },
         { :controller => "api/changeset_comments", :action => "create", :id => "1" }
@@ -31,6 +35,38 @@ module Api
       )
     end
 
+    def test_index
+      user1 = create(:user)
+      user2 = create(:user)
+      changeset1 = create(:changeset, :closed, :user => user2)
+      comment11 = create(:changeset_comment, :changeset => changeset1, :author => user1, :created_at => "2023-01-01", :body => "changeset 1 question")
+      comment12 = create(:changeset_comment, :changeset => changeset1, :author => user2, :created_at => "2023-02-01", :body => "changeset 1 answer")
+      changeset2 = create(:changeset, :closed, :user => user1)
+      comment21 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-03-01", :body => "changeset 2 note")
+      comment22 = create(:changeset_comment, :changeset => changeset2, :author => user1, :created_at => "2023-04-01", :body => "changeset 2 extra note")
+      comment23 = create(:changeset_comment, :changeset => changeset2, :author => user2, :created_at => "2023-05-01", :body => "changeset 2 review")
+
+      get api_changeset_comments_path
+      assert_response :success
+      assert_comments_in_order [comment23, comment22, comment21, comment12, comment11]
+
+      get api_changeset_comments_path(:limit => 3)
+      assert_response :success
+      assert_comments_in_order [comment23, comment22, comment21]
+
+      get api_changeset_comments_path(:from => "2023-03-15T00:00:00Z")
+      assert_response :success
+      assert_comments_in_order [comment23, comment22]
+
+      get api_changeset_comments_path(:from => "2023-01-15T00:00:00Z", :to => "2023-04-15T00:00:00Z")
+      assert_response :success
+      assert_comments_in_order [comment22, comment21, comment12]
+
+      get api_changeset_comments_path(:user => user1.id)
+      assert_response :success
+      assert_comments_in_order [comment22, comment21, comment11]
+    end
+
     def test_create_by_unauthorized
       assert_no_difference "ChangesetComment.count" do
         post changeset_comment_path(create(:changeset, :closed), :text => "This is a comment")
@@ -422,5 +458,20 @@ module Api
       assert_response :success
       assert comment.reload.visible
     end
+
+    private
+
+    ##
+    # check that certain comments exist in the output in the specified order
+    def assert_comments_in_order(comments)
+      assert_dom "osm > comment", comments.size do |dom_comments|
+        comments.zip(dom_comments).each do |comment, dom_comment|
+          assert_dom dom_comment, "> @id", comment.id.to_s
+          assert_dom dom_comment, "> @uid", comment.author.id.to_s
+          assert_dom dom_comment, "> @user", comment.author.display_name
+          assert_dom dom_comment, "> text", comment.body
+        end
+      end
+    end
   end
 end