diff --git a/plugins/poll/config/locales/server.en.yml b/plugins/poll/config/locales/server.en.yml index 1ef088e0e40..d3716baa435 100644 --- a/plugins/poll/config/locales/server.en.yml +++ b/plugins/poll/config/locales/server.en.yml @@ -41,6 +41,9 @@ en: requires_at_least_1_valid_option: "You must select at least 1 valid option." + default_cannot_be_made_public: "Poll with votes cannot be made public." + named_cannot_be_made_public: "Poll named %{name} has votes cannot be made public." + cannot_change_polls_after_5_minutes: "You cannot add, remove or rename polls after the first 5 minutes." op_cannot_edit_options_after_5_minutes: "You cannot add or remove poll options after the first 5 minutes. Please contact a moderator if you need to edit a poll option." staff_cannot_add_or_remove_options_after_5_minutes: "You cannot add or remove poll options after the first 5 minutes. You should close this topic and create a new one instead." diff --git a/plugins/poll/lib/polls_updater.rb b/plugins/poll/lib/polls_updater.rb index 2f05f91c706..df3b22432d9 100644 --- a/plugins/poll/lib/polls_updater.rb +++ b/plugins/poll/lib/polls_updater.rb @@ -41,6 +41,7 @@ module DiscoursePoll # try to merge votes polls.each_key do |poll_name| next unless previous_polls.has_key?(poll_name) + return if has_votes && private_to_public_poll?(post, previous_polls, polls, poll_name) # when the # of options has changed, reset all the votes if polls[poll_name]["options"].size != previous_polls[poll_name]["options"].size @@ -96,5 +97,26 @@ module DiscoursePoll def self.total_votes(polls) polls.map { |key, value| value["voters"].to_i }.sum end + + private + + def self.private_to_public_poll?(post, previous_polls, current_polls, poll_name) + previous_poll = previous_polls[poll_name] + current_poll = current_polls[poll_name] + + if previous_polls["public"].nil? && current_poll["public"] == "true" + error = + if poll_name == DiscoursePoll::DEFAULT_POLL_NAME + I18n.t("poll.default_cannot_be_made_public") + else + I18n.t("poll.named_cannot_be_made_public", name: poll_name) + end + + post.errors.add(:base, error) + return true + end + + false + end end end diff --git a/plugins/poll/spec/lib/polls_updater_spec.rb b/plugins/poll/spec/lib/polls_updater_spec.rb index d2b89c0911a..2dba772e843 100644 --- a/plugins/poll/spec/lib/polls_updater_spec.rb +++ b/plugins/poll/spec/lib/polls_updater_spec.rb @@ -101,7 +101,7 @@ describe DiscoursePoll::PollsUpdater do Fabricate(:post, raw: raw) end - let(:private_poll) do + let(:private_poll_post) do raw = <<-RAW.strip_heredoc [poll] - A @@ -109,7 +109,11 @@ describe DiscoursePoll::PollsUpdater do [/poll] RAW - DiscoursePoll::PollsValidator.new(Fabricate(:post, raw: raw)).validate_polls + Fabricate(:post, raw: raw) + end + + let(:private_poll) do + DiscoursePoll::PollsValidator.new(private_poll_post).validate_polls end let(:public_poll) do @@ -130,6 +134,21 @@ describe DiscoursePoll::PollsUpdater do post.reload end + it "should not allow a private poll with votes to be made public" do + DiscoursePoll::Poll.vote(private_poll_post.id, "poll", ["5c24fc1df56d764b550ceae1b9319125"], user.id) + private_poll_post.reload + + messages = MessageBus.track_publish do + described_class.update(private_poll_post, public_poll) + end + + expect(messages).to eq([]) + + expect(private_poll_post.errors[:base]).to include( + I18n.t("poll.default_cannot_be_made_public") + ) + end + it "should retain voter_ids when options have been edited" do described_class.update(post, public_poll)