Make sure users only vote once in the same poll
When skipping verification, we cannot apply the validation rule saying
the document number and document type must be unique, because they'll be
`nil` in many cases. So we were skipping the rule, but that makes it
possible for the same user to vote several times (for instance, once in
a booth and once via web).
So we're changing the scope of the uniqueness rule: instead of being
unique per document number, voters are unique per user. The reason we
made them unique per document number was that back in commit 900563e3
(when we added the rule), we hadn't added the relation between users and
poll voters yet.
This commit is contained in:
@@ -14,7 +14,8 @@ class Poll
|
||||
validates :booth_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 }, unless: :skip_user_verification?
|
||||
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 }
|
||||
|
||||
before_validation :set_demographic_info, :set_document_info, :set_denormalized_booth_assignment_id
|
||||
|
||||
@@ -508,6 +508,7 @@ en:
|
||||
attributes:
|
||||
document_number:
|
||||
not_in_census: "Document not in census"
|
||||
user_id:
|
||||
has_voted: "User has already voted"
|
||||
legislation/process:
|
||||
attributes:
|
||||
|
||||
@@ -510,6 +510,7 @@ es:
|
||||
attributes:
|
||||
document_number:
|
||||
not_in_census: "Este documento no aparece en el censo"
|
||||
user_id:
|
||||
has_voted: "Este usuario ya ha votado"
|
||||
legislation/process:
|
||||
attributes:
|
||||
|
||||
@@ -34,7 +34,7 @@ describe Poll::Voter do
|
||||
voter = build(:poll_voter, user: user, poll: poll)
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
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
|
||||
|
||||
context "origin" do
|
||||
|
||||
Reference in New Issue
Block a user