mirror of
https://github.com/discourse/discourse.git
synced 2025-06-06 13:06:56 +08:00
FIX: Validate page/limit params for directory, user-badges and groups (#22877)
We'll now return a 400 error instead of 500. 400 is a better description of the issue, and also avoids creating unnecessary noise in the logs.
This commit is contained in:
@ -1086,18 +1086,29 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def fetch_limit_from_params(params: self.params, default:, max:)
|
def fetch_limit_from_params(params: self.params, default:, max:)
|
||||||
raise "default limit cannot be greater than max limit" if default.present? && default > max
|
fetch_int_from_params(:limit, params: params, default: default, max: max)
|
||||||
|
end
|
||||||
|
|
||||||
if params.has_key?(:limit)
|
def fetch_int_from_params(key, params: self.params, default:, min: 0, max: nil)
|
||||||
limit =
|
key = key.to_sym
|
||||||
|
|
||||||
|
if default.present? && ((max.present? && default > max) || (min.present? && default < min))
|
||||||
|
raise "default #{key.inspect} is not between #{min.inspect} and #{max.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if params.has_key?(key)
|
||||||
|
value =
|
||||||
begin
|
begin
|
||||||
Integer(params[:limit])
|
Integer(params[key])
|
||||||
rescue ArgumentError
|
rescue ArgumentError
|
||||||
raise Discourse::InvalidParameters.new(:limit)
|
raise Discourse::InvalidParameters.new(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
raise Discourse::InvalidParameters.new(:limit) if limit < 0 || limit > max
|
if (min.present? && value < min) || (max.present? && value > max)
|
||||||
limit
|
raise Discourse::InvalidParameters.new(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
value
|
||||||
else
|
else
|
||||||
default
|
default
|
||||||
end
|
end
|
||||||
|
@ -58,7 +58,7 @@ class DirectoryItemsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
result = result.includes(:user_stat) if period_type == DirectoryItem.period_types[:all]
|
result = result.includes(:user_stat) if period_type == DirectoryItem.period_types[:all]
|
||||||
page = params[:page].to_i
|
page = fetch_int_from_params(:page, default: 0)
|
||||||
|
|
||||||
user_ids = nil
|
user_ids = nil
|
||||||
if params[:name].present?
|
if params[:name].present?
|
||||||
|
@ -88,7 +88,7 @@ class GroupsController < ApplicationController
|
|||||||
# count the total before doing pagination
|
# count the total before doing pagination
|
||||||
total = groups.count
|
total = groups.count
|
||||||
|
|
||||||
page = params[:page].to_i
|
page = fetch_int_from_params(:page, default: 0)
|
||||||
page_size = MobileDetection.mobile_device?(request.user_agent) ? 15 : 36
|
page_size = MobileDetection.mobile_device?(request.user_agent) ? 15 : 36
|
||||||
groups = groups.offset(page * page_size).limit(page_size)
|
groups = groups.offset(page * page_size).limit(page_size)
|
||||||
|
|
||||||
|
@ -27,9 +27,8 @@ class UserBadgesController < ApplicationController
|
|||||||
grant_count = badge.user_badges.where(user_id: user_id).count
|
grant_count = badge.user_badges.where(user_id: user_id).count
|
||||||
end
|
end
|
||||||
|
|
||||||
if offset = params[:offset]
|
offset = fetch_int_from_params(:offset, default: 0)
|
||||||
user_badges = user_badges.offset(offset.to_i)
|
user_badges = user_badges.offset(offset) if offset > 0
|
||||||
end
|
|
||||||
|
|
||||||
user_badges_topic_ids = user_badges.map { |user_badge| user_badge.post&.topic_id }.compact
|
user_badges_topic_ids = user_badges.map { |user_badge| user_badge.post&.topic_id }.compact
|
||||||
|
|
||||||
|
@ -33,6 +33,16 @@ RSpec.describe DirectoryItemsController do
|
|||||||
include_examples "invalid limit params", "/directory_items.json", described_class::PAGE_SIZE
|
include_examples "invalid limit params", "/directory_items.json", described_class::PAGE_SIZE
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with page parameter" do
|
||||||
|
it "only accepts valid page numbers" do
|
||||||
|
get "/directory_items.json", params: { period: "all", page: -1 }
|
||||||
|
expect(response.status).to eq(400)
|
||||||
|
|
||||||
|
get "/directory_items.json", params: { period: "all", page: 0 }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "with exclude_groups parameter" do
|
context "with exclude_groups parameter" do
|
||||||
before { DirectoryItem.refresh! }
|
before { DirectoryItem.refresh! }
|
||||||
|
|
||||||
|
@ -38,6 +38,17 @@ RSpec.describe GroupsController do
|
|||||||
expect(body["load_more_groups"]).to eq("/groups?page=2")
|
expect(body["load_more_groups"]).to eq("/groups?page=2")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "only accepts valid page numbers" do
|
||||||
|
get "/groups.json", params: { page: -1 }
|
||||||
|
expect(response.status).to eq(400)
|
||||||
|
|
||||||
|
get "/groups.json", params: { page: 0 }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
|
||||||
|
get "/groups.json", params: { page: 1 }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
|
|
||||||
context "when group directory is disabled" do
|
context "when group directory is disabled" do
|
||||||
before { SiteSetting.enable_group_directory = false }
|
before { SiteSetting.enable_group_directory = false }
|
||||||
|
|
||||||
|
@ -31,6 +31,14 @@ RSpec.describe UserBadgesController do
|
|||||||
get "/user_badges.json", params: { badge_id: badge.id }
|
get "/user_badges.json", params: { badge_id: badge.id }
|
||||||
expect(response.status).to eq(404)
|
expect(response.status).to eq(404)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "only accepts valid offset params" do
|
||||||
|
get "/user_badges.json", params: { badge_id: badge.id, offset: -1 }
|
||||||
|
expect(response.status).to eq(400)
|
||||||
|
|
||||||
|
get "/user_badges.json", params: { badge_id: badge.id, offset: 100 }
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#index" do
|
describe "#index" do
|
||||||
|
Reference in New Issue
Block a user