Merge pull request #4047 from consul/poll-skip-verification

Allow voting when skip verification is enabled
This commit is contained in:
Javier Martín
2020-08-07 20:31:29 +02:00
committed by GitHub
7 changed files with 67 additions and 14 deletions

View File

@@ -9,9 +9,7 @@ class Polls::QuestionsController < ApplicationController
token = params[:token] token = params[:token]
answer.answer = params[:answer] answer.answer = params[:answer]
answer.touch if answer.persisted? answer.save_and_record_voter_participation(token)
answer.save!
answer.record_voter_participation(token)
@answers_by_question_id = { @question.id => params[:answer] } @answers_by_question_id = { @question.id => params[:answer] }
end end

View File

@@ -14,7 +14,11 @@ class Poll::Answer < ApplicationRecord
scope :by_author, ->(author_id) { where(author_id: author_id) } scope :by_author, ->(author_id) { where(author_id: author_id) }
scope :by_question, ->(question_id) { where(question_id: question_id) } scope :by_question, ->(question_id) { where(question_id: question_id) }
def record_voter_participation(token) def save_and_record_voter_participation(token)
Poll::Voter.find_or_create_by(user: author, poll: poll, origin: "web", token: token) transaction do
touch if persisted?
save!
Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web", token: token)
end
end end
end end

View File

@@ -14,7 +14,8 @@ class Poll
validates :booth_assignment_id, presence: true, if: ->(voter) { voter.origin == "booth" } validates :booth_assignment_id, presence: true, if: ->(voter) { voter.origin == "booth" }
validates :officer_assignment_id, presence: true, if: ->(voter) { voter.origin == "booth" } validates :officer_assignment_id, presence: true, if: ->(voter) { voter.origin == "booth" }
validates :document_number, presence: true, uniqueness: { scope: [:poll_id, :document_type], message: :has_voted } validates :document_number, presence: true, unless: :skip_user_verification?
validates :user_id, uniqueness: { scope: [:poll_id], message: :has_voted }
validates :origin, inclusion: { in: VALID_ORIGINS } validates :origin, inclusion: { in: VALID_ORIGINS }
before_validation :set_demographic_info, :set_document_info, :set_denormalized_booth_assignment_id before_validation :set_demographic_info, :set_document_info, :set_denormalized_booth_assignment_id
@@ -38,6 +39,10 @@ class Poll
self.document_number = user.document_number self.document_number = user.document_number
end end
def skip_user_verification?
Setting["feature.user.skip_verification"].present?
end
private private
def set_denormalized_booth_assignment_id def set_denormalized_booth_assignment_id

View File

@@ -508,6 +508,7 @@ en:
attributes: attributes:
document_number: document_number:
not_in_census: "Document not in census" not_in_census: "Document not in census"
user_id:
has_voted: "User has already voted" has_voted: "User has already voted"
legislation/process: legislation/process:
attributes: attributes:

View File

@@ -510,6 +510,7 @@ es:
attributes: attributes:
document_number: document_number:
not_in_census: "Este documento no aparece en el censo" not_in_census: "Este documento no aparece en el censo"
user_id:
has_voted: "Este usuario ya ha votado" has_voted: "Este usuario ya ha votado"
legislation/process: legislation/process:
attributes: attributes:

View File

@@ -37,7 +37,7 @@ describe Poll::Answer do
end end
end end
describe "#record_voter_participation" do describe "#save_and_record_voter_participation" do
let(:author) { create(:user, :level_two) } let(:author) { create(:user, :level_two) }
let(:poll) { create(:poll) } let(:poll) { create(:poll) }
let(:question) { create(:poll_question, :yes_no, poll: poll) } let(:question) { create(:poll_question, :yes_no, poll: poll) }
@@ -46,7 +46,7 @@ describe Poll::Answer do
answer = create(:poll_answer, question: question, author: author, answer: "Yes") answer = create(:poll_answer, question: question, author: author, answer: "Yes")
expect(answer.poll.voters).to be_blank expect(answer.poll.voters).to be_blank
answer.record_voter_participation("token") answer.save_and_record_voter_participation("token")
expect(poll.reload.voters.size).to eq(1) expect(poll.reload.voters.size).to eq(1)
voter = poll.voters.first voter = poll.voters.first
@@ -57,12 +57,12 @@ describe Poll::Answer do
it "updates a poll_voter with user and poll data" do it "updates a poll_voter with user and poll data" do
answer = create(:poll_answer, question: question, author: author, answer: "Yes") answer = create(:poll_answer, question: question, author: author, answer: "Yes")
answer.record_voter_participation("token") answer.save_and_record_voter_participation("token")
expect(poll.reload.voters.size).to eq(1) expect(poll.reload.voters.size).to eq(1)
answer = create(:poll_answer, question: question, author: author, answer: "No") answer = create(:poll_answer, question: question, author: author, answer: "No")
answer.record_voter_participation("token") answer.save_and_record_voter_participation("token")
expect(poll.reload.voters.size).to eq(1) expect(poll.reload.voters.size).to eq(1)
@@ -70,5 +70,16 @@ describe Poll::Answer do
expect(voter.document_number).to eq(answer.author.document_number) expect(voter.document_number).to eq(answer.author.document_number)
expect(voter.poll_id).to eq(answer.poll.id) expect(voter.poll_id).to eq(answer.poll.id)
end end
it "does not save the answer if the voter is invalid" do
allow_any_instance_of(Poll::Voter).to receive(:valid?).and_return(false)
answer = build(:poll_answer)
expect do
answer.save_and_record_voter_participation("token")
end.to raise_error(ActiveRecord::RecordInvalid)
expect(answer).not_to be_persisted
end
end end
end end

View File

@@ -34,7 +34,7 @@ describe Poll::Voter do
voter = build(:poll_voter, user: user, poll: poll) voter = build(:poll_voter, user: user, poll: poll)
expect(voter).not_to be_valid expect(voter).not_to be_valid
expect(voter.errors.messages[:document_number]).to eq(["User has already voted"]) expect(voter.errors.messages[:user_id]).to eq(["User has already voted"])
end end
it "is not valid if the user has already voted in the same poll/booth" do it "is not valid if the user has already voted in the same poll/booth" do
@@ -43,7 +43,7 @@ describe Poll::Voter do
voter = build(:poll_voter, user: user, poll: poll, booth_assignment: booth_assignment) voter = build(:poll_voter, user: user, poll: poll, booth_assignment: booth_assignment)
expect(voter).not_to be_valid expect(voter).not_to be_valid
expect(voter.errors.messages[:document_number]).to eq(["User has already voted"]) expect(voter.errors.messages[:user_id]).to eq(["User has already voted"])
end end
it "is not valid if the user has already voted in different booth in the same poll" do it "is not valid if the user has already voted in different booth in the same poll" do
@@ -52,7 +52,7 @@ describe Poll::Voter do
voter = build(:poll_voter, :from_booth, user: user, poll: poll, booth: booth) voter = build(:poll_voter, :from_booth, user: user, poll: poll, booth: booth)
expect(voter).not_to be_valid expect(voter).not_to be_valid
expect(voter.errors.messages[:document_number]).to eq(["User has already voted"]) expect(voter.errors.messages[:user_id]).to eq(["User has already voted"])
end end
it "is valid if the user has already voted in the same booth in different poll" do it "is valid if the user has already voted in the same booth in different poll" do
@@ -69,7 +69,31 @@ describe Poll::Voter do
voter = build(:poll_voter, poll: answer.question.poll, user: answer.author) voter = build(:poll_voter, poll: answer.question.poll, user: answer.author)
expect(voter).not_to be_valid expect(voter).not_to be_valid
expect(voter.errors.messages[:document_number]).to eq(["User has already voted"]) expect(voter.errors.messages[:user_id]).to eq(["User has already voted"])
end
context "Skip verification is enabled" do
before do
Setting["feature.user.skip_verification"] = true
user.update!(document_number: nil, document_type: nil)
end
it "is not valid if the user has already voted in the same poll" do
create(:poll_voter, user: user, poll: poll)
voter = build(:poll_voter, user: user, poll: poll)
expect(voter).not_to be_valid
end
it "is valid if other users have voted in the same poll" do
another_user = create(:user, :level_two, document_number: nil, document_type: nil)
create(:poll_voter, user: another_user, poll: poll)
voter = build(:poll_voter, user: user, poll: poll)
expect(voter).to be_valid
end
end end
context "origin" do context "origin" do
@@ -172,5 +196,14 @@ describe Poll::Voter do
expect(voter.document_type).to eq("1") expect(voter.document_type).to eq("1")
expect(voter.token).to eq("1234abcd") expect(voter.token).to eq("1234abcd")
end end
it "sets user info with skip verification enabled" do
Setting["feature.user.skip_verification"] = true
user = create(:user)
voter = build(:poll_voter, user: user, token: "1234abcd")
voter.save!
expect(voter.token).to eq("1234abcd")
end
end end
end end