* Fix invalid votes from the API being accepted Fixes #12556 - Ensure `choice` is an integer instead of silently converting to 0 - Ensure `choice` corresponds to an actual choice of the poll * Please CodeClimatemaster^2
@@ -20,7 +20,7 @@ class VoteService < BaseService | |||||
ApplicationRecord.transaction do | ApplicationRecord.transaction do | ||||
@choices.each do |choice| | @choices.each do |choice| | ||||
@votes << @poll.votes.create!(account: @account, choice: choice) | |||||
@votes << @poll.votes.create!(account: @account, choice: Integer(choice)) | |||||
end | end | ||||
end | end | ||||
else | else | ||||
@@ -4,10 +4,18 @@ class VoteValidator < ActiveModel::Validator | |||||
def validate(vote) | def validate(vote) | ||||
vote.errors.add(:base, I18n.t('polls.errors.expired')) if vote.poll.expired? | vote.errors.add(:base, I18n.t('polls.errors.expired')) if vote.poll.expired? | ||||
vote.errors.add(:base, I18n.t('polls.errors.invalid_choice')) if invalid_choice?(vote) | |||||
if vote.poll.multiple? && vote.poll.votes.where(account: vote.account, choice: vote.choice).exists? | if vote.poll.multiple? && vote.poll.votes.where(account: vote.account, choice: vote.choice).exists? | ||||
vote.errors.add(:base, I18n.t('polls.errors.already_voted')) | vote.errors.add(:base, I18n.t('polls.errors.already_voted')) | ||||
elsif !vote.poll.multiple? && vote.poll.votes.where(account: vote.account).exists? | elsif !vote.poll.multiple? && vote.poll.votes.where(account: vote.account).exists? | ||||
vote.errors.add(:base, I18n.t('polls.errors.already_voted')) | vote.errors.add(:base, I18n.t('polls.errors.already_voted')) | ||||
end | end | ||||
end | end | ||||
private | |||||
def invalid_choice?(vote) | |||||
vote.choice.negative? || vote.choice >= vote.poll.options.size | |||||
end | |||||
end | end |
@@ -922,6 +922,7 @@ en: | |||||
duration_too_long: is too far into the future | duration_too_long: is too far into the future | ||||
duration_too_short: is too soon | duration_too_short: is too soon | ||||
expired: The poll has already ended | expired: The poll has already ended | ||||
invalid_choice: The chosen vote option does not exist | |||||
over_character_limit: cannot be longer than %{max} characters each | over_character_limit: cannot be longer than %{max} characters each | ||||
too_few_options: must have more than one item | too_few_options: must have more than one item | ||||
too_many_options: can't contain more than %{max} items | too_many_options: can't contain more than %{max} items | ||||