From 21822cf0b766c7b07bc956ab59e6bc01bfda7699 Mon Sep 17 00:00:00 2001 From: Alan Guo Xiang Tan Date: Wed, 5 Jan 2022 09:50:49 +0800 Subject: [PATCH] FIX: Error when voting on a multiple poll without the min/max attrs. --- plugins/poll/lib/poll.rb | 9 ++++-- plugins/poll/spec/lib/poll_spec.rb | 48 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/plugins/poll/lib/poll.rb b/plugins/poll/lib/poll.rb index fceefc090b4..0e9c28ef3fe 100644 --- a/plugins/poll/lib/poll.rb +++ b/plugins/poll/lib/poll.rb @@ -38,7 +38,10 @@ class DiscoursePoll::Poll # Ensure consistency here as we do not have a unique index to limit the # number of votes per the poll's configuration. - DB.query(<<~SQL, poll_id: poll_id, user_id: user.id, offset: serialized_poll[:type] == "multiple" ? serialized_poll[:max] : 1) + is_multiple = serialized_poll[:type] == "multiple" + offset = is_multiple ? (serialized_poll[:max] || serialized_poll[:options].length) : 1 + + DB.query(<<~SQL, poll_id: poll_id, user_id: user.id, offset: offset) DELETE FROM poll_votes USING ( SELECT @@ -315,12 +318,12 @@ class DiscoursePoll::Poll num_of_options = options.length if poll.multiple? - if num_of_options < poll.min + if poll.min && (num_of_options < poll.min) raise DiscoursePoll::Error.new(I18n.t( "poll.min_vote_per_user", count: poll.min )) - elsif num_of_options > poll.max + elsif poll.max && (num_of_options > poll.max) raise DiscoursePoll::Error.new(I18n.t( "poll.max_vote_per_user", count: poll.max diff --git a/plugins/poll/spec/lib/poll_spec.rb b/plugins/poll/spec/lib/poll_spec.rb index 139a82dd7cd..16c224be929 100644 --- a/plugins/poll/spec/lib/poll_spec.rb +++ b/plugins/poll/spec/lib/poll_spec.rb @@ -127,6 +127,54 @@ describe DiscoursePoll::Poll do I18n.t("poll.min_vote_per_user", count: poll.min) ) end + + it 'should allow user to vote on a multiple poll even if min option is not configured' do + post_with_multiple_poll = Fabricate(:post, raw: <<~RAW) + [poll type=multiple max=3] + * 1 + * 2 + * 3 + * 4 + * 5 + [/poll] + RAW + + poll = post_with_multiple_poll.polls.first + + DiscoursePoll::Poll.vote( + user, + post_with_multiple_poll.id, + "poll", + [poll.poll_options.first.digest] + ) + + expect(PollVote.where(poll: poll, user: user).pluck(:poll_option_id)) + .to contain_exactly(poll.poll_options.first.id) + end + + it 'should allow user to vote on a multiple poll even if max option is not configured' do + post_with_multiple_poll = Fabricate(:post, raw: <<~RAW) + [poll type=multiple min=1] + * 1 + * 2 + * 3 + * 4 + * 5 + [/poll] + RAW + + poll = post_with_multiple_poll.polls.first + + DiscoursePoll::Poll.vote( + user, + post_with_multiple_poll.id, + "poll", + [poll.poll_options.first.digest, poll.poll_options.second.digest] + ) + + expect(PollVote.where(poll: poll, user: user).pluck(:poll_option_id)) + .to contain_exactly(poll.poll_options.first.id, poll.poll_options.second.id) + end end describe "post_created" do