merged in changes from live version
[selectricity-live] / app / controllers / voter_controller.rb
1 # Selectricity: Voting Machinery for the Masses
2 # Copyright (C) 2007, 2008 Benjamin Mako Hill <mako@atdot.cc>
3 # Copyright (C) 2007 Massachusetts Institute of Technology
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Affero General Public License for more details.
14 #
15 # You should have received a copy of the GNU Affero General Public
16 # License along with this program.  If not, see
17 # <http://www.gnu.org/licenses/>.
18
19 class VoterController < ApplicationController
20   layout 'main'
21   require_dependency "voter"
22   require_dependency "vote"
23   require_dependency "election"
24
25   def index
26     if params[:election_id]
27       @election = Election.find(params[:election_id])
28       unless @election.authenticated?
29         @voter = Voter.find(:all,
30           :conditions => ["session_id = ? and election_id = ?",
31           session.session_id, @election.id])[0]
32       
33         @voter = Voter.new unless @voter
34
35         @voter.election = @election
36         @voter.session_id = session.session_id
37         @password = "open." + @election.id.to_s
38       end
39     elsif params[:urlpassword]
40       password = params[:urlpassword]
41
42       if @voter = FullVoter.find(:all,
43         :conditions => [ "password = ?", password ] )[0]
44         @election = @voter.election
45         @password = @voter.password
46       end
47     end
48
49     if @voter and @election
50       # initialize things if the vote is blank
51       if @voter.vote.nil?
52         @voter.vote = Vote.new 
53         @voter.save
54       end
55       
56       @voter.vote.set_defaults! if @voter.vote.rankings.empty?
57
58       # if the election is now finished 
59       if @election.enddate < Time.now
60         redirect_to :action => :results, :id => @password
61       else
62         @sidebar_content = render_to_string(:partial => 'vote_sidebar')
63         if @election.embeddable? and params[:embed] == "true"
64           #look for custom theme, and assign to instance variabels for widget use
65           if @election.embed_custom_string
66             @top_bar = SkinPicture.find(:first,
67             :conditions => ["filename = ?", @election.embed_custom_string + "top_bar.png"])
68             @default_image = SkinPicture.find(:first,
69             :conditions => ["filename = ?", @election.embed_custom_string + "default_image.png"])
70             @bg1 = SkinPicture.find(:first,
71             :conditions => ["filename = ?", @election.embed_custom_string + "bg1.png"])
72             @bg2 = SkinPicture.find(:first,
73             :conditions => ["filename = ?", @election.embed_custom_string + "bg2.png"])
74             @bottom_bar = SkinPicture.find(:first,
75             :conditions => ["filename = ?", @election.embed_custom_string + "bottom_bar.png"])
76           end
77           render :template => 'embed/full_vote', :layout => 'embed'
78         else
79           render :action => 'full_vote'
80         end
81       end
82     end
83   end
84
85   def login
86     if params[:vote] and params[:vote][:password]
87       redirect_to votepassword_url( :action => 'index', :urlpassword => params[:vote][:password])
88     else
89       redirect_to :action => 'index'
90     end
91   end
92   
93   def pref_tables
94     if authenticate
95       @election = @voter.election
96       @results = @election.results
97       @candidates = {}
98       @election.candidates.each {|c| @candidates[c.id] = c}
99       @names = @election.names_by_id
100       render :template => 'common/pref_tables', :layout => 'basic'
101     else
102       redirect_to :action => 'index'
103     end
104   end
105
106   def details
107     if authenticate
108       @election = @voter.election
109       @votes = @election.votes.select {|v| v.confirmed? }.randomize
110       @voters = @votes.collect {|v| v.voter}.randomize
111       render :action => 'details'
112     else
113       redirect_to :action => 'index'
114     end
115   end
116
117   def review
118     if authenticate
119       @voter.vote.time = Time.now
120       @voter.vote.save
121       @voter.reload
122     else
123       redirect_to :action => 'index'
124     end
125   end
126
127   def confirm
128     if authenticate
129       @voter.vote.confirm!
130
131       if @voter.election.embeddable? and params[:embed] == "true" \
132         and @voter.election.early_results?
133         redirect_to :action => :results, :id => @password, :embed => 'true'
134       else
135         render :action => 'thanks'
136       end
137     else
138       redirect_to :action => 'index'
139     end
140   end
141   
142   def reminder
143     if params[:email]
144       voter_array= FullVoter.find(:all, :conditions => ["email = ?", params[:email]])
145       voter_array.delete_if {|voter| voter.election.active == 0}
146       unless voter_array.empty?
147         VoterNotify.deliver_reminder(voter_array)
148       end
149       render :action => 'reminder_sent'
150     end
151   end
152   
153   def results
154     if authenticate and
155       (@voter.election.early_results? \
156        or @voter.election.enddate < Time.now)
157       
158       @election = @voter.election
159       # compute and display results
160
161       @results = @election.results
162       @candidates = {}
163       @election.candidates.each {|c| @candidates[c.id] = c}
164       @names = @election.names_by_id
165         
166       @sidebar_content = render_to_string(:partial => 'results_sidebar')
167       #look for custom theme, and assign to instance variabels for widget use
168       if @election.embed_custom_string
169         @top_bar = SkinPicture.find(:first,
170         :conditions => ["filename = ?", @election.embed_custom_string + "top_bar.png"])
171         @default_image = SkinPicture.find(:first,
172         :conditions => ["filename = ?", @election.embed_custom_string + "default_image.png"])
173         @bg1 = SkinPicture.find(:first,
174         :conditions => ["filename = ?", @election.embed_custom_string + "bg1.png"])
175         @bg2 = SkinPicture.find(:first,
176         :conditions => ["filename = ?", @election.embed_custom_string + "bg2.png"])
177         @bottom_bar = SkinPicture.find(:first,
178         :conditions => ["filename = ?", @election.embed_custom_string + "bottom_bar.png"])
179       end
180       if @election.embeddable? and params[:embed] == "true"
181         render :template => 'embed/results', :layout => 'embed'
182       else
183         render :action => 'results'
184       end
185     else
186       redirect_to :action => 'index'
187     end
188   end
189   
190   private
191   def authenticate
192     password = params[:id]
193     if password == "open"
194       election = Election.find(params[:format])
195       unless election.authenticated?
196         @voter = Voter.find(:all,
197           :conditions => ["session_id = ? and election_id = ?",
198                           session.session_id, election.id])[0]
199         @password = "open." + election.id.to_s
200       end
201     else
202       @voter = FullVoter.find(:all,
203         :conditions => [ "password = ?", password ] )[0]
204       @password = @voter.password
205     end
206     @voter
207   end
208 end
209

Benjamin Mako Hill || Want to submit a patch?