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? %> + + <% 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