# frozen_string_literal: true module Decidim module Elections # Exposes the elections resources so users can participate on them class VotesController < Decidim::Elections::ApplicationController WIZARD_STEPS = %w(register election confirm ballot_decision).freeze include FormFactory include HasVoteFlow helper VotesHelper helper_method :bulletin_board_server, :authority_public_key, :scheme_name, :election_unique_id, :exit_path, :elections, :election, :questions, :questions_count, :vote, :valid_questionnaire?, :wizard_steps delegate :count, to: :questions, prefix: true def new vote_flow.voter_login(params) return unless vote_allowed? @form = form(Voter::VoteForm).from_params({ voter_token:, voter_id: }, election:, user: vote_flow.user) end def create vote_flow.voter_from_token(params.require(:vote).permit(:voter_token, :voter_id)) return unless valid_voter_token? return unless vote_allowed? return redirect_to election_vote_path(election, id: params[:vote][:encrypted_data_hash], token: vote_flow.voter_id_token) if preview_mode? @form = form(Voter::VoteForm).from_params(params, election:, user: vote_flow.user, email: vote_flow.email) Voter::CastVote.call(@form) do on(:ok) do |vote| redirect_to election_vote_path(election, id: vote.encrypted_vote_hash, token: vote_flow.voter_id_token) end on(:invalid) do flash[:alert] = I18n.t("votes.create.error", scope: "decidim.elections") redirect_to exit_path end end end def show enforce_permission_to :view, :election, election: end def update enforce_permission_to(:view, :election, election:) Voter::UpdateVoteStatus.call(vote) do on(:ok) do redirect_to election_vote_path(election, id: vote.encrypted_vote_hash, token: vote_flow.voter_id_token(vote.voter_id)) end on(:invalid) do flash[:alert] = I18n.t("votes.update.error", scope: "decidim.elections") redirect_to exit_path end end end def verify enforce_permission_to(:view, :election, election:) @form = form(Voter::VerifyVoteForm).instance(election:) end private delegate :bulletin_board_server, :scheme_name, to: :bulletin_board_client def election_unique_id @election_unique_id ||= Decidim::BulletinBoard::MessageIdentifier.unique_election_id(bulletin_board_client.authority_slug, election.id) end def vote @vote ||= Decidim::Elections::Vote.find_by(election:, encrypted_vote_hash: params[:id]) if params[:id] end def exit_path @exit_path ||= if allowed_to?(:view, :election, election:) election_path(election) else elections_path end end def pending_vote @pending_vote ||= Decidim::Elections::Votes::PendingVotes.for.find_by(voter_id:, election:) end def bulletin_board_client @bulletin_board_client ||= Decidim::Elections.bulletin_board end def authority_public_key @authority_public_key ||= bulletin_board_client.authority_public_key.to_json end def elections @elections ||= Election.where(component: current_component) end def election @election ||= elections.find(params[:election_id]) end def questions @questions ||= ballot_questions.includes(:answers).order(weight: :asc, id: :asc) end def vote_allowed? if preview_mode? return true if can_preview? redirect_to( exit_path, alert: t("votes.messages.not_allowed", scope: "decidim.elections") ) return false end if pending_vote.present? redirect_to( election_vote_path(election, id: pending_vote.encrypted_vote_hash, token: vote_flow.voter_id_token) ) return false end vote_check_result = vote_flow.vote_check(online_vote_path: new_election_vote_path) unless vote_check_result.allowed? redirect_to( vote_check_result.exit_path || exit_path, alert: vote_check_result.error_message, status: :temporary_redirect ) return false end enforce_permission_to(:vote, :election, election:) true end def valid_voter_token? return true if preview_mode? || vote_flow.valid_received_data? redirect_to(exit_path, alert: t("votes.messages.invalid_token", scope: "decidim.elections")) end def valid_questionnaire? return @valid_questionnaire if defined?(@valid_questionnaire) @valid_questionnaire = election.questionnaire.questions.any? end def wizard_steps WIZARD_STEPS end end end end