Merge remote-tracking branch 'upstream/pull/4359'

This commit is contained in:
Tom Hughes 2025-02-16 09:04:17 +00:00
commit d90f353e5f
16 changed files with 273 additions and 137 deletions

View 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

View file

@ -2,6 +2,8 @@
module Api
class ChangesetsController < ApiController
include QueryMethods
before_action :check_api_writable, :only => [:create, :update, :upload, :subscribe, :unsubscribe]
before_action :setup_user_auth, :only => [:show]
before_action :authorize, :only => [:create, :update, :upload, :close, :subscribe, :unsubscribe]
@ -30,7 +32,7 @@ module Api
changesets = conditions_bbox(changesets, bbox)
changesets = conditions_user(changesets, params["user"], params["display_name"])
changesets = conditions_time(changesets, params["time"])
changesets = conditions_from_to(changesets, params["from"], params["to"])
changesets = query_conditions_time(changesets)
changesets = conditions_open(changesets, params["open"])
changesets = conditions_closed(changesets, params["closed"])
changesets = conditions_ids(changesets, params["changesets"])
@ -43,7 +45,7 @@ module Api
end
# limit the result
changesets = changesets.limit(result_limit)
changesets = query_limit(changesets)
# preload users, tags and comments, and render result
@changesets = changesets.preload(:user, :changeset_tags, :comments)
@ -337,33 +339,6 @@ module Api
raise OSM::APIBadUserInput, e.message.to_s
end
##
# restrict changesets to those opened during a particular time period
# works similar to from..to of notes controller, including the requirement of 'from' when specifying 'to'
def conditions_from_to(changesets, from, to)
if from
begin
from = Time.parse(from).utc
rescue ArgumentError
raise OSM::APIBadUserInput, "Date #{from} is in a wrong format"
end
begin
to = if to
Time.parse(to).utc
else
Time.now.utc
end
rescue ArgumentError
raise OSM::APIBadUserInput, "Date #{to} is in a wrong format"
end
changesets.where(:created_at => from..to)
else
changesets
end
end
##
# return changesets which are open (haven't been closed yet)
# we do this by seeing if the 'closed at' time is in the future. Also if we've
@ -403,19 +378,5 @@ module Api
changesets.where(:id => ids)
end
end
##
# Get the maximum number of results to return
def result_limit
if params[:limit]
if params[:limit].to_i.positive? && params[:limit].to_i <= Settings.max_changeset_query_limit
params[:limit].to_i
else
raise OSM::APIBadUserInput, "Changeset limit must be between 1 and #{Settings.max_changeset_query_limit}"
end
else
Settings.default_changeset_query_limit
end
end
end
end

View file

@ -1,5 +1,7 @@
module Api
class NotesController < ApiController
include QueryMethods
before_action :check_api_writable, :only => [:create, :comment, :close, :reopen, :destroy]
before_action :setup_user_auth, :only => [:create, :show]
before_action :authorize, :only => [:close, :reopen, :destroy, :comment]
@ -36,7 +38,9 @@ module Api
@max_lat = bbox.max_lat
# Find the notes we want to return
@notes = notes.bbox(bbox).order("updated_at DESC").limit(result_limit).preload(:comments)
notes = notes.bbox(bbox).order("updated_at DESC")
notes = query_limit(notes)
@notes = notes.preload(:comments)
# Render the result
respond_to do |format|
@ -234,8 +238,9 @@ module Api
# Find the comments we want to return
@comments = NoteComment.where(:note => notes)
.order(:created_at => :desc).limit(result_limit)
.preload(:author, :note => { :comments => :author })
.order(:created_at => :desc)
@comments = query_limit(@comments)
@comments = @comments.preload(:author, :note => { :comments => :author })
# Render the result
respond_to do |format|
@ -251,19 +256,8 @@ module Api
@notes = bbox_condition(@notes)
# Add any user filter
if params[:display_name] || params[:user]
if params[:display_name]
@user = User.find_by(:display_name => params[:display_name])
raise OSM::APIBadUserInput, "User #{params[:display_name]} not known" unless @user
else
@user = User.find_by(:id => params[:user])
raise OSM::APIBadUserInput, "User #{params[:user]} not known" unless @user
end
@notes = @notes.joins(:comments).where(:note_comments => { :author_id => @user })
end
user = query_conditions_user_value
@notes = @notes.joins(:comments).where(:note_comments => { :author_id => user }) if user
# Add any text filter
if params[:q]
@ -271,29 +265,12 @@ module Api
end
# Add any date filter
if params[:from]
begin
from = Time.parse(params[:from]).utc
rescue ArgumentError
raise OSM::APIBadUserInput, "Date #{params[:from]} is in a wrong format"
end
begin
to = if params[:to]
Time.parse(params[:to]).utc
else
Time.now.utc
end
rescue ArgumentError
raise OSM::APIBadUserInput, "Date #{params[:to]} is in a wrong format"
end
@notes = if params[:sort] == "updated_at"
@notes.where(:updated_at => from..to)
else
@notes.where(:created_at => from..to)
end
end
time_filter_property = if params[:sort] == "updated_at"
:updated_at
else
:created_at
end
@notes = query_conditions_time(@notes, time_filter_property)
# Choose the sort order
@notes = if params[:sort] == "created_at"
@ -311,7 +288,8 @@ module Api
end
# Find the notes we want to return
@notes = @notes.distinct.limit(result_limit).preload(:comments)
@notes = query_limit(@notes.distinct)
@notes = @notes.preload(:comments)
# Render the result
respond_to do |format|
@ -328,20 +306,6 @@ module Api
# utility functions below.
#------------------------------------------------------------
##
# Get the maximum number of results to return
def result_limit
if params[:limit]
if params[:limit].to_i.positive? && params[:limit].to_i <= Settings.max_note_query_limit
params[:limit].to_i
else
raise OSM::APIBadUserInput, "Note limit must be between 1 and #{Settings.max_note_query_limit}"
end
else
Settings.default_note_query_limit
end
end
##
# Generate a condition to choose which notes we want based
# on their status and the user's request parameters

View file

@ -1,5 +1,7 @@
module ChangesetComments
class FeedsController < ApplicationController
include QueryMethods
before_action :authorize_web
before_action :set_locale
@ -19,10 +21,13 @@ module ChangesetComments
changeset = Changeset.find(changeset_id)
# Return comments for this changeset only
@comments = changeset.comments.includes(:author, :changeset).reverse_order.limit(comments_limit)
@comments = changeset.comments.includes(:author, :changeset).reverse_order
@comments = query_limit(@comments)
else
# Return comments
@comments = ChangesetComment.includes(:author, :changeset).where(:visible => true).order("created_at DESC").limit(comments_limit).preload(:changeset)
@comments = ChangesetComment.includes(:author, :changeset).where(:visible => true).order("created_at DESC")
@comments = query_limit(@comments)
@comments = @comments.preload(:changeset)
end
# Render the result
@ -32,21 +37,5 @@ module ChangesetComments
rescue OSM::APIBadUserInput
head :bad_request
end
private
##
# Get the maximum number of comments to return
def comments_limit
if params[:limit]
if params[:limit].to_i.positive? && params[:limit].to_i <= 10000
params[:limit].to_i
else
raise OSM::APIBadUserInput, "Comments limit must be between 1 and 10000"
end
else
100
end
end
end
end

View file

@ -0,0 +1,92 @@
module QueryMethods
extend ActiveSupport::Concern
private
##
# Filter the resulting items by user
def query_conditions_user(items, filter_property)
user = query_conditions_user_value
items = items.where(filter_property => user) if user
items
end
##
# Get user value for query filtering by user
# Raises OSM::APIBadUserInput if user not found like notes api does, changesets api raises OSM::APINotFoundError instead
def query_conditions_user_value
if params[:display_name] || params[:user]
if params[:display_name]
user = User.find_by(:display_name => params[:display_name])
raise OSM::APIBadUserInput, "User #{params[:display_name]} not known" unless user
else
user = User.find_by(:id => params[:user])
raise OSM::APIBadUserInput, "User #{params[:user]} not known" unless user
end
user
end
end
##
# Restrict the resulting items to those created during a particular time period
# Using 'to' requires specifying 'from' as well for historical reasons
def query_conditions_time(items, filter_property = :created_at)
interval = query_conditions_time_value
if interval
items.where(filter_property => interval)
else
items
end
end
##
# Get query time interval from request parameters or nil
def query_conditions_time_value
if params[:from]
begin
from = Time.parse(params[:from]).utc
rescue ArgumentError
raise OSM::APIBadUserInput, "Date #{params[:from]} is in a wrong format"
end
begin
to = if params[:to]
Time.parse(params[:to]).utc
else
Time.now.utc
end
rescue ArgumentError
raise OSM::APIBadUserInput, "Date #{params[:to]} is in a wrong format"
end
from..to
end
end
##
# Limit the result according to request parameters and settings
def query_limit(items)
items.limit(query_limit_value)
end
##
# Get query limit value from request parameters and settings
def query_limit_value
name = controller_path.sub(%r{^api/}, "").tr("/", "_").singularize
max_limit = Settings["max_#{name}_query_limit"]
default_limit = Settings["default_#{name}_query_limit"]
if params[:limit]
if params[:limit].to_i.positive? && params[:limit].to_i <= max_limit
params[:limit].to_i
else
raise OSM::APIBadUserInput, "#{controller_name.classify} limit must be between 1 and #{max_limit}"
end
else
default_limit
end
end
end