discourse/spec/requests/post_action_users_controller_spec.rb
Alan Guo Xiang Tan bfc3132bb2
SECURITY: Impose a upper bound on limit params in various controllers
What is the problem here?

In multiple controllers, we are accepting a `limit` params but do not
impose any upper bound on the values being accepted. Without an upper
bound, we may be allowing arbituary users from generating DB queries
which may end up exhausing the resources on the server.

What is the fix here?

A new `fetch_limit_from_params` helper method is introduced in
`ApplicationController` that can be used by controller actions to safely
get the limit from the params as a default limit and maximum limit has
to be set. When an invalid limit params is encountered, the server will
respond with the 400 response code.
2023-07-28 12:53:46 +01:00

142 lines
3.9 KiB
Ruby

# frozen_string_literal: true
RSpec.describe PostActionUsersController do
fab!(:user) { Fabricate(:user) }
let(:post) { Fabricate(:post, user: sign_in(user)) }
describe "index" do
describe "when limit params is invalid" do
include_examples "invalid limit params",
"/post_action_users.json",
described_class::INDEX_LIMIT
end
end
context "with render" do
it "always allows you to see your own actions" do
notify_mod = PostActionType.types[:notify_moderators]
PostActionCreator.new(
post.user,
post,
notify_mod,
message: "well something is wrong here!",
).perform
PostActionCreator.new(
Fabricate(:user),
post,
notify_mod,
message: "well something is not wrong here!",
).perform
get "/post_action_users.json", params: { id: post.id, post_action_type_id: notify_mod }
expect(response.status).to eq(200)
users = response.parsed_body["post_action_users"]
expect(users.length).to eq(1)
expect(users[0]["id"]).to eq(post.user.id)
end
end
it "raises an error without an id" do
get "/post_action_users.json", params: { post_action_type_id: PostActionType.types[:like] }
expect(response.status).to eq(400)
end
it "raises an error without a post action type" do
get "/post_action_users.json", params: { id: post.id }
expect(response.status).to eq(400)
end
it "fails when the user doesn't have permission to see the post" do
post.trash!
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response).to be_forbidden
end
it "raises an error when anon tries to look at an invalid action" do
get "/post_action_users.json",
params: {
id: Fabricate(:post).id,
post_action_type_id: PostActionType.types[:notify_moderators],
}
expect(response).to be_forbidden
end
it "succeeds" do
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
end
it "will return an unknown attribute for muted users" do
ignored_user = Fabricate(:user)
PostActionCreator.like(ignored_user, post)
regular_user = Fabricate(:user)
PostActionCreator.like(regular_user, post)
Fabricate(:ignored_user, user: user, ignored_user: ignored_user)
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
}
expect(response.status).to eq(200)
json_users = response.parsed_body["post_action_users"]
expect(json_users.find { |u| u["id"] == regular_user.id }["unknown"]).to be_blank
expect(json_users.find { |u| u["id"] == ignored_user.id }["unknown"]).to eq(true)
end
it "paginates post actions" do
user_ids = []
5.times do
user = Fabricate(:user)
user_ids << user["id"]
PostActionCreator.like(user, post)
end
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: PostActionType.types[:like],
page: 1,
limit: 2,
}
users = response.parsed_body["post_action_users"]
total = response.parsed_body["total_rows_post_action_users"]
expect(users.length).to eq(2)
expect(users.map { |u| u["id"] }).to eq(user_ids[2..3])
expect(total).to eq(5)
end
it "returns no users when the action type id is invalid" do
get "/post_action_users.json",
params: {
id: post.id,
post_action_type_id: "invalid_action_type",
}
expect(response.status).to eq(200)
users = response.parsed_body["post_action_users"]
total = response.parsed_body["total_rows_post_action_users"]
expect(users.length).to eq(0)
expect(total).to be_nil
end
end