aboutsummaryrefslogtreecommitdiffstats
path: root/app/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/admin_controller.rb16
-rw-r--r--app/controllers/admin_public_body_controller.rb28
-rw-r--r--app/controllers/admin_request_controller.rb4
-rw-r--r--app/controllers/application_controller.rb52
-rw-r--r--app/controllers/comment_controller.rb1
-rw-r--r--app/controllers/general_controller.rb2
-rw-r--r--app/controllers/public_body_controller.rb48
-rw-r--r--app/controllers/request_controller.rb87
-rw-r--r--app/controllers/user_controller.rb99
9 files changed, 252 insertions, 85 deletions
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 7f8cfbd67..ca5538e03 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -19,19 +19,9 @@ class AdminController < ApplicationController
# Expire cached attachment files for a request
def expire_for_request(info_request)
- # Clear out cached entries - use low level disk removal, even though we
- # are clearing results from caches_action, for several reasons:
- # * We can't use expire_action here, as it doesn't seem to be
- # compatible with the :only_path we used in the caches_action
- # call.
- # * Removing everything is simpler than having to get all the
- # parameters right for the path, and calling for HTML version vs. raw
- # attachment version.
- # * We cope properly with filenames changed by censor rules, which
- # change the URL.
- # * We could use expire_fragment with a Regexp, but it walks the whole
- # cache which is insanely slow
- cache_subpath = File.join(self.cache_store.cache_path, "views/request/#{info_request.id}")
+ # Clear out cached entries, by removing files from disk (the built in
+ # Rails fragment cache made doing this and other things too hard)
+ cache_subpath = foi_fragment_cache_all_for_request(info_request)
FileUtils.rm_rf(cache_subpath)
# Remove the database caches of body / attachment text (the attachment text
diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb
index 74a3a86c6..bce04ff98 100644
--- a/app/controllers/admin_public_body_controller.rb
+++ b/app/controllers/admin_public_body_controller.rb
@@ -120,7 +120,15 @@ class AdminPublicBodyController < AdminController
def import_csv
if params[:csv_file]
- if not params[:tag].empty?
+ if !params[:tag].empty?
+ if params['commit'] == 'Dry run'
+ dry_run_only = true
+ elsif params['commit'] == 'Upload'
+ dry_run_only = false
+ else
+ raise "internal error, unknown button label"
+ end
+
# Try with dry run first
csv_contents = params[:csv_file].read
en = PublicBody.import_csv(csv_contents, params[:tag], true, admin_http_auth_user())
@@ -128,14 +136,18 @@ class AdminPublicBodyController < AdminController
notes = en[1]
if errors.size == 0
- # And if OK, with real run
- en = PublicBody.import_csv(csv_contents, params[:tag], false, admin_http_auth_user())
- errors = en[0]
- notes = en[1]
- if errors.size != 0
- raise "dry run mismatched real run"
+ if dry_run_only
+ notes.push("Dry run was successful, real run would do as above.")
+ else
+ # And if OK, with real run
+ en = PublicBody.import_csv(csv_contents, params[:tag], false, admin_http_auth_user())
+ errors = en[0]
+ notes = en[1]
+ if errors.size != 0
+ raise "dry run mismatched real run"
+ end
+ notes.push("Import was successful.")
end
- notes.push("Import was successful.")
end
@errors = errors.join("\n")
@notes = notes.join("\n")
diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb
index ff2772b0e..f077691ff 100644
--- a/app/controllers/admin_request_controller.rb
+++ b/app/controllers/admin_request_controller.rb
@@ -215,10 +215,10 @@ class AdminRequestController < AdminController
# Bejeeps, look, sometimes a URL is something that belongs in a controller, jesus.
# XXX hammer this square peg into the round MVC hole - should be calling main_url(upload_response_url())
post_redirect = PostRedirect.new(
- :uri => upload_response_url(:url_title => info_request.url_title),
+ :uri => main_url(upload_response_url(:url_title => info_request.url_title, :only_path => true)),
:user_id => user.id)
post_redirect.save!
- url = confirm_url(:email_token => post_redirect.email_token)
+ url = main_url(confirm_url(:email_token => post_redirect.email_token, :only_path => true))
flash[:notice] = 'Send "' + name + '" &lt;<a href="mailto:' + email + '">' + email + '</a>&gt; this URL: <a href="' + url + '">' + url + "</a> - it will log them in and let them upload a response to this request."
redirect_to request_admin_url(info_request)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 5055519ec..9ee1c250b 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -40,21 +40,12 @@ class ApplicationController < ActionController::Base
before_filter :session_remember_me
def session_remember_me
# Reset the "sliding window" session expiry time.
- if session[:remember_me]
- expire_time = 1.month.from_now
- # "Why is session[:force_new_cookie] set to Time.now? In order for the “sliding window”
- # concept to work, a fresh cookie must be sent with every response. Rails only
- # sends a cookie when the session data has changed so using a value like Time.now
- # ensures that it changes every time. What I have actually found is that some
- # internal voodoo causes the session data to change slightly anyway but it’s best
- # to be sure!"
- session[:force_new_cookie] = Time.now
- else
- expire_time = nil
- end
- # if statement here is so test code runs
- if session.instance_variable_get(:@dbman)
- session.instance_variable_get(:@dbman).instance_variable_get(:@cookie_options)['expires'] = expire_time
+ if request.env['rack.session.options']
+ if session[:remember_me]
+ request.env['rack.session.options'][:expire_after] = 1.month
+ else
+ request.env['rack.session.options'][:expire_after] = nil
+ end
end
end
@@ -100,6 +91,27 @@ class ApplicationController < ActionController::Base
controller_example_group.get params[:action], params
end
+ # Used to work out where to cache fragments. We add an extra path to the
+ # URL using the first three digits of the info request id, because we can't
+ # have more than 32,000 entries in one directory on an ext3 filesystem.
+ def foi_fragment_cache_part_path(param)
+ path = url_for(param)
+ id = param['id'] || param[:id]
+ first_three_digits = id.to_s()[0..2]
+ path = path.sub("/request/", "/request/" + first_three_digits + "/")
+ return path
+ end
+ def foi_fragment_cache_path(param)
+ path = foi_fragment_cache_part_path(param)
+ path = "/views" + path
+ return File.join(self.cache_store.cache_path, path)
+ end
+ def foi_fragment_cache_all_for_request(info_request)
+ first_three_digits = info_request.id.to_s()[0..2]
+ path = "views/request/#{first_three_digits}/#{info_request.id}"
+ return File.join(self.cache_store.cache_path, path)
+ end
+
private
# Check the user is logged in
@@ -184,6 +196,16 @@ class ApplicationController < ActionController::Base
end
end
+ #
+ def check_read_only
+ read_only = MySociety::Config.get('READ_ONLY')
+ if !read_only.empty?
+ flash[:notice] = "<p>WhatDoTheyKnow is currently in maintenance. You can only view existing requests. You cannot make new ones, add followups or annotations, or otherwise change the database.</p> <p>" + read_only + "</p>"
+ redirect_to frontpage_url
+ end
+
+ end
+
# For administration interface, return display name of authenticated user
def admin_http_auth_user
# This needs special magic in mongrel: http://www.ruby-forum.com/topic/83067
diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb
index dfa31f9ef..d5f8f89fb 100644
--- a/app/controllers/comment_controller.rb
+++ b/app/controllers/comment_controller.rb
@@ -7,6 +7,7 @@
# $Id: comment_controller.rb,v 1.9 2009-03-09 01:17:04 francis Exp $
class CommentController < ApplicationController
+ before_filter :check_read_only, :only => [ :new ]
def new
if params[:type] == 'request'
diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb
index 5c4103616..efab26fad 100644
--- a/app/controllers/general_controller.rb
+++ b/app/controllers/general_controller.rb
@@ -7,7 +7,7 @@
#
# $Id: general_controller.rb,v 1.57 2009-10-03 10:23:43 francis Exp $
-require 'xmlsimple'
+require 'lib/xmlsimple'
require 'open-uri'
class GeneralController < ApplicationController
diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb
index 1ca82e463..591081fe9 100644
--- a/app/controllers/public_body_controller.rb
+++ b/app/controllers/public_body_controller.rb
@@ -6,6 +6,8 @@
#
# $Id: public_body_controller.rb,v 1.8 2009-09-14 13:27:00 francis Exp $
+require 'csv'
+
class PublicBodyController < ApplicationController
# XXX tidy this up with better error messages, and a more standard infrastructure for the redirect to canonical URL
def show
@@ -93,5 +95,51 @@ class PublicBodyController < ApplicationController
cache_in_squid
end
+
+ # Used so URLs like /local/islington work, for use e.g. writing to a local paper.
+ def list_redirect
+ @tag = params[:tag]
+ redirect_to list_public_bodies_url(:tag => @tag)
+ end
+
+ def list_all_csv
+ public_bodies = PublicBody.find(:all, :order => 'url_name')
+ report = StringIO.new
+ CSV::Writer.generate(report, ',') do |title|
+ title << [
+ 'Name',
+ 'Short name',
+ # deliberately not including 'Request email'
+ 'URL name',
+ 'Tags',
+ 'Home page',
+ 'Publication scheme',
+ 'Charity number',
+ 'Created at',
+ 'Updated at',
+ 'Version',
+ ]
+ public_bodies.each do |public_body|
+ title << [
+ public_body.name,
+ public_body.short_name,
+ # DO NOT include request_email (we don't want to make it
+ # easy to spam all authorities with requests)
+ public_body.url_name,
+ public_body.tag_string,
+ public_body.calculated_home_page,
+ public_body.publication_scheme,
+ public_body.charity_number,
+ public_body.created_at,
+ public_body.updated_at,
+ public_body.version,
+ ]
+ end
+ end
+ report.rewind
+ send_data(report.read, :type=> 'text/csv; charset=utf-8; header=present',
+ :filename => 'all-authorities.csv',
+ :disposition =>'attachment', :encoding => 'utf8')
+ end
end
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index 2606a9609..0664093c3 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -7,6 +7,7 @@
# $Id: request_controller.rb,v 1.192 2009-10-19 19:26:40 francis Exp $
class RequestController < ApplicationController
+ before_filter :check_read_only, :only => [ :new, :show_response, :describe_state ]
def show
# Look up by old style numeric identifiers
@@ -64,11 +65,26 @@ class RequestController < ApplicationController
@last_response = @info_request.get_last_response
end
+ # Extra info about a request, such as event history
+ def details
+ @info_request = InfoRequest.find_by_url_title(params[:url_title])
+ if !@info_request.user_can_view?(authenticated_user)
+ render :template => 'request/hidden', :status => 410 # gone
+ return
+ end
+
+ @columns = ['id', 'event_type', 'created_at', 'described_state', 'last_described_at', 'calculated_state' ]
+ end
+
# Requests similar to this one
def similar
@per_page = 25
@page = (params[:page] || "1").to_i
@info_request = InfoRequest.find_by_url_title(params[:url_title])
+ if !@info_request.user_can_view?(authenticated_user)
+ render :template => 'request/hidden', :status => 410 # gone
+ return
+ end
@xapian_object = ::ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events,
:offset => (@page - 1) * @per_page, :limit => @per_page, :collapse_by_prefix => 'request_collapse')
@@ -148,27 +164,27 @@ class RequestController < ApplicationController
# First time we get to the page, just display it
if params[:submitted_new_request].nil? || params[:reedit]
# Read parameters in - public body must be passed in
- if params[:public_body_id]
- params[:info_request] = { :public_body_id => params[:public_body_id] }
+ params[:info_request] = { :public_body_id => params[:public_body_id] } if !params[:info_request]
+ if !params[:info_request][:public_body_id]
+ redirect_to frontpage_url
+ return
end
@info_request = InfoRequest.new(params[:info_request])
params[:info_request_id] = @info_request.id
+ params[:outgoing_message] = {} if !params[:outgoing_message]
+ params[:outgoing_message][:info_request] = @info_request
@outgoing_message = OutgoingMessage.new(params[:outgoing_message])
@outgoing_message.set_signature_name(@user.name) if !@user.nil?
- if @info_request.public_body.nil?
- redirect_to frontpage_url
- else
- if @info_request.public_body.is_requestable?
- render :action => 'new'
+ if @info_request.public_body.is_requestable?
+ render :action => 'new'
+ else
+ if @info_request.public_body.not_requestable_reason == 'bad_contact'
+ render :action => 'new_bad_contact'
else
- if @info_request.public_body.not_requestable_reason == 'bad_contact'
- render :action => 'new_bad_contact'
- else
- # if not requestable because defunct or not_apply, redirect to main page
- # (which doesn't link to the /new/ URL)
- redirect_to public_body_url(@info_request.public_body)
- end
+ # if not requestable because defunct or not_apply, redirect to main page
+ # (which doesn't link to the /new/ URL)
+ redirect_to public_body_url(@info_request.public_body)
end
end
return
@@ -318,11 +334,14 @@ class RequestController < ApplicationController
# Display advice for requester on what to do next, as appropriate
if @info_request.calculate_status == 'waiting_response'
- flash[:notice] = "<p>Thank you! Hopefully your wait isn't too long.</p> <p>By law, you should get a response promptly, and normally before the end of <strong>" + simple_date(@info_request.date_response_required_by) + "</strong>.</p>"
+ flash[:notice] = "<p>Thank you! Hopefully your wait isn't too long.</p> <p>By law, you should get a response promptly, and " + (@info_request.public_body.is_school? ? "in term time" : "") + " normally before the end of <strong>" + simple_date(@info_request.date_response_required_by) + "</strong>.</p>"
redirect_to request_url(@info_request)
elsif @info_request.calculate_status == 'waiting_response_overdue'
- flash[:notice] = "<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and normally before the end of <strong>" + simple_date(@info_request.date_response_required_by) + "</strong>.</p>"
+ flash[:notice] = "<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and " + (@info_request.public_body.is_school? ? "in term time" : "") + " normally before the end of <strong>" + simple_date(@info_request.date_response_required_by) + "</strong>.</p>"
redirect_to request_url(@info_request)
+ elsif @info_request.calculate_status == 'waiting_response_very_overdue'
+ flash[:notice] = "<p>Thank you! Your request is long overdue, by more than 40 working days. Most requests should be answered within 20 working days. You might like to complain about this, see below.</p>"
+ redirect_to unhappy_url(@info_request)
elsif @info_request.calculate_status == 'not_held'
flash[:notice] = "<p>Thank you! Here are some ideas on what to do next:</p>
<ul>
@@ -337,7 +356,7 @@ class RequestController < ApplicationController
"
redirect_to request_url(@info_request)
elsif @info_request.calculate_status == 'rejected'
- flash[:notice] = "Oh no! Sorry to hear that your request was rejected. Here is what to do now."
+ flash[:notice] = "Oh no! Sorry to hear that your request was refused. Here is what to do now."
redirect_to unhappy_url(@info_request)
elsif @info_request.calculate_status == 'successful'
flash[:notice] = "<p>We're glad you got all the information that you wanted. If you write about or make use of the information, please come back and add an annotation below saying what you did.</p><p>If you found WhatDoTheyKnow useful, <a href=\"http://www.mysociety.org/donate/\">make a donation</a> to the charity which runs it.</p>"
@@ -360,8 +379,8 @@ class RequestController < ApplicationController
flash[:notice] = "Please use the form below to tell us more."
redirect_to help_general_url(:action => 'contact')
elsif @info_request.calculate_status == 'user_withdrawn'
- flash[:notice] = "Thanks for letting us know that you've withdrawn your request. Please add an annotation below to let other people know why you withdrew it."
- redirect_to request_url(@info_request)
+ flash[:notice] = "If you have not done so already, please write a message below telling the authority that you have withdrawn your request. Otherwise they will not know it has been withdrawn."
+ redirect_to respond_to_last_url(@info_request)
else
raise "unknown calculate_status " + @info_request.calculate_status
end
@@ -519,7 +538,7 @@ class RequestController < ApplicationController
# Test for hidden
incoming_message = IncomingMessage.find(params[:incoming_message_id])
if !incoming_message.info_request.user_can_view?(authenticated_user)
- render :template => 'request/hidden'
+ render :template => 'request/hidden', :status => 410 # gone
end
end
@@ -527,8 +546,10 @@ class RequestController < ApplicationController
around_filter :cache_attachments, :only => [ :get_attachment, :get_attachment_as_html ]
def cache_attachments
key = params.merge(:only_path => true)
- if cached = read_fragment(key)
- #if cached = 'zzz***zzz'
+ key_path = foi_fragment_cache_path(key)
+
+ if File.exists?(key_path)
+ cached = File.read(key_path)
IncomingMessage # load global filename_to_mimetype XXX should move filename_to_mimetype to proper namespace
response.content_type = filename_to_mimetype(params[:file_name].join("/")) or 'application/octet-stream'
render_for_text(cached)
@@ -537,7 +558,14 @@ class RequestController < ApplicationController
yield
- write_fragment(key, response.body)
+ # write it to the fileystem ourselves, so is just a plain file. (The
+ # various fragment cache functions using Ruby Marshall to write the file
+ # which adds a header, so isnt compatible with images that have been
+ # extracted elsewhere from PDFs)
+ FileUtils.mkdir_p(File.dirname(key_path))
+ File.atomic_write(key_path) do |f|
+ f.write(response.body)
+ end
end
def get_attachment
@@ -558,14 +586,16 @@ class RequestController < ApplicationController
# images made during conversion (e.g. images in PDF files) are put in the cache directory, so
# the same cache code in cache_attachments above will display them.
- image_dir = File.dirname(ActionController::Base.cache_store.cache_path + "/views" + url_for(params.merge(:only_path => true)))
+ key = params.merge(:only_path => true)
+ key_path = foi_fragment_cache_path(key)
+ image_dir = File.dirname(key_path)
FileUtils.mkdir_p(image_dir)
- html = @attachment.body_as_html(image_dir)
+ html, wrapper_id = @attachment.body_as_html(image_dir)
view_html_stylesheet = render_to_string :partial => "request/view_html_stylesheet"
html.sub!(/<head>/i, "<head>" + view_html_stylesheet)
- html.sub!(/<body[^>]*>/i, '<body><prefix-here><div id="wrapper"><div id="view_html_content">' + view_html_stylesheet)
- html.sub!(/<\/body[^>]*>/i, '</div></div></body>' + view_html_stylesheet)
+ html.sub!(/<body[^>]*>/i, '<body><prefix-here><div id="' + wrapper_id + '"><div id="view_html_content">')
+ html.sub!(/<\/body[^>]*>/i, '</div></div></body>')
view_html_prefix = render_to_string :partial => "request/view_html_prefix"
html.sub!("<prefix-here>", view_html_prefix)
@@ -595,6 +625,7 @@ class RequestController < ApplicationController
raise "internal error, pre-auth filter should have caught this" if !@info_request.user_can_view?(authenticated_user)
@attachment = IncomingMessage.get_attachment_by_url_part_number(@incoming_message.get_attachments_for_display, @part_number)
+ raise "attachment not found part number " + @part_number.to_s + " incoming_message " + @incoming_message.id.to_s if @attachment.nil?
# check filename in URL matches that in database (use a censor rule if you want to change a filename)
raise "please use same filename as original file has, display: '" + @attachment.display_filename + "' old_display: '" + @attachment.old_display_filename + "' original: '" + @original_filename + "'" if @attachment.display_filename != @original_filename && @attachment.old_display_filename != @original_filename
@@ -631,7 +662,7 @@ class RequestController < ApplicationController
if params[:submitted_upload_response]
file_name = nil
file_content = nil
- if params[:file_1].class.to_s == "ActionController::UploadedTempfile"
+ if !params[:file_1].nil?
file_name = params[:file_1].original_filename
file_content = params[:file_1].read
end
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb
index bc117ce2e..b3f9511b5 100644
--- a/app/controllers/user_controller.rb
+++ b/app/controllers/user_controller.rb
@@ -147,10 +147,13 @@ class UserController < ApplicationController
end
# Logout form
- def signout
+ def _do_signout
session[:user_id] = nil
session[:user_circumstance] = nil
session[:remember_me] = false
+ end
+ def signout
+ self._do_signout
if params[:r]
redirect_to params[:r]
else
@@ -159,24 +162,24 @@ class UserController < ApplicationController
end
# Change password (XXX and perhaps later email) - requires email authentication
- def signchange
+ def signchangepassword
if @user and ((not session[:user_circumstance]) or (session[:user_circumstance] != "change_password"))
# Not logged in via email, so send confirmation
- params[:submitted_signchange_send_confirm] = true
- params[:signchange] = { :email => @user.email }
+ params[:submitted_signchangepassword_send_confirm] = true
+ params[:signchangepassword] = { :email => @user.email }
end
- if params[:submitted_signchange_send_confirm]
+ if params[:submitted_signchangepassword_send_confirm]
# They've entered the email, check it is OK and user exists
- if not MySociety::Validate.is_valid_email(params[:signchange][:email])
+ if not MySociety::Validate.is_valid_email(params[:signchangepassword][:email])
flash[:error] = "That doesn't look like a valid email address. Please check you have typed it correctly."
- render :action => 'signchange_send_confirm'
+ render :action => 'signchangepassword_send_confirm'
return
end
- user_signchange = User.find_user_by_email(params[:signchange][:email])
- if user_signchange
- # Send email with login link to go to signchange page
- url = signchange_url
+ user_signchangepassword = User.find_user_by_email(params[:signchangepassword][:email])
+ if user_signchangepassword
+ # Send email with login link to go to signchangepassword page
+ url = signchangepassword_url
if params[:pretoken]
url += "?pretoken=" + params[:pretoken]
end
@@ -188,27 +191,27 @@ class UserController < ApplicationController
},
:circumstance => "change_password" # special login that lets you change your password
)
- post_redirect.user = user_signchange
+ post_redirect.user = user_signchangepassword
post_redirect.save!
url = confirm_url(:email_token => post_redirect.email_token)
- UserMailer.deliver_confirm_login(user_signchange, post_redirect.reason_params, url)
+ UserMailer.deliver_confirm_login(user_signchangepassword, post_redirect.reason_params, url)
else
# User not found, but still show confirm page to not leak fact user exists
end
- render :action => 'signchange_confirm'
+ render :action => 'signchangepassword_confirm'
elsif not @user
# Not logged in, prompt for email
- render :action => 'signchange_send_confirm'
+ render :action => 'signchangepassword_send_confirm'
else
# Logged in via special email change password link, so can offer form to change password
raise "internal error" unless (session[:user_circumstance] == "change_password")
- if params[:submitted_signchange_password]
+ if params[:submitted_signchangepassword_do]
@user.password = params[:user][:password]
@user.password_confirmation = params[:user][:password_confirmation]
if not @user.valid?
- render :action => 'signchange'
+ render :action => 'signchangepassword'
else
@user.save!
flash[:notice] = "Your password has been changed."
@@ -220,11 +223,71 @@ class UserController < ApplicationController
end
end
else
- render :action => 'signchange'
+ render :action => 'signchangepassword'
end
end
end
+ # Change your email
+ def signchangeemail
+ if not authenticated?(
+ :web => "To change your email address used on WhatDoTheyKnow.com",
+ :email => "Then you can change your email address used on WhatDoTheyKnow.com",
+ :email_subject => "Change your email address used on WhatDoTheyKnow.com"
+ )
+ # "authenticated?" has done the redirect to signin page for us
+ return
+ end
+
+ if !params[:submitted_signchangeemail_do]
+ render :action => 'signchangeemail'
+ return
+ end
+
+ @signchangeemail = ChangeEmailValidator.new(params[:signchangeemail])
+ @signchangeemail.logged_in_user = @user
+
+ if !@signchangeemail.valid?
+ render :action => 'signchangeemail'
+ return
+ end
+
+ # if new email already in use, send email there saying what happened
+ user_alreadyexists = User.find_user_by_email(@signchangeemail.new_email)
+ if user_alreadyexists
+ UserMailer.deliver_changeemail_already_used(@user.email, @signchangeemail.new_email)
+ # it is important this screen looks the same as the one below, so
+ # you can't change to someone's email in order to tell if they are
+ # registered with that email on the site
+ render :action => 'signchangeemail_confirm'
+ return
+ end
+
+ # if not already, send a confirmation link to the new email address which logs
+ # them into the old email's user account, but with special user_circumstance
+ if (not session[:user_circumstance]) or (session[:user_circumstance] != "change_email")
+ post_redirect = PostRedirect.new(:uri => signchangeemail_url(), :post_params => params,
+ :circumstance => "change_email" # special login that lets you change your email
+ )
+ post_redirect.user = @user
+ post_redirect.save!
+
+ url = confirm_url(:email_token => post_redirect.email_token)
+ UserMailer.deliver_changeemail_confirm(@user, @signchangeemail.new_email, url)
+ # it is important this screen looks the same as the one above, so
+ # you can't change to someone's email in order to tell if they are
+ # registered with that email on the site
+ render :action => 'signchangeemail_confirm'
+ return
+ end
+
+ # circumstance is 'change_email', so can actually change the email
+ @user.email = @signchangeemail.new_email
+ @user.save!
+ flash[:notice] = "You have now changed your email address used on WhatDoTheyKnow.com"
+ redirect_to user_url(@user)
+ end
+
# Send a message to another user
def contact
@recipient_user = User.find(params[:id])