mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 09:42:07 +08:00
SECURITY: Prevent unauthorized access to grouped poll results
This adds access controls for the `/polls/grouped_poll_results` endpoint, such that only users with appropriate permissions can read the grouped results of a given poll.
This commit is contained in:
parent
4cb7472376
commit
ee084b754e
|
@ -198,11 +198,19 @@ class DiscoursePoll::Poll
|
|||
|
||||
def self.grouped_poll_results(user, post_id, poll_name, user_field_name)
|
||||
raise Discourse::InvalidParameters.new(:post_id) if !Post.where(id: post_id).exists?
|
||||
|
||||
poll =
|
||||
Poll.includes(:poll_options).includes(:poll_votes).find_by(post_id: post_id, name: poll_name)
|
||||
Poll.includes(:poll_options, :poll_votes, post: :topic).find_by(
|
||||
post_id: post_id,
|
||||
name: poll_name,
|
||||
)
|
||||
raise Discourse::InvalidParameters.new(:poll_name) unless poll
|
||||
|
||||
# user must be allowed to post in topic
|
||||
guardian = Guardian.new(user)
|
||||
if !guardian.can_create_post?(poll.post.topic)
|
||||
raise DiscoursePoll::Error.new I18n.t("poll.user_cant_post_in_topic")
|
||||
end
|
||||
|
||||
unless SiteSetting.poll_groupable_user_fields.split("|").include?(user_field_name)
|
||||
raise Discourse::InvalidParameters.new(:user_field_name)
|
||||
end
|
||||
|
|
|
@ -147,6 +147,7 @@ RSpec.describe "DiscoursePoll endpoints" do
|
|||
let(:option_b) { "e89dec30bbd9bf50fabf6a05b4324edf" }
|
||||
|
||||
before do
|
||||
sign_in(user1)
|
||||
user_votes = { user_0: option_a, user_1: option_a, user_2: option_b }
|
||||
|
||||
[user1, user2, user3].each_with_index do |user, index|
|
||||
|
@ -219,5 +220,121 @@ RSpec.describe "DiscoursePoll endpoints" do
|
|||
expect(response.status).to eq(400)
|
||||
expect(response.body).to include("user_field_name")
|
||||
end
|
||||
|
||||
context "when topic is in a private category" do
|
||||
fab!(:admin) { Fabricate(:admin) }
|
||||
fab!(:group) { Fabricate(:group) }
|
||||
fab!(:private_category) { Fabricate(:private_category, group: group) }
|
||||
fab!(:private_topic) { Fabricate(:topic, category: private_category) }
|
||||
fab!(:private_post) { Fabricate(:post, topic: private_topic, raw: <<~SQL) }
|
||||
[poll type=multiple public=true min=1 max=2]
|
||||
- A
|
||||
- B
|
||||
[/poll]
|
||||
SQL
|
||||
let(:groupable_user_field) { "anything" }
|
||||
let(:expected_results) do
|
||||
{
|
||||
grouped_results: [
|
||||
{
|
||||
group: "Value0",
|
||||
options: [
|
||||
{ digest: option_a, html: "A", votes: 1 },
|
||||
{ digest: option_b, html: "B", votes: 0 },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "Value1",
|
||||
options: [
|
||||
{ digest: option_a, html: "A", votes: 2 },
|
||||
{ digest: option_b, html: "B", votes: 1 },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "Value2",
|
||||
options: [
|
||||
{ digest: option_a, html: "A", votes: 0 },
|
||||
{ digest: option_b, html: "B", votes: 1 },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
user_votes = { user_0: option_a, user_1: option_a, user_2: option_b }
|
||||
SiteSetting.poll_groupable_user_fields = groupable_user_field
|
||||
|
||||
[user1, user2, user3].each_with_index do |user, index|
|
||||
group.add(user)
|
||||
DiscoursePoll::Poll.vote(
|
||||
user,
|
||||
private_post.id,
|
||||
DiscoursePoll::DEFAULT_POLL_NAME,
|
||||
[user_votes["user_#{index}".to_sym]],
|
||||
)
|
||||
UserCustomField.create(
|
||||
user_id: user.id,
|
||||
name: groupable_user_field,
|
||||
value: "value#{index}",
|
||||
)
|
||||
end
|
||||
|
||||
# Add another user to one of the fields to prove it groups users properly
|
||||
group.add(user4)
|
||||
DiscoursePoll::Poll.vote(
|
||||
user4,
|
||||
private_post.id,
|
||||
DiscoursePoll::DEFAULT_POLL_NAME,
|
||||
[option_a, option_b],
|
||||
)
|
||||
UserCustomField.create(user_id: user4.id, name: groupable_user_field, value: "value1")
|
||||
end
|
||||
|
||||
it "returns grouped poll results for admin based on user field" do
|
||||
sign_in(admin)
|
||||
|
||||
get "/polls/grouped_poll_results.json",
|
||||
params: {
|
||||
post_id: private_post.id,
|
||||
poll_name: DiscoursePoll::DEFAULT_POLL_NAME,
|
||||
user_field_name: groupable_user_field,
|
||||
}
|
||||
|
||||
expect(response).to have_http_status :success
|
||||
expect(response.parsed_body.deep_symbolize_keys).to eq(expected_results)
|
||||
end
|
||||
|
||||
it "returns grouped poll results for user within private group based on user field" do
|
||||
user = Fabricate(:user)
|
||||
group.add(user)
|
||||
sign_in(user)
|
||||
|
||||
get "/polls/grouped_poll_results.json",
|
||||
params: {
|
||||
post_id: private_post.id,
|
||||
poll_name: DiscoursePoll::DEFAULT_POLL_NAME,
|
||||
user_field_name: groupable_user_field,
|
||||
}
|
||||
|
||||
expect(response).to have_http_status :success
|
||||
expect(response.parsed_body.deep_symbolize_keys).to eq(expected_results)
|
||||
end
|
||||
|
||||
it "returns an error when user does not have access to topic category" do
|
||||
user = Fabricate(:user)
|
||||
sign_in(user)
|
||||
|
||||
get "/polls/grouped_poll_results.json",
|
||||
params: {
|
||||
post_id: private_post.id,
|
||||
poll_name: DiscoursePoll::DEFAULT_POLL_NAME,
|
||||
user_field_name: groupable_user_field,
|
||||
}
|
||||
|
||||
expect(response).to have_http_status :unprocessable_entity
|
||||
expect(response.parsed_body["errors"][0]).to eq(I18n.t("poll.user_cant_post_in_topic"))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user