]> projects.mako.cc - selectricity/blob - app/controllers/voter_controller.rb
fix security issue
[selectricity] / 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   helper :sparklines
21   layout 'main'
22   require_dependency "voter"
23   require_dependency "vote"
24   require_dependency "election"
25
26   def index
27     if params[:election_id]
28       @election = Election.find(params[:election_id])
29       unless @election.authenticated?
30         @voter = OpenVoter.find(:all,
31           :conditions => ["session_id = ? and election_id = ?",
32           session.session_id, @election.id])[0]
33       
34
35         @voter = OpenVoter.new unless @voter
36
37         @voter.election = @election
38         @voter.session_id = session.session_id
39         @password = "open." + @election.id.to_s
40       end
41     elsif params[:urlpassword]
42       password = params[:urlpassword]
43
44       if @voter = FullVoter.find(:all,
45         :conditions => [ "password = ?", password ] )[0]
46         @election = @voter.election
47         @password = @voter.password
48       end
49     end
50
51     if @voter and @election
52       # initialize things if the vote is blank
53       if @voter.vote.nil?
54         @voter.vote = Vote.new 
55         @voter.save
56       end
57     
58       @voter.vote.set_defaults! if @voter.vote.rankings.empty?
59
60       # if the election is now finished 
61       if @election.enddate < Time.now
62         redirect_to :action => :results, :id => @password
63       else
64         @sidebar_content = render_to_string(:partial => 'vote_sidebar')
65         if @election.embeddable? and params[:embed] == "true"
66           #look for custom theme, and assign to instance variabels for widget use
67           if @election.embed_custom_string
68             @top_bar = SkinPicture.find(:first,
69             :conditions => ["filename = ?", @election.embed_custom_string + "top_bar.png"])
70             @default_image = SkinPicture.find(:first,
71             :conditions => ["filename = ?", @election.embed_custom_string + "default_image.png"])
72             @bg1 = SkinPicture.find(:first,
73             :conditions => ["filename = ?", @election.embed_custom_string + "bg1.png"])
74             @bg2 = SkinPicture.find(:first,
75             :conditions => ["filename = ?", @election.embed_custom_string + "bg2.png"])
76             @bottom_bar = SkinPicture.find(:first,
77             :conditions => ["filename = ?", @election.embed_custom_string + "bottom_bar.png"])
78           end
79           render :template => 'embed/full_vote', :layout => 'embed'
80         else
81           render :action => 'full_vote'
82         end
83       end
84     end
85   end
86
87   def login
88     if params[:vote] and params[:vote][:password]
89       redirect_to votepassword_url( :action => 'index', :urlpassword => params[:vote][:password])
90     else
91       redirect_to :action => 'index'
92     end
93   end
94   
95   def pref_tables
96     if authenticate
97       @election = @voter.election
98       @results = @election.results
99       @candidates = {}
100       @election.candidates.each {|c| @candidates[c.id] = c}
101       @names = @election.names_by_id
102       render :template => 'common/pref_tables', :layout => 'basic'
103     else
104       redirect_to :action => 'index'
105     end
106   end
107
108   def details
109     if authenticate
110       @election = @voter.election
111       @votes = @election.votes.select {|v| v.confirmed? }.shuffle
112       @voters = @votes.collect {|v| v.voter}.shuffle
113       render :action => 'details'
114     else
115       redirect_to :action => 'index'
116     end
117   end
118
119   def review
120     if authenticate
121       @voter.vote.time = Time.now
122       @voter.vote.save
123       @voter.reload
124     else
125       redirect_to :action => 'index'
126     end
127   end
128
129   def confirm
130     if authenticate
131       if @voter.vote.confirm!
132         if @voter.election.embeddable? and params[:embed] == "true" \
133           and @voter.election.early_results?
134           redirect_to :action => :results, :id => @password, :embed => 'true'
135         else
136           render :action => 'thanks'
137         end
138       else
139         redirect_to :action => 'index'
140       end
141     else
142         redirect_to :action => 'index'
143     end
144   end
145   
146   def reminder
147     if params[:email]
148       voter_array= FullVoter.find(:all, :conditions => ["email = ?", params[:email]])
149       voter_array.delete_if {|voter| voter.election.active == 0}
150       unless voter_array.empty?
151         VoterNotify.deliver_reminder(voter_array)
152       end
153       render :action => 'reminder_sent'
154     end
155   end
156   
157   def results
158     if authenticate and
159       (@voter.election.early_results? \
160        or @voter.election.enddate < Time.now)
161       
162       @election = @voter.election
163       # compute and display results
164
165       @results = @election.results
166       @candidates = {}
167       @election.candidates.each {|c| @candidates[c.id] = c}
168       @names = @election.names_by_id
169         
170       @sidebar_content = render_to_string(:partial => 'results_sidebar')
171       #look for custom theme, and assign to instance variabels for widget use
172       if @election.embed_custom_string
173         @top_bar = SkinPicture.find(:first,
174         :conditions => ["filename = ?", @election.embed_custom_string + "top_bar.png"])
175         @default_image = SkinPicture.find(:first,
176         :conditions => ["filename = ?", @election.embed_custom_string + "default_image.png"])
177         @bg1 = SkinPicture.find(:first,
178         :conditions => ["filename = ?", @election.embed_custom_string + "bg1.png"])
179         @bg2 = SkinPicture.find(:first,
180         :conditions => ["filename = ?", @election.embed_custom_string + "bg2.png"])
181         @bottom_bar = SkinPicture.find(:first,
182         :conditions => ["filename = ?", @election.embed_custom_string + "bottom_bar.png"])
183       end
184       if @election.embeddable? and params[:embed] == "true"
185         render :template => 'embed/results', :layout => 'embed'
186       else
187         render :action => 'results'
188       end
189     else
190       redirect_to :action => 'index'
191     end
192   end
193   
194   private
195   def authenticate
196     password = params[:id]
197     if password == "open"
198       election = Election.find(params[:format])
199
200       # double check to make sure the election is not authenticated
201       unless election.authenticated?
202         @voter = OpenVoter.find(:all,
203           :conditions => ["session_id = ? and election_id = ?",
204                           session.session_id, election.id])[0]
205
206         # if the election is over, proceed
207         if (not @voter) and (election.enddate < Time.now)
208           @voter = OpenVoter.new
209           @voter.election = election
210         end
211
212         @password = "open." + election.id.to_s
213       end
214
215     else
216       @voter = FullVoter.find(:all,
217         :conditions => [ "password = ?", password ] )[0]
218       @password = @voter.password
219     end
220     @voter
221   end
222 end
223

Benjamin Mako Hill || Want to submit a patch?