diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index b73c07474..ce9861547 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -70,6 +70,7 @@
//= require polls_admin
//= require leaflet
//= require map
+//= require polls
var initialize_modules = function() {
App.Comments.initialize();
@@ -108,6 +109,7 @@ var initialize_modules = function() {
App.TagAutocomplete.initialize();
App.PollsAdmin.initialize();
App.Map.initialize();
+ App.Polls.initialize();
};
$(function(){
diff --git a/app/assets/javascripts/polls.js.coffee b/app/assets/javascripts/polls.js.coffee
new file mode 100644
index 000000000..5cf792ce2
--- /dev/null
+++ b/app/assets/javascripts/polls.js.coffee
@@ -0,0 +1,28 @@
+App.Polls =
+ generateToken: ->
+ token = ''
+ rand = ''
+ for n in [0..5]
+ rand = Math.random().toString(36).substr(2) # remove `0.`
+ token = token + rand;
+
+ token = token.substring(0, 64)
+ return token
+
+ replaceToken: ->
+ for link in $('.js-question-answer')
+ token_param = link.search.slice(-6)
+ if token_param == "token="
+ link.href = link.href + @token
+
+ initialize: ->
+ @token = App.Polls.generateToken()
+ App.Polls.replaceToken()
+
+ $(".js-question-answer").on
+ click: =>
+ token_message = $(".js-token-message")
+ if !token_message.is(':visible')
+ token_message.html(token_message.html() + "
" + @token + "");
+ token_message.show()
+ false
diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb
index 7fecefe98..407e6d984 100644
--- a/app/controllers/polls/questions_controller.rb
+++ b/app/controllers/polls/questions_controller.rb
@@ -7,11 +7,12 @@ class Polls::QuestionsController < ApplicationController
def answer
answer = @question.answers.find_or_initialize_by(author: current_user)
+ token = params[:token]
answer.answer = params[:answer]
answer.touch if answer.persisted?
answer.save!
- answer.record_voter_participation
+ answer.record_voter_participation(token)
@answers_by_question_id = { @question.id => params[:answer] }
end
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 41a038b46..064aa130f 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -1,5 +1,7 @@
class PollsController < ApplicationController
+ include PollsHelper
+
load_and_authorize_resource
has_filters %w{current expired incoming}
@@ -12,7 +14,7 @@ class PollsController < ApplicationController
def show
@questions = @poll.questions.for_render.sort_for_list
-
+ @token = poll_voter_token(@poll, current_user)
@answers_by_question_id = {}
poll_answers = ::Poll::Answer.by_question(@poll.question_ids).by_author(current_user.try(:id))
poll_answers.each do |answer|
diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb
index b6c0518bb..dd4018be7 100644
--- a/app/helpers/polls_helper.rb
+++ b/app/helpers/polls_helper.rb
@@ -41,6 +41,10 @@ module PollsHelper
booth.name + location
end
+ def poll_voter_token(poll, user)
+ Poll::Voter.where(poll: poll, user: user, origin: "web").first&.token || ''
+ end
+
def voted_before_sign_in(question)
question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at >= vote.updated_at }
end
diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb
index 2378de6ba..4484060dd 100644
--- a/app/models/poll/answer.rb
+++ b/app/models/poll/answer.rb
@@ -16,7 +16,7 @@ class Poll::Answer < ActiveRecord::Base
scope :by_author, ->(author_id) { where(author_id: author_id) }
scope :by_question, ->(question_id) { where(question_id: question_id) }
- def record_voter_participation
- Poll::Voter.find_or_create_by!(user: author, poll: poll, origin: "web")
+ def record_voter_participation(token)
+ Poll::Voter.find_or_create_by(user: author, poll: poll, origin: "web", token: token)
end
-end
\ No newline at end of file
+end
diff --git a/app/views/polls/questions/_answers.html.erb b/app/views/polls/questions/_answers.html.erb
index 5fc22fd44..7cdb50cfb 100644
--- a/app/views/polls/questions/_answers.html.erb
+++ b/app/views/polls/questions/_answers.html.erb
@@ -10,11 +10,11 @@
<% else %>
<%= link_to answer.title,
- answer_question_path(question, answer: answer.title),
+ answer_question_path(question, answer: answer.title, token: token),
method: :post,
remote: true,
title: t("poll_questions.show.vote_answer", answer: answer.title),
- class: "button secondary hollow" %>
+ class: "button secondary hollow js-question-answer" %>
<% end %>
<% end %>
<% else %>
diff --git a/app/views/polls/questions/_question.html.erb b/app/views/polls/questions/_question.html.erb
index 982d0a070..b0df3fb42 100644
--- a/app/views/polls/questions/_question.html.erb
+++ b/app/views/polls/questions/_question.html.erb
@@ -4,6 +4,6 @@
- <%= render 'polls/questions/answers', question: question %>
+ <%= render 'polls/questions/answers', question: question, token: token %>
diff --git a/app/views/polls/questions/answer.js.erb b/app/views/polls/questions/answer.js.erb
index aabbd8d89..8e8c01358 100644
--- a/app/views/polls/questions/answer.js.erb
+++ b/app/views/polls/questions/answer.js.erb
@@ -1 +1,2 @@
-$("#<%= dom_id(@question) %>_answers").html('<%= j render("polls/questions/answers", question: @question) %>');
+<% token = poll_voter_token(@question.poll, current_user) %>
+$("#<%= dom_id(@question) %>_answers").html('<%= j render("polls/questions/answers", question: @question, token: token) %>');
diff --git a/app/views/polls/show.html.erb b/app/views/polls/show.html.erb
index e152f888c..ad8b9b0c5 100644
--- a/app/views/polls/show.html.erb
+++ b/app/views/polls/show.html.erb
@@ -38,13 +38,21 @@
<%= t("polls.show.already_voted_in_booth") %>
<% else %>
+
+ <% if poll_voter_token(@poll, current_user).empty? %>
+
+ <%= t('poll_questions.show.voted_token') %>
+
+ <% end %>
+
<% if current_user && !@poll.votable_by?(current_user) %>
<%= t("polls.show.already_voted_in_web") %>
<% end %>
+
<% @questions.each do |question| %>
- <%= render 'polls/questions/question', question: question %>
+ <%= render 'polls/questions/question', question: question, token: @token %>
<% end %>
<% end %>
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml
index 79621ddb5..297ec276a 100644
--- a/config/locales/en/general.yml
+++ b/config/locales/en/general.yml
@@ -500,6 +500,7 @@ en:
show:
vote_answer: "Vote %{answer}"
voted: "You have voted %{answer}"
+ voted_token: "You can write down this vote identifier, to check your vote on the final results:"
proposal_notifications:
new:
title: "Send message"
diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml
index 334090b7b..da81699d0 100644
--- a/config/locales/es/general.yml
+++ b/config/locales/es/general.yml
@@ -500,6 +500,7 @@ es:
show:
vote_answer: "Votar %{answer}"
voted: "Has votado %{answer}"
+ voted_token: "Puedes apuntar este identificador de voto, para comprobar tu votación en el resultado final:"
proposal_notifications:
new:
title: "Enviar mensaje"
diff --git a/db/migrate/20171006145053_add_token_to_poll_voters.rb b/db/migrate/20171006145053_add_token_to_poll_voters.rb
new file mode 100644
index 000000000..5d07f5065
--- /dev/null
+++ b/db/migrate/20171006145053_add_token_to_poll_voters.rb
@@ -0,0 +1,5 @@
+class AddTokenToPollVoters < ActiveRecord::Migration
+ def change
+ add_column :poll_voters, :token, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 22e362a1f..b68467ce8 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20171004210108) do
+ActiveRecord::Schema.define(version: 20171006145053) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -768,6 +768,7 @@ ActiveRecord::Schema.define(version: 20171004210108) do
t.integer "user_id"
t.string "origin"
t.integer "officer_id"
+ t.string "token"
end
add_index "poll_voters", ["booth_assignment_id"], name: "index_poll_voters_on_booth_assignment_id", using: :btree
diff --git a/spec/features/polls/voter_spec.rb b/spec/features/polls/voter_spec.rb
index e558b7261..256807928 100644
--- a/spec/features/polls/voter_spec.rb
+++ b/spec/features/polls/voter_spec.rb
@@ -32,6 +32,11 @@ feature "Voter" do
expect(page).to_not have_link('Yes')
end
+ find(:css, ".js-token-message").should be_visible
+ token = find(:css, ".js-question-answer")[:href].gsub(/.+?(?=token)/, '').gsub('token=', '')
+
+ expect(page).to have_content "You can write down this vote identifier, to check your vote on the final results: #{token}"
+
expect(Poll::Voter.count).to eq(1)
expect(Poll::Voter.first.origin).to eq("web")
end
@@ -101,6 +106,8 @@ feature "Voter" do
visit poll_path(poll)
+ expect(page).to_not have_selector('.js-token-message')
+
expect(page).to have_content "You have already participated in this poll. If you vote again it will be overwritten."
within("#poll_question_#{question.id}_answers") do
expect(page).to_not have_link('Yes')
diff --git a/spec/models/poll/answer_spec.rb b/spec/models/poll/answer_spec.rb
index 2c27bc060..8731445cc 100644
--- a/spec/models/poll/answer_spec.rb
+++ b/spec/models/poll/answer_spec.rb
@@ -46,7 +46,7 @@ describe Poll::Answer do
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
expect(answer.poll.voters).to be_blank
- answer.record_voter_participation
+ answer.record_voter_participation('token')
expect(poll.reload.voters.size).to eq(1)
voter = poll.voters.first
@@ -57,12 +57,12 @@ describe Poll::Answer do
it "updates a poll_voter with user and poll data" do
answer = create(:poll_answer, question: question, author: author, answer: "Yes")
- answer.record_voter_participation
+ answer.record_voter_participation('token')
expect(poll.reload.voters.size).to eq(1)
answer = create(:poll_answer, question: question, author: author, answer: "No")
- answer.record_voter_participation
+ answer.record_voter_participation('token')
expect(poll.reload.voters.size).to eq(1)
diff --git a/spec/models/poll/voter_spec.rb b/spec/models/poll/voter_spec.rb
index f306248dc..ae0f84a49 100644
--- a/spec/models/poll/voter_spec.rb
+++ b/spec/models/poll/voter_spec.rb
@@ -76,7 +76,7 @@ describe :voter do
it "should not be valid if the user has voted via web" do
answer = create(:poll_answer)
- answer.record_voter_participation
+ answer.record_voter_participation('token')
voter = build(:poll_voter, poll: answer.question.poll, user: answer.author)
expect(voter).to_not be_valid
@@ -162,11 +162,12 @@ describe :voter do
it "sets user info" do
user = create(:user, document_number: "1234A", document_type: "1")
- voter = build(:poll_voter, user: user)
+ voter = build(:poll_voter, user: user, token: "1234abcd")
voter.save
expect(voter.document_number).to eq("1234A")
expect(voter.document_type).to eq("1")
+ expect(voter.token).to eq("1234abcd")
end
end
-end
\ No newline at end of file
+end