aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/admin_censor_rule_controller.rb2
-rw-r--r--app/controllers/admin_controller.rb47
-rw-r--r--app/controllers/admin_general_controller.rb13
-rw-r--r--app/controllers/admin_public_body_controller.rb32
-rw-r--r--app/controllers/admin_request_controller.rb148
-rw-r--r--app/controllers/admin_user_controller.rb11
-rw-r--r--app/controllers/application_controller.rb75
-rw-r--r--app/controllers/comment_controller.rb6
-rw-r--r--app/controllers/general_controller.rb16
-rw-r--r--app/controllers/help_controller.rb6
-rw-r--r--app/controllers/holiday_controller.rb4
-rw-r--r--app/controllers/public_body_controller.rb34
-rw-r--r--app/controllers/request_controller.rb141
-rw-r--r--app/controllers/request_game_controller.rb6
-rw-r--r--app/controllers/services_controller.rb14
-rw-r--r--app/controllers/track_controller.rb37
-rw-r--r--app/controllers/user_controller.rb74
-rw-r--r--app/helpers/application_helper.rb33
-rw-r--r--app/helpers/config_helper.rb2
-rwxr-xr-xapp/helpers/link_to_helper.rb51
-rw-r--r--app/helpers/mailer_helper.rb7
-rw-r--r--app/models/about_me_validator.rb2
-rw-r--r--app/models/application_mailer.rb9
-rw-r--r--app/models/censor_rule.rb11
-rw-r--r--app/models/change_email_validator.rb4
-rw-r--r--app/models/comment.rb10
-rw-r--r--app/models/contact_mailer.rb17
-rw-r--r--app/models/contact_validator.rb2
-rw-r--r--app/models/exim_log.rb6
-rw-r--r--app/models/exim_log_done.rb2
-rw-r--r--app/models/foi_attachment.rb24
-rw-r--r--app/models/holiday.rb6
-rw-r--r--app/models/incoming_message.rb88
-rw-r--r--app/models/info_request.rb123
-rw-r--r--app/models/info_request_event.rb108
-rw-r--r--app/models/outgoing_mailer.rb6
-rw-r--r--app/models/outgoing_message.rb25
-rw-r--r--app/models/post_redirect.rb6
-rw-r--r--app/models/profile_photo.rb14
-rw-r--r--app/models/public_body.rb98
-rw-r--r--app/models/purge_request.rb52
-rw-r--r--app/models/raw_email.rb8
-rw-r--r--app/models/request_mailer.rb45
-rw-r--r--app/models/track_mailer.rb10
-rw-r--r--app/models/track_thing.rb92
-rw-r--r--app/models/track_things_sent_email.rb2
-rw-r--r--app/models/user.rb75
-rw-r--r--app/models/user_info_request_sent_alert.rb4
-rw-r--r--app/views/admin_general/debug.rhtml2
-rw-r--r--app/views/admin_general/index.rhtml14
-rw-r--r--app/views/admin_general/timeline.rhtml2
-rw-r--r--app/views/admin_request/_incoming_message_actions.rhtml2
-rw-r--r--app/views/admin_request/edit.rhtml17
-rw-r--r--app/views/admin_request/hidden_user_explanation.rhtml9
-rw-r--r--app/views/contact_mailer/from_admin_message.rhtml2
-rw-r--r--app/views/general/_locale_switcher.rhtml22
-rw-r--r--app/views/general/_orglink.rhtml4
-rw-r--r--app/views/general/search.rhtml3
-rw-r--r--app/views/layouts/admin.rhtml18
-rw-r--r--app/views/layouts/default.rhtml20
-rw-r--r--app/views/public_body/show.rhtml2
-rw-r--r--app/views/request/_bubble.rhtml2
-rw-r--r--app/views/request/_sidebar.rhtml25
-rw-r--r--app/views/request/_wall_listing.rhtml30
-rw-r--r--app/views/request/show.rhtml12
-rw-r--r--app/views/request_mailer/not_clarified_alert.rhtml6
-rw-r--r--app/views/request_mailer/requires_admin.rhtml2
-rw-r--r--app/views/track/_tracking_links.rhtml19
-rw-r--r--app/views/user/_change_receive_email.rhtml16
-rw-r--r--app/views/user/confirm.rhtml4
-rw-r--r--app/views/user/rate_limited.rhtml2
-rw-r--r--app/views/user/show.rhtml13
-rw-r--r--app/views/user/sign.rhtml5
-rw-r--r--app/views/user/wall.rhtml16
74 files changed, 1206 insertions, 671 deletions
diff --git a/app/controllers/admin_censor_rule_controller.rb b/app/controllers/admin_censor_rule_controller.rb
index 2c0c7ca4e..52df8dfc1 100644
--- a/app/controllers/admin_censor_rule_controller.rb
+++ b/app/controllers/admin_censor_rule_controller.rb
@@ -65,7 +65,7 @@ class AdminCensorRuleController < AdminController
render :action => 'edit'
end
end
-
+
def destroy
censor_rule = CensorRule.find(params[:censor_rule_id])
info_request = censor_rule.info_request
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index adb506b91..884d7e540 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -36,6 +36,8 @@ class AdminController < ApplicationController
# also force a search reindexing (so changed text reflected in search)
info_request.reindex_request_events
+ # and remove from varnsi
+ info_request.purge_in_cache
end
# Expire cached attachment files for a user
@@ -44,23 +46,40 @@ class AdminController < ApplicationController
expire_for_request(info_request)
end
end
- private
- def authenticate
- config_username = MySociety::Config.get('ADMIN_USERNAME', '')
- config_password = MySociety::Config.get('ADMIN_PASSWORD', '')
- if !config_username.empty? && !config_password.empty?
- authenticate_or_request_with_http_basic do |user_name, password|
- if user_name == config_username && password == config_password
- session[:using_admin] = 1
- request.env['REMOTE_USER'] = user_name
- else
- request_http_basic_authentication
+ private
+
+ def authenticate
+ if MySociety::Config.get('SKIP_ADMIN_AUTH', false)
+ session[:using_admin] = 1
+ return
+ else
+ if session[:using_admin].nil?
+ if params[:emergency].nil?
+ if authenticated?(
+ :web => _("To log into the administrative interface"),
+ :email => _("Then you can log into the administrative interface"),
+ :email_subject => _("Log into the admin interface"),
+ :user_name => "a superuser")
+ if !@user.nil? && @user.admin_level == "super"
+ session[:using_admin] = 1
+ request.env['REMOTE_USER'] = @user.url_name
+ end
+ end
+ else
+ config_username = MySociety::Config.get('ADMIN_USERNAME', '')
+ config_password = MySociety::Config.get('ADMIN_PASSWORD', '')
+ authenticate_or_request_with_http_basic do |user_name, password|
+ if user_name == config_username && password == config_password
+ session[:using_admin] = 1
+ request.env['REMOTE_USER'] = user_name
+ else
+ request_http_basic_authentication
+ end
end
end
- else
- session[:using_admin] = 1
end
- end
+ end
+ end
end
diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb
index 0b7e9bec0..2c961dfc5 100644
--- a/app/controllers/admin_general_controller.rb
+++ b/app/controllers/admin_general_controller.rb
@@ -30,8 +30,9 @@ class AdminGeneralController < AdminController
# Tasks to do
@requires_admin_requests = InfoRequest.find(:all, :select => '*, ' + InfoRequest.last_event_time_clause + ' as last_event_time', :conditions => ["described_state = 'requires_admin'"], :order => "last_event_time")
@error_message_requests = InfoRequest.find(:all, :select => '*, ' + InfoRequest.last_event_time_clause + ' as last_event_time', :conditions => ["described_state = 'error_message'"], :order => "last_event_time")
+ @attention_requests = InfoRequest.find(:all, :select => '*, ' + InfoRequest.last_event_time_clause + ' as last_event_time', :conditions => ["described_state = 'attention_requested'"], :order => "last_event_time")
@blank_contacts = PublicBody.find(:all, :conditions => ["request_email = ''"], :order => "updated_at")
- @old_unclassified = InfoRequest.find_old_unclassified(:limit => 20,
+ @old_unclassified = InfoRequest.find_old_unclassified(:limit => 20,
:conditions => ["prominence = 'normal'"])
@holding_pen_messages = InfoRequest.holding_pen_request.incoming_messages
end
@@ -78,11 +79,13 @@ class AdminGeneralController < AdminController
end
def debug
+ @http_auth_user = admin_http_auth_user
@current_commit = `git log -1 --format="%H"`
- @current_branch = `git branch | grep "\*" | awk '{print $2}'`
- repo = `git remote show origin -n | grep Fetch | awk '{print $3}' | sed -re 's/.*:(.*).git/\\1/'`
- @github_origin = "https://github.com/#{repo.strip}/tree/"
- @request_env = request.env
+ @current_branch = `git branch | perl -ne 'print $1 if /^\\* (.*)/'`
+ @current_version = `git describe --always --tags`
+ repo = `git remote show origin -n | perl -ne 'print $1 if m{Fetch URL: .*github\\.com[:/](.*)\\.git}'`
+ @github_origin = "https://github.com/#{repo}/tree/"
+ @request_env = request.env
end
end
diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb
index bf7c07905..be733ab7d 100644
--- a/app/controllers/admin_public_body_controller.rb
+++ b/app/controllers/admin_public_body_controller.rb
@@ -16,7 +16,7 @@ class AdminPublicBodyController < AdminController
def _lookup_query_internal
@locale = self.locale_from_params()
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
@query = params[:query]
if @query == ""
@query = nil
@@ -26,13 +26,13 @@ class AdminPublicBodyController < AdminController
@page = nil
end
@public_bodies = PublicBody.paginate :order => "public_body_translations.name", :page => @page, :per_page => 100,
- :conditions => @query.nil? ? "public_body_translations.locale = '#{@locale}'" :
- ["(lower(public_body_translations.name) like lower('%'||?||'%') or
- lower(public_body_translations.short_name) like lower('%'||?||'%') or
+ :conditions => @query.nil? ? "public_body_translations.locale = '#{@locale}'" :
+ ["(lower(public_body_translations.name) like lower('%'||?||'%') or
+ lower(public_body_translations.short_name) like lower('%'||?||'%') or
lower(public_body_translations.request_email) like lower('%'||?||'%' )) AND (public_body_translations.locale = '#{@locale}')", @query, @query, @query],
:joins => :translations
end
- @public_bodies_by_tag = PublicBody.find_by_tag(@query)
+ @public_bodies_by_tag = PublicBody.find_by_tag(@query)
end
def list
@@ -62,11 +62,11 @@ class AdminPublicBodyController < AdminController
def missing_scheme
# There might be a way to do this in ActiveRecord, but I can't find it
@public_bodies = PublicBody.find_by_sql("
- SELECT a.id, a.name, a.url_name, COUNT(*) AS howmany
- FROM public_bodies a JOIN info_requests r ON a.id = r.public_body_id
- WHERE a.publication_scheme = ''
- GROUP BY a.id, a.name, a.url_name
- ORDER BY howmany DESC
+ SELECT a.id, a.name, a.url_name, COUNT(*) AS howmany
+ FROM public_bodies a JOIN info_requests r ON a.id = r.public_body_id
+ WHERE a.publication_scheme = ''
+ GROUP BY a.id, a.name, a.url_name
+ ORDER BY howmany DESC
LIMIT 20
")
@stats = {
@@ -77,7 +77,7 @@ class AdminPublicBodyController < AdminController
def show
@locale = self.locale_from_params()
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
@public_body = PublicBody.find(params[:id])
render
end
@@ -87,7 +87,7 @@ class AdminPublicBodyController < AdminController
@public_body = PublicBody.new
render
end
-
+
def create
PublicBody.with_locale(I18n.default_locale) do
params[:public_body][:last_edit_editor] = admin_http_auth_user()
@@ -103,7 +103,7 @@ class AdminPublicBodyController < AdminController
def edit
@public_body = PublicBody.find(params[:id])
- @public_body.last_edit_comment = ""
+ @public_body.last_edit_comment = ""
render
end
@@ -122,7 +122,7 @@ class AdminPublicBodyController < AdminController
def destroy
@locale = self.locale_from_params()
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
public_body = PublicBody.find(params[:id])
if public_body.info_requests.size > 0
@@ -147,7 +147,7 @@ class AdminPublicBodyController < AdminController
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], params[:tag_behaviour], true, admin_http_auth_user(), I18n.available_locales)
@@ -174,7 +174,7 @@ class AdminPublicBodyController < AdminController
@errors = ""
@notes = ""
end
-
+
end
private
diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb
index e5de4f8b7..fd1405319 100644
--- a/app/controllers/admin_request_controller.rb
+++ b/app/controllers/admin_request_controller.rb
@@ -6,6 +6,8 @@
#
# $Id: admin_request_controller.rb,v 1.42 2009-10-03 01:28:33 francis Exp $
+require 'ostruct'
+
class AdminRequestController < AdminController
def index
list
@@ -24,6 +26,15 @@ class AdminRequestController < AdminController
def show
@info_request = InfoRequest.find(params[:id])
+ # XXX is this *really* the only way to render a template to a
+ # variable, rather than to the response?
+ vars = OpenStruct.new(:name_to => @info_request.user.name,
+ :name_from => MySociety::Config.get("CONTACT_NAME", 'Alaveteli'),
+ :info_request => @info_request, :reason => params[:reason],
+ :info_request_url => 'http://' + MySociety::Config.get('DOMAIN') + request_url(@info_request),
+ :site_name => site_name)
+ template = File.read(File.join(File.dirname(__FILE__), "..", "views", "admin_request", "hidden_user_explanation.rhtml"))
+ @request_hidden_user_explanation = ERB.new(template).result(vars.instance_eval { binding })
end
def resend
@@ -60,10 +71,10 @@ class AdminRequestController < AdminController
if @info_request.valid?
@info_request.save!
- @info_request.log_event("edit",
- { :editor => admin_http_auth_user(),
- :old_title => old_title, :title => @info_request.title,
- :old_prominence => old_prominence, :prominence => @info_request.prominence,
+ @info_request.log_event("edit",
+ { :editor => admin_http_auth_user(),
+ :old_title => old_title, :title => @info_request.title,
+ :old_prominence => old_prominence, :prominence => @info_request.prominence,
:old_described_state => old_described_state, :described_state => @info_request.described_state,
:old_awaiting_description => old_awaiting_description, :awaiting_description => @info_request.awaiting_description,
:old_allow_new_responses_from => old_allow_new_responses_from, :allow_new_responses_from => @info_request.allow_new_responses_from,
@@ -75,7 +86,7 @@ class AdminRequestController < AdminController
else
render :action => 'edit'
end
- end
+ end
def fully_destroy
@info_request = InfoRequest.find(params[:id])
@@ -99,28 +110,28 @@ class AdminRequestController < AdminController
outgoing_message_id = @outgoing_message.id
@outgoing_message.fully_destroy
- @outgoing_message.info_request.log_event("destroy_outgoing",
+ @outgoing_message.info_request.log_event("destroy_outgoing",
{ :editor => admin_http_auth_user(), :deleted_outgoing_message_id => outgoing_message_id })
flash[:notice] = 'Outgoing message successfully destroyed.'
redirect_to request_admin_url(@info_request)
- end
+ end
def update_outgoing
@outgoing_message = OutgoingMessage.find(params[:id])
old_body = @outgoing_message.body
- if @outgoing_message.update_attributes(params[:outgoing_message])
- @outgoing_message.info_request.log_event("edit_outgoing",
- { :outgoing_message_id => @outgoing_message.id, :editor => admin_http_auth_user(),
+ if @outgoing_message.update_attributes(params[:outgoing_message])
+ @outgoing_message.info_request.log_event("edit_outgoing",
+ { :outgoing_message_id => @outgoing_message.id, :editor => admin_http_auth_user(),
:old_body => old_body, :body => @outgoing_message.body })
flash[:notice] = 'Outgoing message successfully updated.'
redirect_to request_admin_url(@outgoing_message.info_request)
else
render :action => 'edit_outgoing'
end
- end
+ end
def edit_comment
@comment = Comment.find(params[:id])
@@ -133,9 +144,9 @@ class AdminRequestController < AdminController
old_visible = @comment.visible
@comment.visible = params[:comment][:visible] == "true" ? true : false
- if @comment.update_attributes(params[:comment])
- @comment.info_request.log_event("edit_comment",
- { :comment_id => @comment.id, :editor => admin_http_auth_user(),
+ if @comment.update_attributes(params[:comment])
+ @comment.info_request.log_event("edit_comment",
+ { :comment_id => @comment.id, :editor => admin_http_auth_user(),
:old_body => old_body, :body => @comment.body,
:old_visible => old_visible, :visible => @comment.visible,
})
@@ -144,7 +155,7 @@ class AdminRequestController < AdminController
else
render :action => 'edit_comment'
end
- end
+ end
def destroy_incoming
@@ -153,41 +164,45 @@ class AdminRequestController < AdminController
incoming_message_id = @incoming_message.id
@incoming_message.fully_destroy
- @incoming_message.info_request.log_event("destroy_incoming",
+ @incoming_message.info_request.log_event("destroy_incoming",
{ :editor => admin_http_auth_user(), :deleted_incoming_message_id => incoming_message_id })
flash[:notice] = 'Incoming message successfully destroyed.'
redirect_to request_admin_url(@info_request)
- end
+ end
def redeliver_incoming
incoming_message = IncomingMessage.find(params[:redeliver_incoming_message_id])
-
- if params[:url_title].match(/^[0-9]+$/)
- destination_request = InfoRequest.find(params[:url_title].to_i)
- else
- destination_request = InfoRequest.find_by_url_title(params[:url_title])
- end
-
- if destination_request.nil?
- flash[:error] = "Failed to find destination request '" + params[:url_title] + "'"
- redirect_to request_admin_url(incoming_message.info_request)
+ message_ids = params[:url_title].split(",").each {|x| x.strip}
+ destination_request = nil
+ ActiveRecord::Base.transaction do
+ for m in message_ids
+ if m.match(/^[0-9]+$/)
+ destination_request = InfoRequest.find_by_id(m.to_i)
+ else
+ destination_request = InfoRequest.find_by_url_title(m)
+ end
+ if destination_request.nil?
+ flash[:error] = "Failed to find destination request '" + m + "'"
+ return redirect_to request_admin_url(incoming_message.info_request)
+ end
+
+ raw_email_data = incoming_message.raw_email.data
+ mail = TMail::Mail.parse(raw_email_data)
+ mail.base64_decode
+ destination_request.receive(mail, raw_email_data, true)
+
+ incoming_message_id = incoming_message.id
+ incoming_message.info_request.log_event("redeliver_incoming", {
+ :editor => admin_http_auth_user(),
+ :destination_request => destination_request.id,
+ :deleted_incoming_message_id => incoming_message_id
+ })
+
+ flash[:notice] = "Message has been moved to request(s). Showing the last one:"
+ end
+ incoming_message.fully_destroy
end
-
- raw_email_data = incoming_message.raw_email.data
- mail = TMail::Mail.parse(raw_email_data)
- mail.base64_decode
- destination_request.receive(mail, raw_email_data, true)
-
- incoming_message_id = incoming_message.id
- incoming_message.fully_destroy
- incoming_message.info_request.log_event("redeliver_incoming", {
- :editor => admin_http_auth_user(),
- :destination_request => destination_request.id,
- :deleted_incoming_message_id => incoming_message_id
- })
-
- flash[:notice] = "Message has been moved to this request"
redirect_to request_admin_url(destination_request)
end
@@ -202,10 +217,10 @@ class AdminRequestController < AdminController
else
info_request.user = destination_user
info_request.save!
- info_request.log_event("move_request", {
- :editor => admin_http_auth_user(),
- :old_user_url_name => old_user.url_name,
- :user_url_name => destination_user.url_name
+ info_request.log_event("move_request", {
+ :editor => admin_http_auth_user(),
+ :old_user_url_name => old_user.url_name,
+ :user_url_name => destination_user.url_name
})
info_request.reindex_request_events
@@ -220,10 +235,10 @@ class AdminRequestController < AdminController
else
info_request.public_body = destination_public_body
info_request.save!
- info_request.log_event("move_request", {
- :editor => admin_http_auth_user(),
- :old_public_body_url_name => old_public_body.url_name,
- :public_body_url_name => destination_public_body.url_name
+ info_request.log_event("move_request", {
+ :editor => admin_http_auth_user(),
+ :old_public_body_url_name => old_public_body.url_name,
+ :public_body_url_name => destination_public_body.url_name
})
info_request.reindex_request_events
@@ -288,16 +303,16 @@ class AdminRequestController < AdminController
if domain.nil?
@public_bodies = []
else
- @public_bodies = PublicBody.find(:all, :order => "name",
+ @public_bodies = PublicBody.find(:all, :order => "name",
:conditions => [ "lower(request_email) like lower('%'||?||'%')", domain ])
end
-
+
# 2. Match the email address in the message without matching the hash
@info_requests = InfoRequest.guess_by_incoming_email(@raw_email.incoming_message)
# 3. Give a reason why it's in the holding pen
last_event = InfoRequestEvent.find_by_incoming_message_id(@raw_email.incoming_message.id)
- @rejected_reason = last_event.params[:rejected_reason]
+ @rejected_reason = last_event.params[:rejected_reason] || "unknown reason"
end
end
@@ -323,6 +338,33 @@ class AdminRequestController < AdminController
redirect_to request_admin_url(info_request_event.info_request)
end
+ def hide_request
+ ActiveRecord::Base.transaction do
+ subject = params[:subject]
+ explanation = params[:explanation]
+ info_request = InfoRequest.find(params[:id])
+ info_request.prominence = "requester_only"
+
+ info_request.log_event("hide", {
+ :editor => admin_http_auth_user(),
+ :reason => params[:reason],
+ :subject => subject,
+ :explanation => explanation
+ })
+
+ info_request.set_described_state(params[:reason])
+ info_request.save!
+
+ ContactMailer.deliver_from_admin_message(
+ info_request.user,
+ subject,
+ params[:explanation]
+ )
+ flash[:notice] = _("Your message to {{recipient_user_name}} has been sent",:recipient_user_name=>CGI.escapeHTML(info_request.user.name))
+ redirect_to request_admin_url(info_request)
+ end
+ end
+
private
end
diff --git a/app/controllers/admin_user_controller.rb b/app/controllers/admin_user_controller.rb
index b2c084739..4059ac0bb 100644
--- a/app/controllers/admin_user_controller.rb
+++ b/app/controllers/admin_user_controller.rb
@@ -15,7 +15,7 @@ class AdminUserController < AdminController
def list
@query = params[:query]
@admin_users = User.paginate :order => "name", :page => params[:page], :per_page => 100,
- :conditions => @query.nil? ? nil : ["lower(name) like lower('%'||?||'%') or
+ :conditions => @query.nil? ? nil : ["lower(name) like lower('%'||?||'%') or
lower(email) like lower('%'||?||'%')", @query, @query]
end
@@ -28,7 +28,7 @@ class AdminUserController < AdminController
# Don't use @user as that is any logged in user
@admin_user = User.find(params[:id])
end
-
+
def show_bounce_message
@admin_user = User.find(params[:id])
end
@@ -54,7 +54,7 @@ class AdminUserController < AdminController
else
render :action => 'edit'
end
- end
+ end
def destroy_track
track_thing = TrackThing.find(params[:track_id].to_i)
@@ -62,7 +62,7 @@ class AdminUserController < AdminController
flash[:notice] = 'Track destroyed'
redirect_to user_admin_url(track_thing.tracking_user)
end
-
+
def clear_bounce
user = User.find(params[:id])
user.email_bounced_at = nil
@@ -74,10 +74,9 @@ class AdminUserController < AdminController
def login_as
@admin_user = User.find(params[:id]) # check user does exist
- post_redirect = PostRedirect.new( :uri => main_url(user_url(@admin_user)), :user_id => @admin_user.id)
+ post_redirect = PostRedirect.new( :uri => main_url(user_url(@admin_user)), :user_id => @admin_user.id, :circumstance => "login_as" )
post_redirect.save!
url = main_url(confirm_url(:email_token => post_redirect.email_token, :only_path => true))
- session[:user_id] = nil # Log out current (usually admin) user, so we get logged in as the other user
redirect_to url
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b681f455d..41adf1848 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# controllers/application.rb:
# Parent class of all controllers in FOI site. Filters added to this controller
# apply to all controllers in the application. Likewise, all the methods added
@@ -19,7 +20,7 @@ class ApplicationController < ActionController::Base
# Send notification email on exceptions
include ExceptionNotification::Notifiable
-
+
# Note: a filter stops the chain if it redirects or renders something
before_filter :authentication_check
before_filter :set_gettext_locale
@@ -33,7 +34,7 @@ class ApplicationController < ActionController::Base
def set_vary_header
response.headers['Vary'] = 'Cookie'
end
-
+
helper_method :anonymous_cache, :short_cache, :medium_cache, :long_cache
def anonymous_cache(time)
if session[:user_id].nil?
@@ -117,8 +118,20 @@ class ApplicationController < ActionController::Base
# Override default error handler, for production sites.
def rescue_action_in_public(exception)
+ # Call `set_view_paths` from the theme, if it exists.
+ # Normally, this is called by the theme itself in a
+ # :before_filter, but when there's an error, this doesn't
+ # happen. By calling it here, we can ensure error pages are
+ # still styled according to the theme.
+ begin
+ set_view_paths
+ rescue NameError => e
+ if !(e.message =~ /undefined local variable or method `set_view_paths'/)
+ raise
+ end
+ end
# Make sure expiry time for session is set (before_filters are
- # otherwise missed by this override)
+ # otherwise missed by this override)
session_remember_me
case exception
when ActiveRecord::RecordNotFound, ActionController::UnknownAction, ActionController::RoutingError
@@ -140,19 +153,19 @@ class ApplicationController < ActionController::Base
alias original_rescue_action_locally rescue_action_locally
def rescue_action_locally(exception)
# Make sure expiry time for session is set (before_filters are
- # otherwise missed by this override)
+ # otherwise missed by this override)
session_remember_me
# Display default, detailed error for developers
original_rescue_action_locally(exception)
end
-
+
def local_request?
false
end
- # Called from test code, is a mimic of User.confirm, for use in following email
- # links when in controller tests (since we don't have full integration tests that
+ # Called from test code, is a mimic of UserController.confirm, for use in following email
+ # links when in controller tests (though we also have full integration tests that
# can work over multiple controllers)
def test_code_redirect_by_email_token(token, controller_example_group)
post_redirect = PostRedirect.find_by_email_token(token)
@@ -178,7 +191,7 @@ class ApplicationController < ActionController::Base
end
def foi_fragment_cache_path(param)
- path = File.join(RAILS_ROOT, 'cache', 'views', foi_fragment_cache_part_path(param))
+ path = File.join(Rails.root, 'cache', 'views', foi_fragment_cache_part_path(param))
max_file_length = 255 - 35 # we subtract 35 because tempfile
# adds on a variable number of
# characters
@@ -189,7 +202,7 @@ class ApplicationController < ActionController::Base
# return stub path so admin can expire it
first_three_digits = info_request.id.to_s()[0..2]
path = "views/request/#{first_three_digits}/#{info_request.id}"
- foi_cache_path = File.join(File.dirname(__FILE__), '../../cache')
+ foi_cache_path = File.expand_path(File.join(File.dirname(__FILE__), '../../cache'))
return File.join(foi_cache_path, path)
end
def foi_fragment_cache_exists?(key_path)
@@ -207,7 +220,7 @@ class ApplicationController < ActionController::Base
end
end
- # get the local locale
+ # get the local locale
def locale_from_params(*args)
if params[:show_locale]
params[:show_locale]
@@ -224,15 +237,15 @@ class ApplicationController < ActionController::Base
post_redirect = PostRedirect.new(:uri => request.request_uri, :post_params => params,
:reason_params => reason_params)
post_redirect.save!
- # 'modal' controls whether the sign-in form will be displayed in the typical full-blown
- # page or on its own, useful for pop-ups
+ # 'modal' controls whether the sign-in form will be displayed in the typical full-blown
+ # page or on its own, useful for pop-ups
redirect_to signin_url(:token => post_redirect.token, :modal => params[:modal])
return false
end
return true
end
- def authenticated_as_user?(user, reason_params)
+ def authenticated_as_user?(user, reason_params)
reason_params[:user_name] = user.name
reason_params[:user_url] = show_user_url(:url_name => user.url_name)
if session[:user_id]
@@ -274,6 +287,8 @@ class ApplicationController < ActionController::Base
# XXX what is the built in Ruby URI munging function that can do this
# choice of & vs. ? more elegantly than this dumb if statement?
if uri.include?("?")
+ # XXX This looks odd. What would a fragment identifier be doing server-side?
+ # But it also looks harmless, so I’ll leave it just in case.
if uri.include?("#")
uri.sub!("#", "&post_redirect=1#")
else
@@ -294,6 +309,7 @@ class ApplicationController < ActionController::Base
if params[:post_redirect] and session[:post_redirect_token]
post_redirect = PostRedirect.find_by_token(session[:post_redirect_token])
params.update(post_redirect.post_params)
+ params[:post_redirect_user] = post_redirect.user
end
end
@@ -304,7 +320,7 @@ class ApplicationController < ActionController::Base
end
end
- #
+ #
def check_read_only
read_only = MySociety::Config.get('READ_ONLY', '')
if !read_only.empty?
@@ -329,11 +345,8 @@ class ApplicationController < ActionController::Base
return "*unknown*";
end
end
- def assign_http_auth_user
- @http_auth_user = admin_http_auth_user
- end
- # Convert URL name for sort by order, to Xapian query
+ # Convert URL name for sort by order, to Xapian query
def order_to_sort_by(sortby)
if sortby.nil?
return [nil, nil]
@@ -349,7 +362,7 @@ class ApplicationController < ActionController::Base
end
# Function for search
- def perform_search(models, query, sortby, collapse, per_page = 25, this_page = nil)
+ def perform_search(models, query, sortby, collapse, per_page = 25, this_page = nil)
@query = query
@sortby = sortby
@@ -385,7 +398,7 @@ class ApplicationController < ActionController::Base
collapse = 'request_collapse'
end
options = {
- :offset => (@page - 1) * @per_page,
+ :offset => (@page - 1) * @per_page,
:limit => @per_page,
:sort_by_prefix => nil,
:sort_by_ascending => true,
@@ -404,7 +417,7 @@ class ApplicationController < ActionController::Base
if e.message =~ /^QueryParserError: Wildcard/
# Wildcard expands to too many terms
logger.info "Wildcard query '#{query.strip + '*'}' caused: #{e.message}"
-
+
user_query = ActsAsXapian.query_parser.parse_query(
query,
Xapian::QueryParser::FLAG_LOVEHATE |
@@ -433,8 +446,8 @@ class ApplicationController < ActionController::Base
def param_exists(item)
return params[item] && !params[item].empty?
- end
-
+ end
+
def get_request_variety_from_params
query = ""
sortby = "newest"
@@ -459,7 +472,7 @@ class ApplicationController < ActionController::Base
def get_status_from_params
query = ""
- if params[:latest_status]
+ if params[:latest_status]
statuses = []
if params[:latest_status].class == String
params[:latest_status] = [params[:latest_status]]
@@ -510,7 +523,7 @@ class ApplicationController < ActionController::Base
query = ""
tags = []
if param_exists(:tags)
- params[:tags].split().each do |tag|
+ params[:tags].split().each do |tag|
tags << "tag:#{tag}"
end
end
@@ -519,7 +532,7 @@ class ApplicationController < ActionController::Base
end
return query
end
-
+
def make_query_from_params
query = params[:query] || "" if query.nil?
query += get_date_range_from_params
@@ -540,16 +553,6 @@ class ApplicationController < ActionController::Base
return country
end
- def quietly_try_to_open(url)
- begin
- result = open(url).read.strip
- rescue OpenURI::HTTPError, SocketError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
- logger.warn("Unable to open third-party URL #{url}")
- result = ""
- end
- return result
- end
-
# URL generating functions are needed by all controllers (for redirects),
# views (for links) and mailers (for use in emails), so include them into
# all of all.
diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb
index 86d5b0a06..d9cd002dd 100644
--- a/app/controllers/comment_controller.rb
+++ b/app/controllers/comment_controller.rb
@@ -9,14 +9,14 @@
class CommentController < ApplicationController
before_filter :check_read_only, :only => [ :new ]
protect_from_forgery :only => [ :new ]
-
+
def new
if params[:type] == 'request'
@info_request = InfoRequest.find_by_url_title(params[:url_title])
@track_thing = TrackThing.create_track_for_request(@info_request)
if params[:comment]
@comment = Comment.new(params[:comment].merge({
- :comment_type => 'request',
+ :comment_type => 'request',
:user => @user
}))
end
@@ -38,7 +38,7 @@ class CommentController < ApplicationController
# Default to subscribing to request when first viewing form
params[:subscribe_to_request] = true
end
-
+
# See if values were valid or not
if !params[:comment] || !@existing_comment.nil? || !@comment.valid? || params[:reedit]
render :action => 'new'
diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb
index 82b1b8629..6e89a2832 100644
--- a/app/controllers/general_controller.rb
+++ b/app/controllers/general_controller.rb
@@ -28,19 +28,19 @@ class GeneralController < ApplicationController
@locale = self.locale_from_params()
locale_condition = 'public_body_translations.locale = ?'
conditions = [locale_condition, @locale]
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
if body_short_names.empty?
# This is too slow
- @popular_bodies = PublicBody.find(:all,
- :select => "public_bodies.*, (select count(*) from info_requests where info_requests.public_body_id = public_bodies.id) as c",
- :order => "c desc",
+ @popular_bodies = PublicBody.find(:all,
+ :select => "public_bodies.*, (select count(*) from info_requests where info_requests.public_body_id = public_bodies.id) as c",
+ :order => "c desc",
:limit => 32,
:conditions => conditions,
:joins => :translations
)
else
conditions[0] += " and public_bodies.url_name in (" + body_short_names + ")"
- @popular_bodies = PublicBody.find(:all,
+ @popular_bodies = PublicBody.find(:all,
:conditions => conditions,
:joins => :translations)
end
@@ -52,7 +52,7 @@ class GeneralController < ApplicationController
max_count = 5
xapian_object = perform_search([InfoRequestEvent], query, sortby, 'request_title_collapse', max_count)
@request_events = xapian_object.results.map { |r| r[:model] }
-
+
# If there are not yet enough successful requests, fill out the list with
# other requests
if @request_events.count < max_count
@@ -97,7 +97,7 @@ class GeneralController < ApplicationController
query_parts = @query.split("/")
if !['bodies', 'requests', 'users', 'all'].include?(query_parts[-1])
redirect_to search_url([@query, "all"], params)
- else
+ else
redirect_to search_url(@query, params)
end
end
@@ -236,4 +236,4 @@ class GeneralController < ApplicationController
end
-
+
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index b08438b52..e3b77271e 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -9,7 +9,7 @@
class HelpController < ApplicationController
# we don't even have a control subroutine for most help pages, just see their templates
-
+
before_filter :long_cache
def unhappy
@@ -61,7 +61,7 @@ class HelpController < ApplicationController
@last_request, @last_body
)
flash[:notice] = _("Your message has been sent. Thank you for getting in touch! We'll get back to you soon.")
- redirect_to frontpage_url
+ redirect_to frontpage_url
return
end
@@ -69,7 +69,7 @@ class HelpController < ApplicationController
@contact.errors.clear
end
end
-
+
end
end
diff --git a/app/controllers/holiday_controller.rb b/app/controllers/holiday_controller.rb
index 916ff54c8..7f62aa26d 100644
--- a/app/controllers/holiday_controller.rb
+++ b/app/controllers/holiday_controller.rb
@@ -1,5 +1,5 @@
# app/controllers/holiday_controller.rb:
-# Calculate dates
+# Calculate dates
#
# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved.
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
@@ -16,7 +16,7 @@ class HolidayController < ApplicationController
@request_date = Date.strptime(params[:holiday]) or raise "Invalid date"
@due_date = Holiday.due_date_from(@request_date, 20)
@skipped = Holiday.all(
- :conditions => [ 'day >= ? AND day <= ?',
+ :conditions => [ 'day >= ? AND day <= ?',
@request_date.strftime("%F"), @due_date.strftime("%F")
]
).collect { |h| h.day }.sort
diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb
index 00d1cc1e0..95d936e54 100644
--- a/app/controllers/public_body_controller.rb
+++ b/app/controllers/public_body_controller.rb
@@ -14,23 +14,23 @@ class PublicBodyController < ApplicationController
def show
long_cache
if MySociety::Format.simplify_url_part(params[:url_name], 'body') != params[:url_name]
- redirect_to :url_name => MySociety::Format.simplify_url_part(params[:url_name], 'body'), :status => :moved_permanently
+ redirect_to :url_name => MySociety::Format.simplify_url_part(params[:url_name], 'body'), :status => :moved_permanently
return
end
@locale = self.locale_from_params()
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
@public_body = PublicBody.find_by_url_name_with_historic(params[:url_name])
raise ActiveRecord::RecordNotFound.new("None found") if @public_body.nil?
if @public_body.url_name.nil?
redirect_to :back
return
- end
+ end
# If found by historic name, or alternate locale name, redirect to new name
if @public_body.url_name != params[:url_name]
- redirect_to show_public_body_url(:url_name => @public_body.url_name)
+ redirect_to show_public_body_url(:url_name => @public_body.url_name)
return
end
-
+
set_last_body(@public_body)
top_url = main_url("/")
@@ -50,8 +50,8 @@ class PublicBodyController < ApplicationController
begin
@xapian_requests = perform_search([InfoRequestEvent], query, sortby, 'request_collapse')
if (@page > 1)
- @page_desc = " (page " + @page.to_s + ")"
- else
+ @page_desc = " (page " + @page.to_s + ")"
+ else
@page_desc = ""
end
rescue
@@ -65,7 +65,7 @@ class PublicBodyController < ApplicationController
format.html { @has_json = true; render :template => "public_body/show"}
format.json { render :json => @public_body.json_for_api }
end
-
+
end
end
@@ -93,8 +93,8 @@ class PublicBodyController < ApplicationController
@tag = params[:tag]
@locale = self.locale_from_params()
default_locale = I18n.default_locale.to_s
- locale_condition = "(upper(public_body_translations.name) LIKE upper(?)
- OR upper(public_body_translations.notes) LIKE upper (?))
+ locale_condition = "(upper(public_body_translations.name) LIKE upper(?)
+ OR upper(public_body_translations.notes) LIKE upper (?))
AND public_body_translations.locale = ?
AND public_bodies.id <> #{PublicBody.internal_admin_body.id}"
if @tag.nil? or @tag == "all"
@@ -152,10 +152,10 @@ class PublicBodyController < ApplicationController
report = StringIO.new
CSV::Writer.generate(report, ',') do |title|
title << [
- 'Name',
+ 'Name',
'Short name',
# deliberately not including 'Request email'
- 'URL name',
+ 'URL name',
'Tags',
'Home page',
'Publication scheme',
@@ -164,12 +164,12 @@ class PublicBodyController < ApplicationController
'Version',
]
public_bodies.each do |public_body|
- title << [
- public_body.name,
- public_body.short_name,
+ 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.url_name,
public_body.tag_string,
public_body.calculated_home_page,
public_body.publication_scheme,
@@ -181,7 +181,7 @@ class PublicBodyController < ApplicationController
end
report.rewind
send_data(report.read, :type=> 'text/csv; charset=utf-8; header=present',
- :filename => 'all-authorities.csv',
+ :filename => 'all-authorities.csv',
:disposition =>'attachment', :encoding => 'utf8')
end
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index 313a57d7d..2f5b4d643 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -16,7 +16,7 @@ class RequestController < ApplicationController
MAX_RESULTS = 500
PER_PAGE = 25
-
+
@@custom_states_loaded = false
begin
if ENV["RAILS_ENV"] != "test"
@@ -44,11 +44,17 @@ class RequestController < ApplicationController
end
medium_cache
end
-
+
def show
- medium_cache
+ if !MySociety::Config.get('VARNISH_HOST').nil?
+ # If varnish is set up to accept PURGEs, then cache for a
+ # long time
+ long_cache
+ else
+ medium_cache
+ end
@locale = self.locale_from_params()
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
# Look up by old style numeric identifiers
if params[:url_title].match(/^[0-9]+$/)
@@ -57,7 +63,7 @@ class RequestController < ApplicationController
return
end
- # Look up by new style text names
+ # Look up by new style text names
@info_request = InfoRequest.find_by_url_title(params[:url_title])
if @info_request.nil?
raise ActiveRecord::RecordNotFound.new("Request not found")
@@ -69,7 +75,7 @@ class RequestController < ApplicationController
render :template => 'request/hidden', :status => 410 # gone
return
end
-
+
# Other parameters
@info_request_events = @info_request.info_request_events
@status = @info_request.calculate_status
@@ -77,7 +83,7 @@ class RequestController < ApplicationController
@update_status = params[:update_status] ? true : false
@old_unclassified = @info_request.is_old_unclassified? && !authenticated_user.nil?
@is_owning_user = @info_request.is_owning_user?(authenticated_user)
-
+
if @update_status
return if !@is_owning_user && !authenticated_as_user?(@info_request.user,
:web => _("To update the status of this FOI request"),
@@ -85,7 +91,7 @@ class RequestController < ApplicationController
:email_subject => _("Update the status of your request to ") + @info_request.public_body.name
)
end
-
+
@last_info_request_event_id = @info_request.last_event_id_needing_description
@new_responses_count = @info_request.events_needing_description.select {|i| i.event_type == 'response'}.size
@@ -95,14 +101,14 @@ class RequestController < ApplicationController
behavior_cache :tag => ['similar', @info_request.id] do
begin
limit = 10
- @xapian_similar = ::ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events,
+ @xapian_similar = ::ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events,
:limit => limit, :collapse_by_prefix => 'request_collapse')
@xapian_similar_more = (@xapian_similar.matches_estimated > limit)
rescue
@xapian_similar = nil
end
end
-
+
# Track corresponding to this page
@track_thing = TrackThing.create_track_for_request(@info_request)
@feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ]
@@ -122,7 +128,7 @@ class RequestController < ApplicationController
@info_request = InfoRequest.find_by_url_title(params[:url_title])
if @info_request.nil?
raise ActiveRecord::RecordNotFound.new("Request not found")
- else
+ else
if !@info_request.user_can_view?(authenticated_user)
render :template => 'request/hidden', :status => 410 # gone
return
@@ -137,16 +143,18 @@ class RequestController < ApplicationController
@per_page = 25
@page = (params[:page] || "1").to_i
@info_request = InfoRequest.find_by_url_title(params[:url_title])
+ raise ActiveRecord::RecordNotFound.new("Request not found") if @info_request.nil?
+
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,
+ @xapian_object = ::ActsAsXapian::Similar.new([InfoRequestEvent], @info_request.info_request_events,
:offset => (@page - 1) * @per_page, :limit => @per_page, :collapse_by_prefix => 'request_collapse')
-
+
if (@page > 1)
- @page_desc = " (page " + @page.to_s + ")"
- else
+ @page_desc = " (page " + @page.to_s + ")"
+ else
@page_desc = ""
end
end
@@ -158,7 +166,7 @@ class RequestController < ApplicationController
if @view == "recent"
return redirect_to request_list_all_path(:action => "list", :view => "all", :page => @page), :status => :moved_permanently
end
-
+
# Later pages are very expensive to load
if @page > MAX_RESULTS / PER_PAGE
raise ActiveRecord::RecordNotFound.new("Sorry. No pages after #{MAX_RESULTS / PER_PAGE}.")
@@ -168,14 +176,14 @@ class RequestController < ApplicationController
query = make_query_from_params
@title = _("View and search requests")
sortby = "newest"
- @cache_tag = Digest::MD5.hexdigest(query + @page.to_s)
+ @cache_tag = Digest::MD5.hexdigest(query + @page.to_s + I18n.locale.to_s)
behavior_cache :tag => [@cache_tag] do
xapian_object = perform_search([InfoRequestEvent], query, sortby, 'request_collapse')
@list_results = xapian_object.results.map { |r| r[:model] }
@matches_estimated = xapian_object.matches_estimated
@show_no_more_than = (@matches_estimated > MAX_RESULTS) ? MAX_RESULTS : @matches_estimated
end
-
+
@title = @title + " (page " + @page.to_s + ")" if (@page > 1)
@track_thing = TrackThing.create_track_for_search_query(query)
@feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ]
@@ -199,7 +207,7 @@ class RequestController < ApplicationController
# get_undescribed_requests also allows one day since the response
# arrived.
if !@user.nil? && params[:submitted_new_request].nil? && !@user.can_leave_requests_undescribed?
- @undescribed_requests = @user.get_undescribed_requests
+ @undescribed_requests = @user.get_undescribed_requests
if @undescribed_requests.size > 1
render :action => 'new_please_describe'
return
@@ -245,7 +253,7 @@ class RequestController < ApplicationController
elsif params[:public_body_id]
params[:info_request][:public_body_id] = params[:public_body_id]
end
- if !params[:info_request][:public_body_id]
+ if !params[:info_request][:public_body_id]
# compulsory to have a body by here, or go to front page which is start of process
redirect_to frontpage_url
return
@@ -263,7 +271,7 @@ class RequestController < ApplicationController
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.is_requestable?
render :action => 'new'
else
@@ -286,8 +294,8 @@ class RequestController < ApplicationController
# Create both FOI request and the first request message
@info_request = InfoRequest.new(params[:info_request])
- @outgoing_message = OutgoingMessage.new(params[:outgoing_message].merge({
- :status => 'ready',
+ @outgoing_message = OutgoingMessage.new(params[:outgoing_message].merge({
+ :status => 'ready',
:message_type => 'initial_request'
}))
@info_request.outgoing_messages << @outgoing_message
@@ -312,7 +320,7 @@ class RequestController < ApplicationController
if params[:preview].to_i == 1
message = ""
if @outgoing_message.contains_email?
- if @user.nil?
+ if @user.nil?
message += _("<p>You do not need to include your email in the request in order to get a reply, as we will ask for it on the next screen (<a href=\"%s\">details</a>).</p>") % [help_privacy_path+"#email_address"];
else
message += _("<p>You do not need to include your email in the request in order to get a reply (<a href=\"%s\">details</a>).</p>") % [help_privacy_path+"#email_address"];
@@ -344,7 +352,13 @@ class RequestController < ApplicationController
return
end
- @info_request.user = authenticated_user
+ if params[:post_redirect_user]
+ # If an admin has clicked the confirmation link on a users behalf,
+ # we don’t want to reassign the request to the administrator.
+ @info_request.user = params[:post_redirect_user]
+ else
+ @info_request.user = authenticated_user
+ end
# This automatically saves dependent objects, such as @outgoing_message, in the same transaction
@info_request.save!
# XXX send_message needs the database id, so we send after saving, which isn't ideal if the request broke here.
@@ -352,7 +366,7 @@ class RequestController < ApplicationController
flash[:notice] = _("<p>Your {{law_used_full}} request has been <strong>sent on its way</strong>!</p>
<p><strong>We will email you</strong> when there is a response, or after {{late_number_of_days}} working days if the authority still hasn't
replied by then.</p>
- <p>If you write about this request (for example in a forum or a blog) please link to this page, and add an
+ <p>If you write about this request (for example in a forum or a blog) please link to this page, and add an
annotation below telling people about your writing.</p>",:law_used_full=>@info_request.law_used_full,
:late_number_of_days => MySociety::Config.get('REPLY_LATE_AFTER_DAYS', 20))
redirect_to show_new_request_path(:url_title => @info_request.url_title)
@@ -369,10 +383,10 @@ class RequestController < ApplicationController
return
end
- @is_owning_user = @info_request.is_owning_user?(authenticated_user)
+ @is_owning_user = @info_request.is_owning_user?(authenticated_user)
@last_info_request_event_id = @info_request.last_event_id_needing_description
@old_unclassified = @info_request.is_old_unclassified? && !authenticated_user.nil?
-
+
# Check authenticated, and parameters set. We check is_owning_user
# to get admin overrides (see is_owning_user? above)
if !@old_unclassified && !@is_owning_user && !authenticated_as_user?(@info_request.user,
@@ -399,7 +413,7 @@ class RequestController < ApplicationController
# Make the state change
old_described_state = @info_request.described_state
@info_request.set_described_state(params[:incoming_message][:described_state])
-
+
# If you're not the *actual* requester owner. e.g. you are playing the
# classification game, or you're doing this just because you are an
# admin user (not because you also own the request).
@@ -408,24 +422,24 @@ class RequestController < ApplicationController
# don't log if you were the requester XXX This is presumably so you
# don't score for classifying your own requests. Could instead
# always log and filter at display time.
- @info_request.log_event("status_update",
- { :user_id => authenticated_user.id,
- :old_described_state => old_described_state,
+ @info_request.log_event("status_update",
+ { :user_id => authenticated_user.id,
+ :old_described_state => old_described_state,
:described_state => @info_request.described_state,
})
-
+
# Don't give advice on what to do next, as it isn't their request
RequestMailer.deliver_old_unclassified_updated(@info_request)
- if session[:request_game]
+ if session[:request_game]
flash[:notice] = _('Thank you for updating the status of the request \'<a href="{{url}}">{{info_request_title}}</a>\'. There are some more requests below for you to classify.',:info_request_title=>CGI.escapeHTML(@info_request.title), :url=>CGI.escapeHTML(request_url(@info_request)))
- redirect_to play_url
+ redirect_to play_url
else
flash[:notice] = _('Thank you for updating this request!')
redirect_to request_url(@info_request)
end
return
end
-
+
# 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>
@@ -441,14 +455,14 @@ class RequestController < ApplicationController
flash[:notice] = _("<p>Thank you! Here are some ideas on what to do next:</p>
<ul>
<li>To send your request to another authority, first copy the text of your request below, then <a href=\"{{find_authority_url}}\">find the other authority</a>.</li>
- <li>If you would like to contest the authority's claim that they do not hold the information, here is
+ <li>If you would like to contest the authority's claim that they do not hold the information, here is
<a href=\"{{complain_url}}\">how to complain</a>.
</li>
<li>We have <a href=\"{{other_means_url}}\">suggestions</a>
on other means to answer your question.
</li>
- </ul>",
- :find_authority_url => "/new",
+ </ul>",
+ :find_authority_url => "/new",
:complain_url => CGI.escapeHTML(unhappy_url(@info_request)),
:other_means_url => CGI.escapeHTML(unhappy_url(@info_request)) + "#other_means")
redirect_to request_url(@info_request)
@@ -487,7 +501,7 @@ class RequestController < ApplicationController
end
end
- # Used for links from polymorphic URLs e.g. in Atom feeds - just redirect to
+ # Used for links from polymorphic URLs e.g. in Atom feeds - just redirect to
# proper URL for the message the event refers to
def show_request_event
@info_request_event = InfoRequestEvent.find(params[:info_request_event_id])
@@ -497,8 +511,8 @@ class RequestController < ApplicationController
redirect_to outgoing_message_url(@info_request_event.outgoing_message), :status => :moved_permanently
else
# XXX maybe there are better URLs for some events than this
- redirect_to request_url(@info_request_event.info_request), :status => :moved_permanently
- end
+ redirect_to request_url(@info_request_event.info_request), :status => :moved_permanently
+ end
end
# Show an individual incoming message, and allow followup
@@ -542,8 +556,8 @@ class RequestController < ApplicationController
if params_outgoing_message.nil?
params_outgoing_message = {}
end
- params_outgoing_message.merge!({
- :status => 'ready',
+ params_outgoing_message.merge!({
+ :status => 'ready',
:message_type => 'followup',
:incoming_message_followup => @incoming_message,
:info_request_id => @info_request.id
@@ -567,7 +581,7 @@ class RequestController < ApplicationController
render :template => 'request/hidden', :status => 410 # gone
return
end
-
+
# Check address is good
if !OutgoingMailer.is_followupable?(@info_request, @incoming_message)
raise "unexpected followupable inconsistency" if @info_request.public_body.is_requestable?
@@ -580,7 +594,7 @@ class RequestController < ApplicationController
# to make sure they're the right user first, before they start writing a
# message and wasting their time if they are not the requester.
if !authenticated_as_user?(@info_request.user,
- :web => @incoming_message.nil? ?
+ :web => @incoming_message.nil? ?
_("To send a follow up message to ") + @info_request.public_body.name :
_("To reply to ") + @info_request.public_body.name,
:email => @incoming_message.nil? ?
@@ -645,6 +659,25 @@ class RequestController < ApplicationController
end
end
+ def report_request
+ info_request = InfoRequest.find_by_url_title(params[:url_title])
+ return if !authenticated?(
+ :web => _("To report this FOI request"),
+ :email => _("Then you can report the request '{{title}}'", :title => info_request.title),
+ :email_subject => _("Report an offensive or unsuitable request")
+ )
+
+ if !info_request.attention_requested
+ info_request.set_described_state('attention_requested', @user)
+ info_request.attention_requested = true # tells us if attention has ever been requested
+ info_request.save!
+ flash[:notice] = _("This request has been reported for administrator attention")
+ else
+ flash[:notice] = _("This request has already been reported for administrator attention")
+ end
+ redirect_to request_url(info_request)
+ end
+
# special caching code so mime types are handled right
around_filter :cache_attachments, :only => [ :get_attachment, :get_attachment_as_html ]
def cache_attachments
@@ -678,7 +711,7 @@ class RequestController < ApplicationController
# Prevent spam to magic request address. Note that the binary
# subsitution method used depends on the content type
- @incoming_message.binary_mask_stuff!(@attachment.body, @attachment.content_type)
+ @incoming_message.binary_mask_stuff!(@attachment.body, @attachment.content_type)
# we don't use @attachment.content_type here, as we want same mime type when cached in cache_attachments above
response.content_type = AlaveteliFileTypes.filename_to_mimetype(params[:file_name].join("/")) || 'application/octet-stream'
@@ -706,7 +739,7 @@ class RequestController < ApplicationController
html.sub!("<prefix-here>", view_html_prefix)
html.sub!("<attachment-url-here>", CGI.escape(@attachment_url))
- @incoming_message.html_mask_stuff!(html)
+ @incoming_message.html_mask_stuff!(html)
response.content_type = 'text/html'
render :text => html
end
@@ -731,7 +764,7 @@ class RequestController < ApplicationController
else
@original_filename = @filename
end
-
+
# check permissions
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)
@@ -748,7 +781,7 @@ class RequestController < ApplicationController
# FOI officers can upload a response
def upload_response
@locale = self.locale_from_params()
- PublicBody.with_locale(@locale) do
+ PublicBody.with_locale(@locale) do
@info_request = InfoRequest.find_by_url_title(params[:url_title])
@reason_params = {
@@ -817,8 +850,8 @@ class RequestController < ApplicationController
)
updated = Digest::SHA1.hexdigest(info_request.get_last_event.created_at.to_i.to_s + info_request.updated_at.to_i.to_s)
@url_path = "/download/#{updated[0..1]}/#{updated}/#{params[:url_title]}.zip"
- file_path = File.join(File.dirname(__FILE__), '../../cache/zips', @url_path)
- if !File.exists?(file_path)
+ file_path = File.expand_path(File.join(File.dirname(__FILE__), '../../cache/zips', @url_path))
+ if !File.exists?(file_path)
FileUtils.mkdir_p(File.dirname(file_path))
Zip::ZipFile.open(file_path, Zip::ZipFile::CREATE) { |zipfile|
convert_command = MySociety::Config.get("HTML_TO_PDF_COMMAND")
@@ -837,7 +870,7 @@ class RequestController < ApplicationController
logger.error("Could not convert info request #{info_request.id} to PDF with command '#{convert_command} #{url} #{tempfile.path}'")
end
tempfile.close
- else
+ else
logger.warn("No HTML -> PDF converter found at #{convert_command}")
end
if !done
@@ -849,7 +882,7 @@ class RequestController < ApplicationController
f.puts(output)
}
end
- for message in info_request.incoming_messages
+ for message in info_request.incoming_messages
attachments = message.get_attachments_for_display
for attachment in attachments
filename = "#{attachment.url_part_number}_#{attachment.display_filename}"
diff --git a/app/controllers/request_game_controller.rb b/app/controllers/request_game_controller.rb
index 8a84575bb..904c44759 100644
--- a/app/controllers/request_game_controller.rb
+++ b/app/controllers/request_game_controller.rb
@@ -7,7 +7,7 @@
# $Id: request_game_controller.rb,v 1.9 2009-10-19 22:06:54 francis Exp $
class RequestGameController < ApplicationController
-
+
def play
session[:request_game] = Time.now
@@ -20,7 +20,7 @@ class RequestGameController < ApplicationController
@requests = old.sort_by{ rand }.slice(0..2)
if @missing == 0
- flash[:notice] = _('<p>All done! Thank you very much for your help.</p><p>There are <a href="{{helpus_url}}">more things you can do</a> to help {{site_name}}.</p>',
+ flash[:notice] = _('<p>All done! Thank you very much for your help.</p><p>There are <a href="{{helpus_url}}">more things you can do</a> to help {{site_name}}.</p>',
:helpus_url => help_credits_path+"#helpus",
:site_name => site_name)
end
@@ -38,7 +38,7 @@ class RequestGameController < ApplicationController
url_title = params[:url_title]
if !authenticated?(
:web => _("To play the request categorisation game"),
- :email => _("Then you can play the request categorisation game."),
+ :email => _("Then you can play the request categorisation game."),
:email_subject => _("Play the request categorisation game")
)
# do nothing - as "authenticated?" has done the redirect to signin page for us
diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb
index 225790d71..00c0e61bd 100644
--- a/app/controllers/services_controller.rb
+++ b/app/controllers/services_controller.rb
@@ -9,16 +9,30 @@ class ServicesController < ApplicationController
if country_from_ip.downcase != iso_country_code
found_country = WorldFOIWebsites.by_code(country_from_ip)
found_country_name = !found_country.nil? && found_country[:country_name]
+ old_locale = FastGettext.locale
+ FastGettext.locale = FastGettext.best_locale_in(request.env['HTTP_ACCEPT_LANGUAGE'])
if found_country_name
text = _("Hello! You can make Freedom of Information requests within {{country_name}} at {{link_to_website}}", :country_name => found_country_name, :link_to_website => "<a href=\"#{found_country[:url]}\">#{found_country[:name]}</a>")
else
current_country = WorldFOIWebsites.by_code(iso_country_code)[:country_name]
text = _("Hello! We have an <a href=\"/help/alaveteli?country_name=#{CGI.escape(current_country)}\">important message</a> for visitors outside {{country_name}}", :country_name => current_country)
end
+ FastGettext.locale = old_locale
end
if !text.empty?
text += ' <span class="close-button">X</span>'
end
render :text => text, :content_type => "text/plain" # XXX workaround the HTML validation in test suite
end
+ def hidden_user_explanation
+ info_request = InfoRequest.find(params[:info_request_id])
+ render :template => "admin_request/hidden_user_explanation",
+ :content_type => "text/plain",
+ :layout => false,
+ :locals => {:name_to => info_request.user.name,
+ :name_from => MySociety::Config.get("CONTACT_NAME", 'Alaveteli'),
+ :info_request => info_request, :reason => params[:reason],
+ :info_request_url => 'http://' + MySociety::Config.get('DOMAIN') + request_url(info_request),
+ :site_name => site_name}
+ end
end
diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb
index d858ab233..07e807451 100644
--- a/app/controllers/track_controller.rb
+++ b/app/controllers/track_controller.rb
@@ -50,11 +50,15 @@ class TrackController < ApplicationController
raise ActiveRecord::RecordNotFound.new("None found") if @public_body.nil?
# If found by historic name, or alternate locale name, redirect to new name
if @public_body.url_name != params[:url_name]
- redirect_to track_public_body_url(:url_name => @public_body.url_name, :feed => params[:feed])
+ redirect_to track_public_body_url(:url_name => @public_body.url_name, :feed => params[:feed], :event_type => params[:event_type])
return
end
- @track_thing = TrackThing.create_track_for_public_body(@public_body)
+ if params[:event_type]
+ @track_thing = TrackThing.create_track_for_public_body(@public_body, params[:event_type])
+ else
+ @track_thing = TrackThing.create_track_for_public_body(@public_body)
+ end
return atom_feed_internal if params[:feed] == 'feed'
@@ -94,7 +98,23 @@ class TrackController < ApplicationController
return atom_feed_internal if params[:feed] == 'feed'
if self.track_set
- redirect_to search_url(@query)
+ if @query.scan("variety").length == 1
+ # we're making a track for a simple filter, for which
+ # there's an expression in the UI (rather than relying
+ # on index:value strings in the query)
+ if @query =~ /variety:user/
+ postfix = "users"
+ @query.sub!("variety:user", "")
+ elsif @query =~ /variety:authority/
+ postfix = "bodies"
+ @query.sub!("variety:authority", "")
+ elsif @query =~ /variety:sent/
+ postfix = "requests"
+ @query.sub!("variety:sent", "")
+ end
+ @query.strip!
+ end
+ redirect_to search_url([@query, postfix])
end
end
@@ -103,7 +123,7 @@ class TrackController < ApplicationController
if @user
@existing_track = TrackThing.find_by_existing_track(@user, @track_thing)
if @existing_track
- flash[:notice] = _("You are already being emailed updates about ") + @track_thing.params[:list_description]
+ flash[:notice] = _("You are already following updates about {{track_description}}", :track_description => @track_thing.params[:list_description])
return true
end
end
@@ -115,8 +135,11 @@ class TrackController < ApplicationController
@track_thing.track_medium = 'email_daily'
@track_thing.tracking_user_id = @user.id
@track_thing.save!
-
- flash[:notice] = _("You will now be emailed updates about ") + @track_thing.params[:list_description]
+ if @user.receive_email_alerts
+ flash[:notice] = _('You will now be emailed updates about {{track_description}}. <a href="{{change_email_alerts_url}}">Prefer not to receive emails?</a>', :track_description => @track_thing.params[:list_description], :change_email_alerts_url => url_for(:controller => "user", :action => "wall", :url_name => @user.url_name))
+ else
+ flash[:notice] = _('You are now <a href="{{wall_url_user}}">following</a> updates about {{track_description}}', :track_description => @track_thing.params[:list_description], :wall_url_user => url_for(:controller => "user", :action => "wall", :url_name => @user.url_name))
+ end
return true
end
@@ -159,7 +182,7 @@ class TrackController < ApplicationController
new_medium = params[:track_medium]
if new_medium == 'delete'
track_thing.destroy
- flash[:notice] = _("You will no longer be emailed updates about ") + track_thing.params[:list_description]
+ flash[:notice] = _("You are no longer following {{track_description}}", :track_description => track_thing.params[:list_description])
redirect_to params[:r]
# Reuse code like this if we let medium change again.
#elsif new_medium == 'email_daily'
diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb
index 403cb9684..e56c4dd33 100644
--- a/app/controllers/user_controller.rb
+++ b/app/controllers/user_controller.rb
@@ -6,10 +6,12 @@
#
# $Id: user_controller.rb,v 1.71 2009-09-17 07:51:47 francis Exp $
+require 'set'
+
class UserController < ApplicationController
layout :select_layout
-
+
protect_from_forgery :only => [ :contact,
:set_profile_photo,
:signchangeemail,
@@ -33,7 +35,7 @@ class UserController < ApplicationController
@show_profile = false
@show_requests = true
end
-
+
@display_user = User.find(:first, :conditions => [ "url_name = ? and email_confirmed = ?", params[:url_name], true ])
if not @display_user
raise ActiveRecord::RecordNotFound.new("user not found, url_name=" + params[:url_name])
@@ -55,7 +57,7 @@ class UserController < ApplicationController
end
@xapian_requests = perform_search([InfoRequestEvent], requests_query, 'newest', 'request_collapse')
@xapian_comments = perform_search([InfoRequestEvent], comments_query, 'newest', nil)
-
+
if (@page > 1)
@page_desc = " (page " + @page.to_s + ")"
else
@@ -89,6 +91,50 @@ class UserController < ApplicationController
end
+ # Show the user's wall
+ def wall
+ long_cache
+ @display_user = User.find(:first, :conditions => [ "url_name = ? and email_confirmed = ?", params[:url_name], true ])
+ if not @display_user
+ raise ActiveRecord::RecordNotFound.new("user not found, url_name=" + params[:url_name])
+ end
+ @is_you = !@user.nil? && @user.id == @display_user.id
+ feed_results = Set.new
+ # Use search query for this so can collapse and paginate easily
+ # XXX really should just use SQL query here rather than Xapian.
+ begin
+ requests_query = 'requested_by:' + @display_user.url_name
+ comments_query = 'commented_by:' + @display_user.url_name
+ # XXX combine these as OR query
+ @xapian_requests = perform_search([InfoRequestEvent], requests_query, 'newest', 'request_collapse')
+ @xapian_comments = perform_search([InfoRequestEvent], comments_query, 'newest', nil)
+ rescue
+ @xapian_requests = nil
+ @xapian_comments = nil
+ end
+
+ feed_results += @xapian_requests.results.map {|x| x[:model]} if !@xapian_requests.nil?
+ feed_results += @xapian_comments.results.map {|x| x[:model]} if !@xapian_comments.nil?
+
+ # All tracks for the user
+ if @is_you
+ @track_things = TrackThing.find(:all, :conditions => ["tracking_user_id = ? and track_medium = ?", @display_user.id, 'email_daily'], :order => 'created_at desc')
+ for track_thing in @track_things
+ # XXX factor out of track_mailer.rb
+ xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 20, 1)
+ feed_results += xapian_object.results.map {|x| x[:model]}
+ end
+ end
+
+ @feed_results = Array(feed_results).sort {|x,y| y.created_at <=> x.created_at}.first(20)
+
+ respond_to do |format|
+ format.html { @has_json = true }
+ format.json { render :json => @display_user.json_for_api }
+ end
+
+ end
+
# Login form
def signin
work_out_post_redirect
@@ -129,7 +175,7 @@ class UserController < ApplicationController
session[:user_id] = @user_signin.id
session[:user_circumstance] = nil
session[:remember_me] = params[:remember_me] ? true : false
-
+
if is_modal_dialog
render :action => 'signin_successful'
else
@@ -182,7 +228,7 @@ class UserController < ApplicationController
return
end
- if !User.stay_logged_in_on_redirect?(@user)
+ if !User.stay_logged_in_on_redirect?(@user) || post_redirect.circumstance == "login_as"
@user = post_redirect.user
@user.email_confirmed = true
@user.save!
@@ -319,7 +365,7 @@ class UserController < ApplicationController
if (not session[:user_circumstance]) or (session[:user_circumstance] != "change_email")
# don't store the password in the db
params[:signchangeemail].delete(:password)
- post_redirect = PostRedirect.new(:uri => signchangeemail_url(),
+ post_redirect = PostRedirect.new(:uri => signchangeemail_url(),
:post_params => params,
:circumstance => "change_email" # special login that lets you change your email
)
@@ -533,17 +579,29 @@ class UserController < ApplicationController
end
end
+ # Change about me text on your profile page
+ def set_receive_email_alerts
+ if authenticated_user.nil?
+ flash[:error] = _("You need to be logged in to edit your profile.")
+ redirect_to frontpage_url
+ return
+ end
+ @user.receive_email_alerts = params[:receive_email_alerts]
+ @user.save!
+ redirect_to params[:came_from]
+ end
+
private
def is_modal_dialog
(params[:modal].to_i != 0)
end
-
+
# when logging in through a modal iframe, don't display chrome around the content
def select_layout
is_modal_dialog ? 'no_chrome' : 'default'
end
-
+
# Decide where we are going to redirect back to after signin/signup, and record that
def work_out_post_redirect
# Redirect to front page later if nothing else specified
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a0f16dfaf..cb6615199 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -17,6 +17,9 @@ module ApplicationHelper
# Site-wide access to configuration settings
include ConfigHelper
+ # Useful for sending emails
+ include MailerHelper
+
# Copied from error_messages_for in active_record_helper.rb
def foi_error_messages_for(*params)
options = params.last.is_a?(Hash) ? params.pop.symbolize_keys : {}
@@ -32,14 +35,14 @@ module ApplicationHelper
html[key] = 'errorExplanation'
end
end
-
+
error_messages = []
for object in objects
object.errors.each do |attr, message|
error_messages << content_tag(:li, message)
end
end
-
+
content_tag(:div,
content_tag(:ul, error_messages),
html
@@ -48,7 +51,7 @@ module ApplicationHelper
''
end
end
-
+
# Highlight words, also escapes HTML (other than spans that we add)
def highlight_words(t, words, html = true)
if html
@@ -70,10 +73,10 @@ module ApplicationHelper
t = highlight_words(t, words, html)
return t
end
-
+
def locale_name(locale)
return LanguageNames::get_language_name(locale)
- end
+ end
# Use our own algorithm for finding path of cache
def foi_cache(name = {}, options = nil, &block)
@@ -100,11 +103,11 @@ module ApplicationHelper
def sanitized_object_name(object_name)
object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/,"_").sub(/_$/,"")
end
-
+
def sanitized_method_name(method_name)
method_name.sub(/\?$/, "")
end
-
+
def form_tag_id(object_name, method_name, locale=nil)
if locale.nil?
return "#{sanitized_object_name(object_name.to_s)}_#{sanitized_method_name(method_name.to_s)}"
@@ -113,5 +116,21 @@ module ApplicationHelper
end
end
+ def admin_value(v)
+ if v.nil?
+ nil
+ elsif v.instance_of?(Time)
+ admin_date(v)
+ else
+ h(v)
+ end
+ end
+
+ def admin_date(date)
+ ago_text = _('{{length_of_time}} ago', :length_of_time => time_ago_in_words(date))
+ exact_date = I18n.l(date, :format => "%e %B %Y %H:%M:%S")
+ return "#{exact_date} (#{ago_text})"
+ end
+
end
diff --git a/app/helpers/config_helper.rb b/app/helpers/config_helper.rb
index b0381a2f5..543b60256 100644
--- a/app/helpers/config_helper.rb
+++ b/app/helpers/config_helper.rb
@@ -2,7 +2,7 @@ module ConfigHelper
def site_name
MySociety::Config.get('SITE_NAME', 'Alaveteli')
end
-
+
def force_registration_on_new_request
MySociety::Config.get('FORCE_REGISTRATION_ON_NEW_REQUEST', false)
end
diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb
index 56c33e512..f621721b6 100755
--- a/app/helpers/link_to_helper.rb
+++ b/app/helpers/link_to_helper.rb
@@ -1,6 +1,6 @@
# app/helpers/link_to_helper.rb:
# This module is included into all controllers via controllers/application.rb
-# -
+# -
#
# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
@@ -10,25 +10,29 @@
module LinkToHelper
# Links to various models
-
+
# Requests
def request_url(info_request, extra_params={})
params = {:url_title => info_request.url_title, :only_path => true}
return show_request_url(params.merge(extra_params))
end
-
- def request_link(info_request)
- link_to h(info_request.title), request_url(info_request)
+
+ def request_link(info_request, cls=nil )
+ link_to h(info_request.title), request_url(info_request), :class => cls
end
-
+
def request_admin_url(info_request)
return admin_url('request/show/' + info_request.id.to_s)
end
-
+
+ def request_admin_link(info_request, name="admin", cls=nil)
+ link_to name, request_admin_url(info_request), :class => cls
+ end
+
def request_both_links(info_request)
link_to(h(info_request.title), main_url(request_url(info_request))) + " (" + link_to("admin", request_admin_url(info_request)) + ")"
end
-
+
def request_similar_url(info_request)
return similar_request_url(:url_title => info_request.url_title, :only_path => true)
end
@@ -58,7 +62,7 @@ module LinkToHelper
end
return respond_url
end
-
+
# Public bodies
def public_body_url(public_body)
public_body.url_name.nil? ? '' : show_public_body_url(:url_name => public_body.url_name, :only_path => true)
@@ -66,8 +70,8 @@ module LinkToHelper
def public_body_link_short(public_body)
link_to h(public_body.short_or_long_name), public_body_url(public_body)
end
- def public_body_link(public_body)
- link_to h(public_body.name), public_body_url(public_body)
+ def public_body_link(public_body, cls=nil)
+ link_to h(public_body.name), public_body_url(public_body), :class => cls
end
def public_body_link_absolute(public_body) # e.g. for in RSS
link_to h(public_body.name), main_url(public_body_url(public_body))
@@ -79,15 +83,15 @@ module LinkToHelper
link_to(h(public_body.name), main_url(public_body_url(public_body))) + " (" + link_to("admin", public_body_admin_url(public_body)) + ")"
end
def list_public_bodies_default
- list_public_bodies_url(:tag => 'all')
+ list_public_bodies_url(:tag => 'all')
end
# Users
def user_url(user)
return show_user_url(:url_name => user.url_name, :only_path => true)
end
- def user_link(user)
- link_to h(user.name), user_url(user)
+ def user_link(user, cls=nil)
+ link_to h(user.name), user_url(user), :class => cls
end
def user_link_absolute(user)
link_to h(user.name), main_url(user_url(user))
@@ -112,6 +116,9 @@ module LinkToHelper
def user_admin_url(user)
return admin_url('user/show/' + user.id.to_s)
end
+ def user_admin_link(user, name="admin", cls=nil)
+ link_to name, user_admin_url(user), :class => cls
+ end
def user_both_links(user)
link_to(h(user.name), main_url(user_url(user))) + " (" + link_to("admin", user_admin_url(user)) + ")"
end
@@ -120,15 +127,15 @@ module LinkToHelper
def do_track_url(track_thing, feed = 'track')
if track_thing.track_type == 'request_updates'
track_request_url(:url_title => track_thing.info_request.url_title, :feed => feed)
- elsif track_thing.track_type == 'all_new_requests'
+ elsif track_thing.track_type == 'all_new_requests'
track_list_url(:view => 'recent', :feed => feed)
- elsif track_thing.track_type == 'all_successful_requests'
+ elsif track_thing.track_type == 'all_successful_requests'
track_list_url(:view => 'successful', :feed => feed)
- elsif track_thing.track_type == 'public_body_updates'
+ elsif track_thing.track_type == 'public_body_updates'
track_public_body_url(:url_name => track_thing.public_body.url_name, :feed => feed)
- elsif track_thing.track_type == 'user_updates'
+ elsif track_thing.track_type == 'user_updates'
track_user_url(:url_name => track_thing.tracked_user.url_name, :feed => feed)
- elsif track_thing.track_type == 'search_query'
+ elsif track_thing.track_type == 'search_query'
track_search_url(:query_array => track_thing.track_query, :feed => feed)
else
raise "unknown tracking type " + track_thing.track_type
@@ -141,7 +148,7 @@ module LinkToHelper
query = query - ["", nil]
query = query.join("/")
end
- routing_info = {:controller => 'general',
+ routing_info = {:controller => 'general',
:action => 'search',
:combined => query,
:view => nil}
@@ -204,7 +211,9 @@ module LinkToHelper
# Basic date format
def simple_date(date)
- return I18n.l(date, :format => "%e %B %Y")
+ date_format = _("simple_date_format")
+ date_format = :long if date_format == "simple_date_format"
+ return I18n.l(date.to_date, :format => date_format)
end
def simple_time(date)
diff --git a/app/helpers/mailer_helper.rb b/app/helpers/mailer_helper.rb
new file mode 100644
index 000000000..c0a950d47
--- /dev/null
+++ b/app/helpers/mailer_helper.rb
@@ -0,0 +1,7 @@
+module MailerHelper
+ def contact_from_name_and_email
+ contact_name = MySociety::Config.get("CONTACT_NAME", 'Alaveteli')
+ contact_email = MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost')
+ return "#{contact_name} <#{contact_email}>"
+ end
+end
diff --git a/app/models/about_me_validator.rb b/app/models/about_me_validator.rb
index e24c5512c..67b81bc9c 100644
--- a/app/models/about_me_validator.rb
+++ b/app/models/about_me_validator.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 95
+# Schema version: 114
#
# Table name: about_me_validators
#
diff --git a/app/models/application_mailer.rb b/app/models/application_mailer.rb
index e9f82a2c3..044006f7c 100644
--- a/app/models/application_mailer.rb
+++ b/app/models/application_mailer.rb
@@ -9,17 +9,12 @@
class ApplicationMailer < ActionMailer::Base
# Include all the functions views get, as emails call similar things.
helper :application
+ include MailerHelper
# This really should be the default - otherwise you lose any information
# about the errors, and have to do error checking on return codes.
self.raise_delivery_errors = true
- def contact_from_name_and_email
- contact_name = MySociety::Config.get("CONTACT_NAME", 'Alaveteli')
- contact_email = MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost')
- return "#{contact_name} <#{contact_email}>"
- end
-
def blackhole_email
MySociety::Config.get("BLACKHOLE_PREFIX", 'do-not-reply-to-this-address')+"@"+MySociety::Config.get("INCOMING_EMAIL_DOMAIN", "localhost")
end
@@ -28,7 +23,7 @@ class ApplicationMailer < ActionMailer::Base
# views (for links) and mailers (for use in emails), so include them into
# all of all.
include LinkToHelper
-
+
# Site-wide access to configuration settings
include ConfigHelper
end
diff --git a/app/models/censor_rule.rb b/app/models/censor_rule.rb
index 201e60746..a477d2568 100644
--- a/app/models/censor_rule.rb
+++ b/app/models/censor_rule.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: censor_rules
#
@@ -51,7 +51,10 @@ class CensorRule < ActiveRecord::Base
errors.add("Censor must apply to an info request a user or a body; ")
end
end
-end
-
-
+ def for_admin_column
+ self.class.content_columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
+end
diff --git a/app/models/change_email_validator.rb b/app/models/change_email_validator.rb
index e3f8fa892..0395ab6d5 100644
--- a/app/models/change_email_validator.rb
+++ b/app/models/change_email_validator.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: change_email_validators
#
@@ -30,7 +30,7 @@ class ChangeEmailValidator < ActiveRecord::BaseWithoutTable
validates_presence_of :old_email, :message => N_("Please enter your old email address")
validates_presence_of :new_email, :message => N_("Please enter your new email address")
validates_presence_of :password, :message => N_("Please enter your password"), :unless => :changing_email
-
+
def changing_email()
self.user_circumstance == 'change_email'
end
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 44a1079cd..6edfaa24f 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: comments
#
@@ -84,7 +84,9 @@ class Comment < ActiveRecord::Base
return Comment.find(:first, :conditions => [ "info_request_id = ? and body = ?", info_request_id, body ])
end
end
-
+ def for_admin_column
+ self.class.content_columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
end
-
-
diff --git a/app/models/contact_mailer.rb b/app/models/contact_mailer.rb
index 0390fc347..6e781d48c 100644
--- a/app/models/contact_mailer.rb
+++ b/app/models/contact_mailer.rb
@@ -25,7 +25,7 @@ class ContactMailer < ApplicationMailer
# they shouldn't, and this might help. (Have had mysterious cases of a
# reply coming in duplicate from a public body to both From and envelope
# from)
-
+
# Send message to another user
def user_message(from_user, recipient_user, from_user_url, subject, message)
@from = from_user.name_and_email
@@ -34,7 +34,7 @@ class ContactMailer < ApplicationMailer
headers 'Return-Path' => blackhole_email, 'Reply-To' => @from
@recipients = recipient_user.name_and_email
@subject = subject
- @body = {
+ @body = {
:message => message,
:from_user => from_user,
:recipient_user => recipient_user,
@@ -42,4 +42,17 @@ class ContactMailer < ApplicationMailer
}
end
+ # Send message to a user from the administrator
+ def from_admin_message(recipient_user, subject, message)
+ @from = contact_from_name_and_email
+ @recipients = recipient_user.name_and_email
+ @subject = subject
+ @body = {
+ :message => message,
+ :from_user => @from,
+ :recipient_user => recipient_user,
+ }
+ bcc MySociety::Config::get("CONTACT_EMAIL")
+ end
+
end
diff --git a/app/models/contact_validator.rb b/app/models/contact_validator.rb
index 0bc562835..a9748a739 100644
--- a/app/models/contact_validator.rb
+++ b/app/models/contact_validator.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 95
+# Schema version: 114
#
# Table name: contact_validators
#
diff --git a/app/models/exim_log.rb b/app/models/exim_log.rb
index 77e5e2d21..60faa7f0b 100644
--- a/app/models/exim_log.rb
+++ b/app/models/exim_log.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: exim_logs
#
@@ -40,7 +40,7 @@ class EximLog < ActiveRecord::Base
ActiveRecord::Base.transaction do
# see if we already have it
- done = EximLogDone.find_by_filename(file_name_db)
+ done = EximLogDone.find_by_filename(file_name_db)
if !done.nil?
if modified.utc == done.last_stat.utc
# already have that, nothing to do
@@ -124,7 +124,7 @@ class EximLog < ActiveRecord::Base
return ok
end
-
+
end
diff --git a/app/models/exim_log_done.rb b/app/models/exim_log_done.rb
index b8a39033a..3cedc1379 100644
--- a/app/models/exim_log_done.rb
+++ b/app/models/exim_log_done.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 95
+# Schema version: 114
#
# Table name: exim_log_dones
#
diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb
index da92d1c2d..9bbf0988f 100644
--- a/app/models/foi_attachment.rb
+++ b/app/models/foi_attachment.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: foi_attachments
#
@@ -42,7 +42,7 @@ class FoiAttachment < ActiveRecord::Base
if rails_env.nil? || rails_env.empty?
raise "$RAILS_ENV is not set"
end
- base_dir = File.join(File.dirname(__FILE__), "../../cache", "attachments_#{rails_env}")
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), "../../cache", "attachments_#{rails_env}"))
return File.join(base_dir, self.hexdigest[0..2])
end
@@ -177,7 +177,7 @@ class FoiAttachment < ActiveRecord::Base
filename = filename.gsub(/\//, "-")
return filename
- end
+ end
# XXX changing this will break existing URLs, so have a care - maybe
# make another old_display_filename see above
@@ -248,16 +248,16 @@ class FoiAttachment < ActiveRecord::Base
return !! {
"application/pdf" => true, # .pdf
"image/tiff" => true, # .tiff
-
+
"application/vnd.ms-word" => true, # .doc
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" => true, # .docx
-
+
"application/vnd.ms-powerpoint" => true, # .ppt
"application/vnd.openxmlformats-officedocument.presentationml.presentation" => true, # .pptx
-
+
"application/vnd.ms-excel" => true, # .xls
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" => true, # .xlsx
-
+
} [self.content_type]
end
@@ -277,16 +277,16 @@ class FoiAttachment < ActiveRecord::Base
return {
"text/plain" => "Text file",
'application/rtf' => "RTF file",
-
+
'application/pdf' => "PDF file",
'image/tiff' => "TIFF image",
-
+
'application/vnd.ms-word' => "Word document",
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => "Word document",
-
+
'application/vnd.ms-powerpoint' => "PowerPoint presentation",
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => "PowerPoint presentation",
-
+
'application/vnd.ms-excel' => "Excel spreadsheet",
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => "Excel spreadsheet",
}[self.content_type]
@@ -345,7 +345,7 @@ class FoiAttachment < ActiveRecord::Base
if self.has_google_docs_viewer?
wrapper_id = "wrapper_google_embed"
ret = ret + "<iframe src='http://docs.google.com/viewer?url=<attachment-url-here>&embedded=true' width='100%' height='100%' style='border: none;'></iframe>";
- else
+ else
ret = ret + "<p>Sorry, we were unable to convert this file to HTML. Please use the download link at the top right.</p>"
end
ret = ret + "</body></html>"
diff --git a/app/models/holiday.rb b/app/models/holiday.rb
index 60b5ff443..debd88dec 100644
--- a/app/models/holiday.rb
+++ b/app/models/holiday.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: holidays
#
@@ -10,7 +10,7 @@
# models/holiday.rb:
#
-# Store details on, and perform calculations with, public holidays on which
+# Store details on, and perform calculations with, public holidays on which
# the clock for answering FOI requests does not run:
#
# ... "working day" means any day other than a Saturday, a Sunday, Christmas
@@ -37,7 +37,7 @@ class Holiday < ActiveRecord::Base
# Count forward (20) working days. We start with today as "day zero". The
# first of the twenty full working days is the next day. We return the
# date of the last of the twenty.
-
+
# This response for example of a public authority complains that we had
# it wrong. We didn't (even thought I changed the code for a while,
# it's changed back now). A day is a day, our lawyer tells us.
diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb
index cbbcf5aa6..3419956d6 100644
--- a/app/models/incoming_message.rb
+++ b/app/models/incoming_message.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: incoming_messages
#
@@ -11,12 +11,12 @@
# cached_attachment_text_clipped :text
# cached_main_body_text_folded :text
# cached_main_body_text_unfolded :text
-# sent_at :time
# subject :text
# mail_from_domain :text
# valid_to_reply_to :boolean
# last_parsed :datetime
# mail_from :text
+# sent_at :datetime
#
# encoding: UTF-8
@@ -81,7 +81,7 @@ class IncomingMessage < ActiveRecord::Base
# http://www.whatdotheyknow.com/request/reviews_of_unduly_lenient_senten#incoming-4830
# Report of TMail bug:
# http://rubyforge.org/tracker/index.php?func=detail&aid=21810&group_id=4512&atid=17370
- copy_of_raw_data = self.raw_email.data.gsub(/; boundary=\s+"/ims,'; boundary="')
+ copy_of_raw_data = self.raw_email.data.gsub(/; boundary=\s+"/ims,'; boundary="')
@mail = TMail::Mail.parse(copy_of_raw_data)
@mail.base64_decode
@@ -92,7 +92,7 @@ class IncomingMessage < ActiveRecord::Base
# Returns the name of the person the incoming message is from, or nil if
# there isn't one or if there is only an email address. XXX can probably
# remove from_name_if_present (which is a monkey patch) by just calling
- # .from_addrs[0].name here instead?
+ # .from_addrs[0].name here instead?
# Return false if for some reason this is a message that we shouldn't let them reply to
def _calculate_valid_to_reply_to
@@ -178,7 +178,7 @@ class IncomingMessage < ActiveRecord::Base
def safe_mail_from
if !self.mail_from.nil?
mail_from = self.mail_from.dup
- self.info_request.apply_censor_rules_to_text!(mail_from)
+ self.info_request.apply_censor_rules_to_text!(mail_from)
return mail_from
end
end
@@ -191,7 +191,7 @@ class IncomingMessage < ActiveRecord::Base
# XXX This fills in part.rfc822_attachment and part.url_part_number within
# all the parts of the email (see TMail monkeypatch above for how these
# attributes are added). ensure_parts_counted must be called before using
- # the attributes.
+ # the attributes.
def ensure_parts_counted
@count_parts_count = 0
_count_parts_recursive(self.mail)
@@ -215,7 +215,7 @@ class IncomingMessage < ActiveRecord::Base
# e.g. http://www.whatdotheyknow.com/request/chinese_names_for_british_politi
msg = Mapi::Msg.open(StringIO.new(part.body))
part.rfc822_attachment = TMail::Mail.parse(msg.to_mime.to_s)
- elsif part.content_type == 'application/ms-tnef'
+ elsif part.content_type == 'application/ms-tnef'
# A set of attachments in a TNEF file
part.rfc822_attachment = TNEF.as_tmail(part.body)
end
@@ -250,10 +250,10 @@ class IncomingMessage < ActiveRecord::Base
# if they are public anyway. For now just be precautionary and only
# put in descriptions of them in square brackets.
if self.info_request.public_body.is_followupable?
- text.gsub!(self.info_request.public_body.request_email, "[" + self.info_request.public_body.short_or_long_name + " request email]")
+ text.gsub!(self.info_request.public_body.request_email, _("[{{public_body}} request email]", :public_body => self.info_request.public_body.short_or_long_name))
end
- text.gsub!(self.info_request.incoming_email, "[FOI #" + self.info_request.id.to_s + " email]")
- text.gsub!(MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost'), "[#{MySociety::Config.get('SITE_NAME', 'Alaveteli')} contact email]")
+ text.gsub!(self.info_request.incoming_email, _('[FOI #{{request}} email]', :request => self.info_request.id.to_s) )
+ text.gsub!(MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost'), _("[{{site_name}} contact email]", :site_name => MySociety::Config.get('SITE_NAME', 'Alaveteli')) )
end
# Replaces all email addresses in (possibly binary data) with equal length alternative ones.
@@ -289,7 +289,7 @@ class IncomingMessage < ActiveRecord::Base
# buggy versions of pdftk sometimes fail on
# compression, I don't see it's a disaster in
# these cases to save an uncompressed version?
- recompressed_text = censored_uncompressed_text
+ recompressed_text = censored_uncompressed_text
logger.warn "Unable to compress PDF; problem with your pdftk version?"
end
if !recompressed_text.nil? && !recompressed_text.empty?
@@ -297,10 +297,10 @@ class IncomingMessage < ActiveRecord::Base
end
end
end
- return
+ return
end
- self._binary_mask_stuff_internal!(text)
+ self._binary_mask_stuff_internal!(text)
end
# Used by binary_mask_stuff - replace text in place
@@ -309,7 +309,7 @@ class IncomingMessage < ActiveRecord::Base
orig_size = text.size
# Replace ASCII email addresses...
- text.gsub!(MySociety::Validate.email_find_regexp) do |email|
+ text.gsub!(MySociety::Validate.email_find_regexp) do |email|
email.gsub(/[^@.]/, 'x')
end
@@ -320,7 +320,7 @@ class IncomingMessage < ActiveRecord::Base
emails = ascii_chars.scan(MySociety::Validate.email_find_regexp)
# Convert back to UCS-2, making a mask at the same time
emails.map! {|email| [
- Iconv.conv('ucs-2le', 'ascii', email[0]),
+ Iconv.conv('ucs-2le', 'ascii', email[0]),
Iconv.conv('ucs-2le', 'ascii', email[0].gsub(/[^@.]/, 'x'))
] }
# Now search and replace the UCS-2 email with the UCS-2 mask
@@ -416,7 +416,7 @@ class IncomingMessage < ActiveRecord::Base
# http://www.whatdotheyknow.com/request/secured_convictions_aided_by_cct
multiline_original_message = '(' + '''>>>.* \d\d/\d\d/\d\d\d\d\s+\d\d:\d\d(?::\d\d)?\s*>>>''' + ')'
text.gsub!(/^(#{multiline_original_message}\n.*)$/ms, replacement)
-
+
# Single line sections
text.gsub!(/^(>.*\n)/, replacement)
text.gsub!(/^(On .+ (wrote|said):\n)/, replacement)
@@ -453,8 +453,8 @@ class IncomingMessage < ActiveRecord::Base
# http://www.whatdotheyknow.com/request/123/response/192
# http://www.whatdotheyknow.com/request/235/response/513
# http://www.whatdotheyknow.com/request/445/response/743
- original_message =
- '(' + '''----* This is a copy of the message, including all the headers. ----*''' +
+ original_message =
+ '(' + '''----* This is a copy of the message, including all the headers. ----*''' +
'|' + '''----*\s*Original Message\s*----*''' +
'|' + '''----*\s*Forwarded message.+----*''' +
'|' + '''----*\s*Forwarded by.+----*''' +
@@ -482,7 +482,7 @@ class IncomingMessage < ActiveRecord::Base
return part_file_name
end
- # (This risks losing info if the unchosen alternative is the only one to contain
+ # (This risks losing info if the unchosen alternative is the only one to contain
# useful info, but let's worry about that another time)
def get_attachment_leaves
force = true
@@ -538,7 +538,7 @@ class IncomingMessage < ActiveRecord::Base
if calc_mime
curr_mail.content_type = calc_mime
end
- end
+ end
# Use standard content types for Word documents etc.
curr_mail.content_type = normalise_content_type(curr_mail.content_type)
@@ -660,11 +660,11 @@ class IncomingMessage < ActiveRecord::Base
# Test if it's good UTF-8
text = Iconv.conv('utf-8', 'utf-8', text)
rescue Iconv::IllegalSequence
- # Text looks like unlabelled nonsense,
+ # Text looks like unlabelled nonsense,
# strip out anything that isn't UTF-8
begin
- text = Iconv.conv('utf-8//IGNORE', source_charset, text) +
- _("\n\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]",
+ text = Iconv.conv('utf-8//IGNORE', source_charset, text) +
+ _("\n\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]",
:site_name => MySociety::Config.get('SITE_NAME', 'Alaveteli'))
rescue Iconv::InvalidEncoding, Iconv::IllegalSequence
if source_charset != "utf-8"
@@ -673,7 +673,6 @@ class IncomingMessage < ActiveRecord::Base
end
end
end
-
# Fix DOS style linefeeds to Unix style ones (or other later regexps won't work)
# Needed for e.g. http://www.whatdotheyknow.com/request/60/response/98
@@ -693,7 +692,7 @@ class IncomingMessage < ActiveRecord::Base
# Find first part which is text/plain or text/html
# (We have to include HTML, as increasingly there are mail clients that
# include no text alternative for the main part, and we don't want to
- # instead use the first text attachment
+ # instead use the first text attachment
# e.g. http://www.whatdotheyknow.com/request/list_of_public_authorties)
leaves.each do |p|
if p.content_type == 'text/plain' or p.content_type == 'text/html'
@@ -707,8 +706,8 @@ class IncomingMessage < ActiveRecord::Base
return p
end
end
-
- # ... or if none, consider first part
+
+ # ... or if none, consider first part
p = leaves[0]
# if it is a known type then don't use it, return no body (nil)
if !p.nil? && AlaveteliFileTypes.mimetype_to_extension(p.content_type)
@@ -752,7 +751,7 @@ class IncomingMessage < ActiveRecord::Base
:display_size => "0K")
attachment.save!
attachments << attachment
- end
+ end
return attachments
end
@@ -802,7 +801,7 @@ class IncomingMessage < ActiveRecord::Base
# XXX call _convert_part_body_to_text here, but need to get charset somehow
# e.g. http://www.whatdotheyknow.com/request/1593/response/3088/attach/4/Freedom%20of%20Information%20request%20-%20car%20oval%20sticker:%20Article%2020,%20Convention%20on%20Road%20Traffic%201949.txt
body = headers + "\n" + body
-
+
# This is quick way of getting all headers, but instead we only add some a) to
# make it more usable, b) as at least one authority accidentally leaked security
# information into a header.
@@ -816,7 +815,6 @@ class IncomingMessage < ActiveRecord::Base
:filename => _get_part_file_name(leaf),
:charset => leaf.charset,
:within_rfc822_subject => within_rfc822_subject,
- :display_size => "0K",
:body => body)
attachment.save!
attachments << attachment.id
@@ -837,7 +835,7 @@ class IncomingMessage < ActiveRecord::Base
end
# now get rid of any attachments we no longer have
- FoiAttachment.destroy_all("id NOT IN (#{attachments.join(',')}) AND incoming_message_id = #{self.id}")
+ FoiAttachment.destroy_all("id NOT IN (#{attachments.join(',')}) AND incoming_message_id = #{self.id}")
end
# Returns body text as HTML with quotes flattened, and emails removed.
@@ -866,10 +864,10 @@ class IncomingMessage < ActiveRecord::Base
text = "[Subject only] " + CGI.escapeHTML(self.subject) + text
end
# and display link for quoted stuff
- text = text.gsub(/FOLDED_QUOTED_SECTION/, "\n\n" + '<span class="unfold_link"><a href="?unfold=1#incoming-'+self.id.to_s+'">show quoted sections</a></span>' + "\n\n")
+ text = text.gsub(/FOLDED_QUOTED_SECTION/, "\n\n" + '<span class="unfold_link"><a href="?unfold=1#incoming-'+self.id.to_s+'">'+_("show quoted sections")+'</a></span>' + "\n\n")
else
if folded_quoted_text.include?('FOLDED_QUOTED_SECTION')
- text = text + "\n\n" + '<span class="unfold_link"><a href="?#incoming-'+self.id.to_s+'">hide quoted sections</a></span>'
+ text = text + "\n\n" + '<span class="unfold_link"><a href="?#incoming-'+self.id.to_s+'">'+_("hide quoted sections")+'</a></span>'
end
end
text.strip!
@@ -899,13 +897,13 @@ class IncomingMessage < ActiveRecord::Base
self.remove_privacy_sensitive_things!(text)
# This can be useful for memory debugging
#STDOUT.puts 'xxx '+ MySociety::DebugHelpers::allocated_string_size_around_gc
-
+
# Save clipped version for snippets
if self.cached_attachment_text_clipped.nil?
self.cached_attachment_text_clipped = text[0..MAX_ATTACHMENT_TEXT_CLIPPED]
self.save!
end
-
+
return text
end
# Returns a version reduced to a sensible maximum size - this
@@ -988,7 +986,7 @@ class IncomingMessage < ActiveRecord::Base
for entry in zip_file
if entry.file?
filename = entry.to_s
- begin
+ begin
body = entry.get_input_stream.read
rescue
# move to next attachment silently if there were problems
@@ -1002,7 +1000,7 @@ class IncomingMessage < ActiveRecord::Base
else
content_type = 'application/octet-stream'
end
-
+
text += _get_attachment_text_internal_one_file(content_type, body)
end
end
@@ -1030,8 +1028,6 @@ class IncomingMessage < ActiveRecord::Base
return get_body_for_quoting + "\n\n" + get_attachment_text_clipped
end
-
-
# Has message arrived "recently"?
def recently_arrived
(Time.now - self.created_at) <= 3.days
@@ -1052,7 +1048,7 @@ class IncomingMessage < ActiveRecord::Base
end
end
- # Search all info requests for
+ # Search all info requests for
def IncomingMessage.find_all_unknown_mime_types
for incoming_message in IncomingMessage.find(:all)
for attachment in incoming_message.get_attachments_for_display
@@ -1118,7 +1114,7 @@ class IncomingMessage < ActiveRecord::Base
content_type = 'application/vnd.ms-excel'
end
if content_type == 'application/mspowerpoint' or content_type == 'application/x-ms-powerpoint'
- content_type = 'application/vnd.ms-powerpoint'
+ content_type = 'application/vnd.ms-powerpoint'
end
if content_type == 'application/msword' or content_type == 'application/x-ms-word'
content_type = 'application/vnd.ms-word'
@@ -1134,8 +1130,16 @@ class IncomingMessage < ActiveRecord::Base
return content_type
end
- private :normalise_content_type
+
+ def for_admin_column
+ self.class.content_columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
+
+ private :normalise_content_type
end
+
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index b5a1cd833..45819bfe7 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: info_requests
#
@@ -17,12 +17,16 @@
# allow_new_responses_from :string(255) default("anybody"), not null
# handle_rejected_responses :string(255) default("bounce"), not null
# idhash :string(255) not null
+# attention_requested :boolean default(FALSE)
#
require 'digest/sha1'
class InfoRequest < ActiveRecord::Base
+ include ActionView::Helpers::UrlHelper
+ include ActionController::UrlWriter
+
strip_attributes!
validates_presence_of :title, :message => N_("Please enter a summary of your request")
@@ -48,14 +52,14 @@ class InfoRequest < ActiveRecord::Base
# user described state (also update in info_request_event, admin_request/edit.rhtml)
validate :must_be_valid_state
- validates_inclusion_of :prominence, :in => [
- 'normal',
+ validates_inclusion_of :prominence, :in => [
+ 'normal',
'backpage',
'hidden',
'requester_only'
]
- validates_inclusion_of :law_used, :in => [
+ validates_inclusion_of :law_used, :in => [
'foi', # Freedom of Information Act
'eir', # Environmental Information Regulations
]
@@ -74,18 +78,21 @@ class InfoRequest < ActiveRecord::Base
]
def self.enumerate_states
- states = [
+ states = [
'waiting_response',
- 'waiting_clarification',
+ 'waiting_clarification',
'gone_postal',
'not_held',
'rejected', # this is called 'refused' in UK FOI law and the user interface, but 'rejected' internally for historic reasons
- 'successful',
+ 'successful',
'partially_successful',
'internal_review',
'error_message',
'requires_admin',
- 'user_withdrawn'
+ 'user_withdrawn',
+ 'attention_requested',
+ 'vexatious',
+ 'not_foi'
]
if @@custom_states_loaded
states += InfoRequest.theme_extra_states
@@ -94,7 +101,7 @@ class InfoRequest < ActiveRecord::Base
end
def must_be_valid_state
- errors.add(:described_state, "is not a valid state") if
+ errors.add(:described_state, "is not a valid state") if
!InfoRequest.enumerate_states.include? described_state
end
@@ -120,7 +127,7 @@ class InfoRequest < ActiveRecord::Base
errors.add(:title, _('Please describe more what the request is about in the subject. There is no need to say it is an FOI request, we add that on anyway.'))
end
end
-
+
OLD_AGE_IN_DAYS = 21.days
def after_initialize
@@ -166,7 +173,7 @@ class InfoRequest < ActiveRecord::Base
end
end
# Force reindex when tag string changes
- alias_method :orig_tag_string=, :tag_string=
+ alias_method :orig_tag_string=, :tag_string=
def tag_string=(tag_string)
ret = self.orig_tag_string=(tag_string)
reindex_request_events
@@ -219,7 +226,7 @@ public
end
# Email which public body should use to respond to request. This is in
- # the format PREFIXrequest-ID-HASH@DOMAIN. Here ID is the id of the
+ # the format PREFIXrequest-ID-HASH@DOMAIN. Here ID is the id of the
# FOI request, and HASH is a signature for that id.
def incoming_email
return self.magic_email("request-")
@@ -251,7 +258,7 @@ public
end
end
- # Two sorts of laws for requests, FOI or EIR
+ # Two sorts of laws for requests, FOI or EIR
def law_used_full
if self.law_used == 'foi'
return _("Freedom of Information")
@@ -306,7 +313,7 @@ public
guesses = []
# 1. Try to guess based on the email address(es)
addresses =
- (incoming_message.mail.to || []) +
+ (incoming_message.mail.to || []) +
(incoming_message.mail.cc || []) +
(incoming_message.mail.envelope_to || [])
addresses.uniq!
@@ -453,7 +460,6 @@ public
# An annotation (comment) is made
def add_comment(body, user)
comment = Comment.new
-
ActiveRecord::Base.transaction do
comment.body = body
comment.user = user
@@ -501,7 +507,7 @@ public
# states which require administrator action (hence email administrators
# when they are entered, and offer state change dialog to them)
def InfoRequest.requires_admin_states
- return ['requires_admin', 'error_message']
+ return ['requires_admin', 'error_message', 'attention_requested']
end
def requires_admin?
@@ -509,8 +515,11 @@ public
return false
end
+ def can_have_attention_requested?
+ end
+
# change status, including for last event for later historical purposes
- def set_described_state(new_state)
+ def set_described_state(new_state, set_by = nil)
ActiveRecord::Base.transaction do
self.awaiting_description = false
last_event = self.get_last_event
@@ -523,7 +532,7 @@ public
self.calculate_event_states
if self.requires_admin?
- RequestMailer.deliver_requires_admin(self)
+ RequestMailer.deliver_requires_admin(self, set_by)
end
end
@@ -539,7 +548,7 @@ public
self.base_calculate_status
end
end
-
+
def base_calculate_status
return 'waiting_classification' if self.awaiting_description
return described_state unless self.described_state == "waiting_response"
@@ -559,13 +568,13 @@ public
curr_state = nil
for event in self.info_request_events.reverse
event.xapian_mark_needs_index # we need to reindex all events in order to update their latest_* terms
- if curr_state.nil?
+ if curr_state.nil?
if !event.described_state.nil?
curr_state = event.described_state
end
end
- if !curr_state.nil? && event.event_type == 'response'
+ if !curr_state.nil? && event.event_type == 'response'
if event.calculated_state != curr_state
event.calculated_state = curr_state
event.last_described_at = Time.now()
@@ -579,7 +588,7 @@ public
elsif !curr_state.nil? && (event.event_type == 'followup_sent' || event.event_type == 'sent') && !event.described_state.nil? && (event.described_state == 'waiting_response' || event.described_state == 'internal_review')
# Followups can set the status to waiting response / internal
# review. Initial requests ('sent') set the status to waiting response.
-
+
# We want to store that in calculated_state state so it gets
# indexed.
if event.calculated_state != event.described_state
@@ -665,7 +674,11 @@ public
return self.public_body.is_followupable?
end
def recipient_name_and_email
- return TMail::Address.address_from_name_and_email(self.law_used_short + " requests at " + self.public_body.short_or_long_name, self.recipient_email).to_s
+ return TMail::Address.address_from_name_and_email(
+ _("{{law_used}} requests at {{public_body}}",
+ :law_used => self.law_used_short,
+ :public_body => self.public_body.short_or_long_name),
+ self.recipient_email).to_s
end
# History of some things that have happened
@@ -723,8 +736,8 @@ public
def index_of_last_described_event
events = self.info_request_events
events.each_index do |i|
- revi = events.size - 1 - i
- m = events[revi]
+ revi = events.size - 1 - i
+ m = events[revi]
if not m.described_state.nil?
return revi
end
@@ -735,7 +748,7 @@ public
def last_event_id_needing_description
last_event = events_needing_description[-1]
last_event.nil? ? 0 : last_event.id
- end
+ end
# Returns all the events which the user hasn't described yet - an empty array if all described.
def events_needing_description
@@ -801,8 +814,14 @@ public
_("Delivery error")
elsif status == 'requires_admin'
_("Unusual response.")
+ elsif status == 'attention_requested'
+ _("Reported for administrator attention.")
elsif status == 'user_withdrawn'
_("Withdrawn by the requester.")
+ elsif status == 'vexatious'
+ _("Considered by administrators as vexatious and hidden from site.")
+ elsif status == 'not_foi'
+ _("Considered by administrators as not an FOI request and hidden from site.")
else
begin
return self.theme_display_status(status)
@@ -823,11 +842,11 @@ public
track_thing.destroy
end
self.user_info_request_sent_alerts.each { |a| a.destroy }
- self.info_request_events.each do |info_request_event|
+ self.info_request_events.each do |info_request_event|
info_request_event.track_things_sent_emails.each { |a| a.destroy }
info_request_event.destroy
end
- self.exim_logs.each do |exim_log|
+ self.exim_logs.each do |exim_log|
exim_log.destroy
end
self.outgoing_messages.each { |a| a.destroy }
@@ -842,8 +861,8 @@ public
return InfoRequest.magic_email_for_id(prefix_part, self.id)
end
- def InfoRequest.magic_email_for_id(prefix_part, id)
- magic_email = MySociety::Config.get("INCOMING_EMAIL_PREFIX", "")
+ def InfoRequest.magic_email_for_id(prefix_part, id)
+ magic_email = MySociety::Config.get("INCOMING_EMAIL_PREFIX", "")
magic_email += prefix_part + id.to_s
magic_email += "-" + InfoRequest.hash_from_id(id)
magic_email += "@" + MySociety::Config.get("INCOMING_EMAIL_DOMAIN", "localhost")
@@ -888,14 +907,14 @@ public
def InfoRequest.find_old_unclassified(extra_params={})
last_response_created_at = last_event_time_clause('response')
age = extra_params[:age_in_days] ? extra_params[:age_in_days].days : OLD_AGE_IN_DAYS
- params = {:select => "*, #{last_response_created_at} as last_response_time",
- :conditions => ["awaiting_description = ? and #{last_response_created_at} < ? and url_title != 'holding_pen'",
- true, Time.now() - age],
+ params = {:select => "*, #{last_response_created_at} as last_response_time",
+ :conditions => ["awaiting_description = ? and #{last_response_created_at} < ? and url_title != 'holding_pen'",
+ true, Time.now() - age],
:order => "last_response_time"}
params[:limit] = extra_params[:limit] if extra_params[:limit]
params[:include] = extra_params[:include] if extra_params[:include]
if extra_params[:order]
- params[:order] = extra_params[:order]
+ params[:order] = extra_params[:order]
params.delete(:select)
end
if extra_params[:conditions]
@@ -905,7 +924,7 @@ public
end
find(:all, params)
end
-
+
def is_old_unclassified?
return false if !awaiting_description
return false if url_title == 'holding_pen'
@@ -924,7 +943,7 @@ public
next
end
incoming_message.safe_mail_from
-
+
email = OutgoingMailer.email_for_followup(self, incoming_message)
name = OutgoingMailer.name_for_followup(self, incoming_message)
@@ -953,7 +972,7 @@ public
end
end
end
-
+
def apply_censor_rules_to_binary!(binary)
for censor_rule in self.censor_rules
censor_rule.apply_to_binary!(binary)
@@ -964,7 +983,7 @@ public
end
end
end
-
+
def is_owning_user?(user)
!user.nil? && (user.id == user_id || user.owns_every_request?)
end
@@ -973,10 +992,10 @@ public
end
def user_can_view?(user)
- if self.prominence == 'hidden'
+ if self.prominence == 'hidden'
return User.view_hidden_requests?(user)
end
- if self.prominence == 'requester_only'
+ if self.prominence == 'requester_only'
return self.is_owning_user?(user)
end
return true
@@ -1017,7 +1036,7 @@ public
end
def json_for_api(deep)
- ret = {
+ ret = {
:id => self.id,
:url_title => self.url_title,
:title => self.title,
@@ -1042,6 +1061,26 @@ public
end
return ret
end
-end
+ before_save :purge_in_cache
+ def purge_in_cache
+ if !MySociety::Config.get('VARNISH_HOST').nil? && !self.id.nil?
+ # we only do this for existing info_requests (new ones have a nil id)
+ path = url_for(:controller => 'request', :action => 'show', :url_title => self.url_title, :only_path => true, :locale => :none)
+ req = PurgeRequest.find_by_url(path)
+ if req.nil?
+ req = PurgeRequest.new(:url => path,
+ :model => self.class.base_class.to_s,
+ :model_id => self.id)
+ end
+ req.save()
+ end
+ end
+
+ def for_admin_column
+ self.class.content_columns.map{|c| c unless %w(title url_title).include?(c.name) }.compact.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
+end
diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb
index 99f34cf9e..9a4f6d9fe 100644
--- a/app/models/info_request_event.rb
+++ b/app/models/info_request_event.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: info_request_events
#
@@ -36,51 +36,57 @@ class InfoRequestEvent < ActiveRecord::Base
has_many :track_things_sent_emails
validates_presence_of :event_type
- validates_inclusion_of :event_type, :in => [
- 'sent',
- 'resent',
- 'followup_sent',
- 'followup_resent',
-
- 'edit', # title etc. edited (in admin interface)
- 'edit_outgoing', # outgoing message edited (in admin interface)
- 'edit_comment', # comment edited (in admin interface)
- 'destroy_incoming', # deleted an incoming message (in admin interface)
- 'destroy_outgoing', # deleted an outgoing message (in admin interface)
- 'redeliver_incoming', # redelivered an incoming message elsewhere (in admin interface)
- 'move_request', # changed user or public body (in admin interface)
- 'manual', # you did something in the db by hand
-
- 'response',
- 'comment',
- 'status_update'
- ]
+
+ def self.enumerate_event_types
+ [
+ 'sent',
+ 'resent',
+ 'followup_sent',
+ 'followup_resent',
+
+ 'edit', # title etc. edited (in admin interface)
+ 'edit_outgoing', # outgoing message edited (in admin interface)
+ 'edit_comment', # comment edited (in admin interface)
+ 'destroy_incoming', # deleted an incoming message (in admin interface)
+ 'destroy_outgoing', # deleted an outgoing message (in admin interface)
+ 'redeliver_incoming', # redelivered an incoming message elsewhere (in admin interface)
+ 'move_request', # changed user or public body (in admin interface)
+ 'hide', # hid a request (in admin interface)
+ 'manual', # you did something in the db by hand
+
+ 'response',
+ 'comment',
+ 'status_update'
+ ]
+ end
+
+ validates_inclusion_of :event_type, :in => enumerate_event_types
# user described state (also update in info_request)
validate :must_be_valid_state
# whether event is publicly visible
- validates_inclusion_of :prominence, :in => [
- 'normal',
+ validates_inclusion_of :prominence, :in => [
+ 'normal',
'hidden',
'requester_only'
]
def must_be_valid_state
if !described_state.nil? and !InfoRequest.enumerate_states.include?(described_state)
- errors.add(described_state, "is not a valid state")
+ errors.add(described_state, "is not a valid state")
end
end
-
+
def user_can_view?(user)
if !self.info_request.user_can_view?(user)
raise "internal error, called user_can_view? on event when there is not permission to view entire request"
end
- if self.prominence == 'hidden'
+ if self.prominence == 'hidden'
return User.view_hidden_requests?(user)
end
- if self.prominence == 'requester_only'
+ if self.prominence == 'requester_only'
return self.info_request.is_owning_user?(user)
end
return true
@@ -89,7 +95,7 @@ class InfoRequestEvent < ActiveRecord::Base
# Full text search indexing
acts_as_xapian :texts => [ :search_text_main, :title ],
- :values => [
+ :values => [
[ :created_at, 0, "range_search", :date ], # for QueryParser range searches e.g. 01/01/2008..14/01/2008
[ :created_at_numeric, 1, "created_at", :number ], # for sorting
[ :described_at_numeric, 2, "described_at", :number ], # XXX using :number for lack of :datetime support in Xapian values
@@ -106,7 +112,7 @@ class InfoRequestEvent < ActiveRecord::Base
[ :latest_status, 'L', "latest_status" ],
[ :waiting_classification, 'W', "waiting_classification" ],
[ :filetype, 'T', "filetype" ],
- [ :tags, 'U', "tag" ]
+ [ :tags, 'U', "tag" ]
],
:if => :indexed_by_search?,
:eager_load => [ :outgoing_message, :comment, { :info_request => [ :user, :public_body, :censor_rules ] } ]
@@ -115,7 +121,7 @@ class InfoRequestEvent < ActiveRecord::Base
self.info_request.user.url_name
end
def requested_from
- # acts_as_xapian will detect translated fields via Globalize and add all the
+ # acts_as_xapian will detect translated fields via Globalize and add all the
# available locales to the index. But 'requested_from' is not translated directly,
# although it relies on a translated field in PublicBody. Hence, we need to
# manually add all the localized values to the index (Xapian can handle a list
@@ -170,15 +176,15 @@ class InfoRequestEvent < ActiveRecord::Base
end
def described_at_numeric
# format it here as no datetime support in Xapian's value ranges
- return self.described_at.strftime("%Y%m%d%H%M%S")
+ return self.described_at.strftime("%Y%m%d%H%M%S")
end
def created_at_numeric
# format it here as no datetime support in Xapian's value ranges
- return self.created_at.strftime("%Y%m%d%H%M%S")
+ return self.created_at.strftime("%Y%m%d%H%M%S")
end
-
+
def incoming_message_selective_columns(fields)
- message = IncomingMessage.find(:all,
+ message = IncomingMessage.find(:all,
:select => fields + ", incoming_messages.info_request_id",
:joins => "INNER JOIN info_request_events ON incoming_messages.id = incoming_message_id ",
:conditions => "info_request_events.id = #{self.id}"
@@ -214,7 +220,7 @@ class InfoRequestEvent < ActiveRecord::Base
# performance reasons. Xapian will take the full text.
def search_text_main(clipped = false)
text = ''
- if self.event_type == 'sent'
+ if self.event_type == 'sent'
text = text + self.outgoing_message.get_text_for_indexing + "\n\n"
elsif self.event_type == 'followup_sent'
text = text + self.outgoing_message.get_text_for_indexing + "\n\n"
@@ -232,7 +238,7 @@ class InfoRequestEvent < ActiveRecord::Base
return text
end
def title
- if self.event_type == 'sent'
+ if self.event_type == 'sent'
return self.info_request.title
end
return ''
@@ -313,26 +319,26 @@ class InfoRequestEvent < ActiveRecord::Base
old_value = old_params[key].to_s
new_value = new_params[key].to_s
if old_value != new_value
- ret = ret + "<em>" + CGI.escapeHTML(key) + ":</em> "
- ret = ret +
- CGI.escapeHTML(MySociety::Format.wrap_email_body_by_lines(old_value).strip).gsub(/\n/, '<br>') +
- " => " +
+ ret = ret + "<em>" + CGI.escapeHTML(key) + ":</em> "
+ ret = ret +
+ CGI.escapeHTML(MySociety::Format.wrap_email_body_by_lines(old_value).strip).gsub(/\n/, '<br>') +
+ " => " +
CGI.escapeHTML(MySociety::Format.wrap_email_body_by_lines(new_value).strip).gsub(/\n/, '<br>')
ret = ret + "<br>"
end
end
for key, value in other_params
- ret = ret + "<em>" + CGI.escapeHTML(key.to_s) + ":</em> "
- ret = ret + CGI.escapeHTML(value.to_s.strip)
+ ret = ret + "<em>" + CGI.escapeHTML(key.to_s) + ":</em> "
+ ret = ret + CGI.escapeHTML(value.to_s.strip)
ret = ret + "<br>"
end
return ret
end
-
- def is_incoming_message?() not self.incoming_message_selective_columns("incoming_messages.id").nil? end
- def is_outgoing_message?() not self.outgoing_message.nil? end
- def is_comment?() not self.comment.nil? end
+
+ def is_incoming_message?() not self.incoming_message_selective_columns("incoming_messages.id").nil? end
+ def is_outgoing_message?() not self.outgoing_message.nil? end
+ def is_comment?() not self.comment.nil? end
# Display version of status
def display_status
@@ -402,7 +408,7 @@ class InfoRequestEvent < ActiveRecord::Base
end
def json_for_api(deep, snippet_highlight_proc = nil)
- ret = {
+ ret = {
:id => self.id,
:event_type => self.event_type,
# params_yaml has possibly sensitive data in it, don't include it
@@ -427,7 +433,7 @@ class InfoRequestEvent < ActiveRecord::Base
ret[:snippet] = snippet_highlight_proc.call(self.search_text_main(true))
end
- if deep
+ if deep
ret[:info_request] = self.info_request.json_for_api(false)
ret[:public_body] = self.info_request.public_body.json_for_api
ret[:user] = self.info_request.user.json_for_api
@@ -436,7 +442,9 @@ class InfoRequestEvent < ActiveRecord::Base
return ret
end
-
+ def for_admin_column
+ self.class.content_columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
end
-
-
diff --git a/app/models/outgoing_mailer.rb b/app/models/outgoing_mailer.rb
index bf81bb89f..8562c5b68 100644
--- a/app/models/outgoing_mailer.rb
+++ b/app/models/outgoing_mailer.rb
@@ -10,12 +10,12 @@
# separated) paragraphs, as is the convention for all the other mailers. This
# turned out to fit better with user exepectations when formatting messages.
#
-# XXX The other mail templates are written to use blank line separated
+# XXX The other mail templates are written to use blank line separated
# paragraphs. They could be rewritten, and the wrapping method made uniform
# throughout the application.
class OutgoingMailer < ApplicationMailer
-
+
# Email to public body requesting info
def initial_request(info_request, outgoing_message)
@wrap_lines_as_paragraphs = true
@@ -96,4 +96,4 @@ class OutgoingMailer < ApplicationMailer
end
end
-
+
diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb
index cc561b21d..0ce1ee11c 100644
--- a/app/models/outgoing_message.rb
+++ b/app/models/outgoing_message.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: outgoing_messages
#
@@ -37,7 +37,7 @@ class OutgoingMessage < ActiveRecord::Base
# can have many events, for items which were resent by site admin e.g. if
# contact address changed
- has_many :info_request_events
+ has_many :info_request_events
# To override the default letter
attr_accessor :default_letter
@@ -45,7 +45,7 @@ class OutgoingMessage < ActiveRecord::Base
# reindex if body text is edited (e.g. by admin interface)
after_update :xapian_reindex_after_update
def xapian_reindex_after_update
- if self.changes.include?('body')
+ if self.changes.include?('body')
for info_request_event in self.info_request_events
info_request_event.xapian_mark_needs_index
end
@@ -83,11 +83,11 @@ class OutgoingMessage < ActiveRecord::Base
"\n\n" +
"I am writing to request an internal review of " +
self.info_request.public_body.name +
- "'s handling of my FOI request " +
- "'" + self.info_request.title + "'." +
+ "'s handling of my FOI request " +
+ "'" + self.info_request.title + "'." +
"\n\n\n\n [ " + self.get_internal_review_insert_here_note + " ] \n\n\n\n" +
"A full history of my FOI request and all correspondence is available on the Internet at this address:\n" +
- "http://" + MySociety::Config.get("DOMAIN", '127.0.0.1:3000') + "/request/" + self.info_request.url_title
+ "http://" + MySociety::Config.get("DOMAIN", '127.0.0.1:3000') + "/request/" + self.info_request.url_title
else
""
end
@@ -98,7 +98,7 @@ class OutgoingMessage < ActiveRecord::Base
def set_signature_name(name)
# XXX We use raw_body here to get unstripped one
if self.raw_body == self.get_default_message
- self.body = self.raw_body + name
+ self.body = self.raw_body + name
end
end
@@ -130,7 +130,7 @@ class OutgoingMessage < ActiveRecord::Base
def contains_postcode?
MySociety::Validate.contains_postcode?(self.body)
end
-
+
# Set default letter
def after_initialize
if self.body.nil?
@@ -267,7 +267,16 @@ class OutgoingMessage < ActiveRecord::Base
end
end
+ after_save(:purge_in_cache)
+ def purge_in_cache
+ self.info_request.purge_in_cache
+ end
+ def for_admin_column
+ self.class.content_columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
end
diff --git a/app/models/post_redirect.rb b/app/models/post_redirect.rb
index 59cc86799..f613fc58d 100644
--- a/app/models/post_redirect.rb
+++ b/app/models/post_redirect.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: post_redirects
#
@@ -39,7 +39,7 @@ class PostRedirect < ActiveRecord::Base
self.post_params_yaml = params.to_yaml
end
def post_params
- if self.post_params_yaml.nil?
+ if self.post_params_yaml.nil?
return {}
end
YAML.load(self.post_params_yaml)
@@ -64,7 +64,7 @@ class PostRedirect < ActiveRecord::Base
MySociety::Util.generate_token
end
- # Make the token
+ # Make the token
def after_initialize
# The token is used to return you to what you are doing after the login form.
if not self.token
diff --git a/app/models/profile_photo.rb b/app/models/profile_photo.rb
index 43dbbbf0a..72bfe954f 100644
--- a/app/models/profile_photo.rb
+++ b/app/models/profile_photo.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: profile_photos
#
@@ -17,8 +17,6 @@
#
# $Id: profile_photo.rb,v 1.2 2009-09-17 21:10:05 francis Exp $
#
-require 'mahoro'
-require 'RMagick'
class ProfilePhoto < ActiveRecord::Base
WIDTH = 96
@@ -29,9 +27,9 @@ class ProfilePhoto < ActiveRecord::Base
belongs_to :user
# deliberately don't strip_attributes, so keeps raw photo properly
-
+
attr_accessor :x, :y, :w, :h
-
+
# convert binary data blob into ImageMagick image when assigned
attr_accessor :image
def after_initialize
@@ -47,7 +45,7 @@ class ProfilePhoto < ActiveRecord::Base
self.image = nil
return
end
-
+
self.image = image_list[0] # XXX perhaps take largest image or somesuch if there were multiple in the file?
self.convert_image
end
@@ -70,7 +68,7 @@ class ProfilePhoto < ActiveRecord::Base
# draft images are before the user has cropped them
if !self.draft && (image.columns != WIDTH || image.rows != HEIGHT)
# do any exact cropping (taken from Jcrop interface)
- if self.w && self.h
+ if self.w && self.h
image.crop!(self.x.to_i, self.y.to_i, self.w.to_i, self.h.to_i)
end
# do any further cropping
@@ -100,7 +98,7 @@ class ProfilePhoto < ActiveRecord::Base
if self.image.format != 'PNG'
errors.add(:data, N_("Failed to convert image to a PNG"))
end
-
+
if !self.draft && (self.image.columns != WIDTH || self.image.rows != HEIGHT)
errors.add(:data, N_("Failed to convert image to the correct size: at %{cols}x%{rows}, need %{width}x%{height}" % { :cols => self.image.columns, :rows => self.image.rows, :width => WIDTH, :height => HEIGHT }))
end
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index 90e9395ae..267b5d60c 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 95
+# Schema version: 114
#
# Table name: public_bodies
#
@@ -58,11 +58,11 @@ class PublicBody < ActiveRecord::Base
short_long_name = t.short_name if t.short_name and !t.short_name.empty?
t.url_name = MySociety::Format.simplify_url_part(short_long_name, 'body')
end
-
+
def translated_versions
translations
end
-
+
def translated_versions=(translation_attrs)
def skip?(attrs)
valueless = attrs.inject({}) { |h, (k, v)| h[k] = v if v != '' and k != 'locale'; h } # because we want to fall back to alternative translations where there are empty values
@@ -86,7 +86,7 @@ class PublicBody < ActiveRecord::Base
end
end
end
-
+
# Make sure publication_scheme gets the correct default value.
# (This would work automatically, were publication_scheme not a translated attribute)
def after_initialize
@@ -96,7 +96,7 @@ class PublicBody < ActiveRecord::Base
# like find_by_url_name but also search historic url_name if none found
def self.find_by_url_name_with_historic(name)
locale = self.locale || I18n.locale
- PublicBody.with_locale(locale) do
+ PublicBody.with_locale(locale) do
found = PublicBody.find(:all,
:conditions => ["public_body_translations.url_name='#{name}'"],
:joins => :translations,
@@ -189,18 +189,37 @@ class PublicBody < ActiveRecord::Base
text = text.gsub(/\n/, '<br>')
return text
end
+
+ def compare(previous = nil)
+ if previous.nil?
+ yield([])
+ else
+ v = self
+ changes = self.class.content_columns.inject([]) {|memo, c|
+ unless %w(version last_edit_editor last_edit_comment updated_at).include?(c.name)
+ from = previous.send(c.name)
+ to = self.send(c.name)
+ memo << { :name => c.human_name, :from => from, :to => to } if from != to
+ end
+ memo
+ }
+ changes.each do |change|
+ yield(change)
+ end
+ end
+ end
end
acts_as_xapian :texts => [ :name, :short_name, :notes ],
- :values => [
+ :values => [
[ :created_at_numeric, 1, "created_at", :number ] # for sorting
],
:terms => [ [ :variety, 'V', "variety" ],
- [ :tag_array_for_search, 'U', "tag" ]
+ [ :tag_array_for_search, 'U', "tag" ]
]
def created_at_numeric
# format it here as no datetime support in Xapian's value ranges
- return self.created_at.strftime("%Y%m%d%H%M%S")
+ return self.created_at.strftime("%Y%m%d%H%M%S")
end
def variety
return "authority"
@@ -236,7 +255,7 @@ class PublicBody < ActiveRecord::Base
def update_url_name
self.url_name = MySociety::Format.simplify_url_part(self.short_or_long_name, 'body')
end
-
+
# Return the short name if present, or else long name
def short_or_long_name
if self.short_name.nil? || self.short_name.empty? # 'nil' can happen during construction
@@ -253,7 +272,7 @@ class PublicBody < ActiveRecord::Base
first = true
for tag in self.tags
if PublicBodyCategories::get().by_tag().include?(tag.name)
- desc = PublicBodyCategories::get().singular_by_tag()[tag.name]
+ desc = PublicBodyCategories::get().singular_by_tag()[tag.name]
if first
# terrible that Ruby/Rails doesn't have an equivalent of ucfirst
# (capitalize shockingly converts later characters to lowercase)
@@ -270,7 +289,7 @@ class PublicBody < ActiveRecord::Base
if types.size > 0
ret = types[0, types.size - 1].join(", ")
if types.size > 1
- ret = ret + " and "
+ ret = ret + " and "
end
ret = ret + types[-1]
return ret
@@ -282,19 +301,11 @@ class PublicBody < ActiveRecord::Base
# Guess home page from the request email, or use explicit override, or nil
# if not known.
def calculated_home_page
- # manual override for ones we calculate wrongly
- if self.home_page != ''
- return self.home_page
- end
-
- # extract the domain name from the FOI request email
- url = self.request_email_domain
- if url.nil?
- return nil
+ if home_page && !home_page.empty?
+ home_page[URI::regexp(%w(http https))] ? home_page : "http://#{home_page}"
+ elsif request_email_domain
+ "http://www.#{request_email_domain}"
end
-
- # add standard URL prefix
- return "http://www." + url
end
# Are all requests to this body under the Environmental Information Regulations?
@@ -359,12 +370,12 @@ class PublicBody < ActiveRecord::Base
for existing_body in bodies
# Hide InternalAdminBody from import notes
next if existing_body.id == PublicBody.internal_admin_body.id
-
+
bodies_by_name[existing_body.name] = existing_body
set_of_existing.add(existing_body.name)
end
end
-
+
set_of_importing = Set.new()
field_names = { 'name'=>1, 'request_email'=>2 } # Default values in case no field list is given
line = 0
@@ -380,7 +391,7 @@ class PublicBody < ActiveRecord::Base
fields = {}
field_names.each{|name, i| fields[name] = row[i]}
-
+
name = row[field_names['name']]
email = row[field_names['request_email']]
next if name.nil?
@@ -392,7 +403,7 @@ class PublicBody < ActiveRecord::Base
errors.push "error: line #{line.to_s}: invalid email '#{email}' for authority '#{name}'"
next
end
-
+
field_list = ['name', 'short_name', 'request_email', 'notes', 'publication_scheme', 'home_page', 'tag_string']
if public_body = bodies_by_name[name] # Existing public body
@@ -402,7 +413,7 @@ class PublicBody < ActiveRecord::Base
field_list.each do |field_name|
localized_field_name = (locale.to_s == I18n.default_locale.to_s) ? field_name : "#{field_name}.#{locale}"
localized_value = field_names[localized_field_name] && row[field_names[localized_field_name]]
-
+
# Tags are a special case, as we support adding to the field, not just setting a new value
if localized_field_name == 'tag_string'
if localized_value.nil?
@@ -410,11 +421,11 @@ class PublicBody < ActiveRecord::Base
else
if tag_behaviour == 'add'
localized_value = "#{localized_value} #{tag}" unless tag.empty?
- localized_value = "#{localized_value} #{public_body.tag_string}"
+ localized_value = "#{localized_value} #{public_body.tag_string}"
end
end
end
-
+
if !localized_value.nil? and public_body.send(field_name) != localized_value
changed[field_name] = "#{public_body.send(field_name)}: #{localized_value}"
public_body.send("#{field_name}=", localized_value)
@@ -424,14 +435,14 @@ class PublicBody < ActiveRecord::Base
unless changed.empty?
notes.push "line #{line.to_s}: updating authority '#{name}' (locale: #{locale}):\n\t#{changed.to_json}"
public_body.last_edit_editor = editor
- public_body.last_edit_comment = 'Updated from spreadsheet'
+ public_body.last_edit_comment = 'Updated from spreadsheet'
public_body.save!
end
end
end
else # New public body
public_body = PublicBody.new(:name=>"", :short_name=>"", :request_email=>"")
- available_locales.each do |locale|
+ available_locales.each do |locale|
PublicBody.with_locale(locale) do
changed = ActiveSupport::OrderedHash.new
field_list.each do |field_name|
@@ -441,7 +452,7 @@ class PublicBody < ActiveRecord::Base
if localized_field_name == 'tag_string' and tag_behaviour == 'add'
localized_value = "#{localized_value} #{tag}" unless tag.empty?
end
-
+
if !localized_value.nil? and public_body.send(field_name) != localized_value
changed[field_name] = localized_value
public_body.send("#{field_name}=", localized_value)
@@ -452,7 +463,7 @@ class PublicBody < ActiveRecord::Base
notes.push "line #{line.to_s}: creating new authority '#{name}' (locale: #{locale}):\n\t#{changed.to_json}"
public_body.publication_scheme = public_body.publication_scheme || ""
public_body.last_edit_editor = editor
- public_body.last_edit_comment = 'Created from spreadsheet'
+ public_body.last_edit_comment = 'Created from spreadsheet'
public_body.save!
end
end
@@ -462,7 +473,7 @@ class PublicBody < ActiveRecord::Base
set_of_importing.add(name)
end
- # Give an error listing ones that are to be deleted
+ # Give an error listing ones that are to be deleted
deleted_ones = set_of_existing - set_of_importing
if deleted_ones.size > 0
notes.push "Notes: Some " + tag + " bodies are in database, but not in CSV file:\n " + Array(deleted_ones).sort.join("\n ") + "\nYou may want to delete them manually.\n"
@@ -527,7 +538,7 @@ class PublicBody < ActiveRecord::Base
end
def has_notes?
- return self.notes != ""
+ return !self.notes.nil? && self.notes != ""
end
def notes_as_html
self.notes
@@ -538,7 +549,7 @@ class PublicBody < ActiveRecord::Base
end
def json_for_api
- return {
+ return {
:id => self.id,
:url_name => self.url_name,
:name => self.name,
@@ -546,7 +557,7 @@ class PublicBody < ActiveRecord::Base
# :request_email # we hide this behind a captcha, to stop people doing bulk requests easily
:created_at => self.created_at,
:updated_at => self.updated_at,
- # don't add the history as some edit comments contain sensitive information
+ # don't add the history as some edit comments contain sensitive information
# :version, :last_edit_editor, :last_edit_comment
:home_page => self.calculated_home_page,
:notes => self.notes,
@@ -555,6 +566,17 @@ class PublicBody < ActiveRecord::Base
}
end
+ after_save(:purge_in_cache)
+ def purge_in_cache
+ self.info_requests.each {|x| x.purge_in_cache}
+ end
+
+ def for_admin_column
+ self.class.content_columns.map{|c| c unless %w(name last_edit_comment).include?(c.name)}.compact.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
+
end
diff --git a/app/models/purge_request.rb b/app/models/purge_request.rb
new file mode 100644
index 000000000..48a16f9e6
--- /dev/null
+++ b/app/models/purge_request.rb
@@ -0,0 +1,52 @@
+# == Schema Information
+# Schema version: 114
+#
+# Table name: purge_requests
+#
+# id :integer not null, primary key
+# url :string(255)
+# created_at :datetime not null
+# model :string(255) not null
+# model_id :integer not null
+#
+
+# models/purge_request.rb:
+# A queue of URLs to purge
+#
+# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved.
+# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
+#
+
+class PurgeRequest < ActiveRecord::Base
+ def self.purge_all
+ done_something = false
+ for item in PurgeRequest.all()
+ item.purge
+ done_something = true
+ end
+ return done_something
+ end
+
+ def self.purge_all_loop
+ # Run purge_all in an endless loop, sleeping when there is nothing to do
+ while true
+ sleep_seconds = 1
+ while !purge_all
+ sleep sleep_seconds
+ sleep_seconds *= 2
+ sleep_seconds = 30 if sleep_seconds > 30
+ end
+ end
+ end
+
+ def purge
+ config = MySociety::Config.load_default()
+ varnish_url = config['VARNISH_HOST']
+ result = quietly_try_to_purge(varnish_url, self.url)
+ self.delete()
+ end
+end
+
+
+
+
diff --git a/app/models/raw_email.rb b/app/models/raw_email.rb
index 3e12a6feb..1466e5d9c 100644
--- a/app/models/raw_email.rb
+++ b/app/models/raw_email.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: raw_emails
#
@@ -16,7 +16,7 @@
class RawEmail < ActiveRecord::Base
# deliberately don't strip_attributes, so keeps raw email properly
-
+
has_one :incoming_message
# We keep the old data_text field (which is of type text) for backwards
@@ -27,10 +27,10 @@ class RawEmail < ActiveRecord::Base
def directory
request_id = self.incoming_message.info_request.id.to_s
if ENV["RAILS_ENV"] == "test"
- return File.join(RAILS_ROOT, 'files/raw_email_test')
+ return File.join(Rails.root, 'files/raw_email_test')
else
return File.join(MySociety::Config.get('RAW_EMAILS_LOCATION',
- 'files/raw_emails'),
+ 'files/raw_emails'),
request_id[0..2], request_id)
end
end
diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb
index 83cce9045..1b0bb48b9 100644
--- a/app/models/request_mailer.rb
+++ b/app/models/request_mailer.rb
@@ -9,7 +9,7 @@
require 'alaveteli_file_types'
class RequestMailer < ApplicationMailer
-
+
# Used when an FOI officer uploads a response from their web browser - this is
# the "fake" email used to store in the same format in the database as if they
@@ -38,20 +38,25 @@ class RequestMailer < ApplicationMailer
@subject = "Your response to an FOI request was not delivered"
attachment :content_type => 'message/rfc822', :body => raw_email_data,
:filename => "original.eml", :transfer_encoding => '7bit', :content_disposition => 'inline'
- @body = {
+ @body = {
:info_request => info_request,
- :contact_email => MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost')
+ :contact_email => MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost')
}
end
# An FOI response is outside the scope of the system, and needs admin attention
- def requires_admin(info_request)
- @from = info_request.user.name_and_email
+ def requires_admin(info_request, set_by = nil)
+ if !set_by.nil?
+ user = set_by
+ else
+ user = info_request.user
+ end
+ @from = user.name_and_email
@recipients = contact_from_name_and_email
- @subject = _("FOI response requires admin - ") + info_request.title
+ @subject = _("FOI response requires admin ({{reason}}) - {{title}}", :reason => info_request.described_state, :title => info_request.title)
url = main_url(request_url(info_request))
admin_url = request_admin_url(info_request)
- @body = {:info_request => info_request, :url => url, :admin_url => admin_url }
+ @body = {:reported_by => user, :info_request => info_request, :url => url, :admin_url => admin_url }
end
# Tell the requester that a new response has arrived
@@ -142,7 +147,7 @@ class RequestMailer < ApplicationMailer
# Tell the requester that they need to clarify their request
def not_clarified_alert(info_request, incoming_message)
respond_url = show_response_url(:id => info_request.id, :incoming_message_id => incoming_message.id)
- respond_url = respond_url + "#followup"
+ respond_url = respond_url + "#followup"
post_redirect = PostRedirect.new(
:uri => respond_url,
@@ -155,7 +160,7 @@ class RequestMailer < ApplicationMailer
'Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834
'X-Auto-Response-Suppress' => 'OOF'
@recipients = info_request.user.name_and_email
- @subject = "Clarify your FOI request - " + info_request.title
+ @subject = _("Clarify your FOI request - ") + info_request.title
@body = { :incoming_message => incoming_message, :info_request => info_request, :url => url }
end
@@ -182,7 +187,7 @@ class RequestMailer < ApplicationMailer
# Class function, called by script/mailin with all incoming responses.
# [ This is a copy (Monkeypatch!) of function from action_mailer/base.rb,
# but which additionally passes the raw_email to the member function, as we
- # want to record it.
+ # want to record it.
#
# That is because we want to be sure we properly record the actual message
# received in its raw form - so any information won't be lost in a round
@@ -215,7 +220,7 @@ class RequestMailer < ApplicationMailer
# Find which info requests the email is for
reply_info_requests = self.requests_matching_email(email)
# Nothing found, so save in holding pen
- if reply_info_requests.size == 0
+ if reply_info_requests.size == 0
reason = _("Could not identify the request from the email address")
request = InfoRequest.holding_pen_request
request.receive(email, raw_email, false, reason)
@@ -225,7 +230,7 @@ class RequestMailer < ApplicationMailer
# Send the message to each request, to be archived with it
for reply_info_request in reply_info_requests
# If environment variable STOP_DUPLICATES is set, don't send message with same id again
- if ENV['STOP_DUPLICATES']
+ if ENV['STOP_DUPLICATES']
if reply_info_request.already_received?(email, raw_email)
raise "message " + email.message_id + " already received by request"
end
@@ -275,7 +280,7 @@ class RequestMailer < ApplicationMailer
end
end
- # Send email alerts for new responses which haven't been classified. By default,
+ # Send email alerts for new responses which haven't been classified. By default,
# it goes out 3 days after last update of event, then after 10, then after 24.
def self.alert_new_response_reminders
MySociety::Config.get("NEW_RESPONSE_REMINDER_AFTER_DAYS", [3, 10, 24]).each_with_index do |days, i|
@@ -283,10 +288,10 @@ class RequestMailer < ApplicationMailer
end
end
def self.alert_new_response_reminders_internal(days_since, type_code)
- info_requests = InfoRequest.find_old_unclassified(:order => 'info_requests.id',
- :include => [:user],
+ info_requests = InfoRequest.find_old_unclassified(:order => 'info_requests.id',
+ :include => [:user],
:age_in_days => days_since)
-
+
for info_request in info_requests
alert_event_id = info_request.get_last_response_event_id
last_response_message = info_request.get_last_response
@@ -302,7 +307,7 @@ class RequestMailer < ApplicationMailer
store_sent.user = info_request.user
store_sent.alert_type = type_code
store_sent.info_request_event_id = alert_event_id
- # XXX uses same template for reminder 1 and reminder 2 right now.
+ # XXX uses same template for reminder 1 and reminder 2 right now.
RequestMailer.deliver_new_response_reminder_alert(info_request, last_response_message)
store_sent.save!
end
@@ -340,11 +345,11 @@ class RequestMailer < ApplicationMailer
# Send email alert to request submitter for new comments on the request.
def self.alert_comment_on_request()
-
+
# We only check comments made in the last month - this means if the
# cron jobs broke for more than a month events would be lost, but no
# matter. I suspect the performance gain will be needed (with an index on updated_at)
-
+
# XXX the :order part info_request_events.created_at is a work around
# for a very old Rails bug which means eager loading does not respect
# association orders.
@@ -352,7 +357,7 @@ class RequestMailer < ApplicationMailer
# http://lists.rubyonrails.org/pipermail/rails-core/2006-July/001798.html
# That that patch has not been applied, despite bribes of beer, is
# typical of the lack of quality of Rails.
-
+
info_requests = InfoRequest.find(:all,
:conditions => [
"info_requests.id in (
diff --git a/app/models/track_mailer.rb b/app/models/track_mailer.rb
index 0c053c4ad..92da7c376 100644
--- a/app/models/track_mailer.rb
+++ b/app/models/track_mailer.rb
@@ -47,8 +47,8 @@ class TrackMailer < ApplicationMailer
return done_something
end
for user in users
- next if !user.should_be_emailed?
-
+ next if !user.should_be_emailed? || !user.receive_email_alerts
+
email_about_things = []
track_things = TrackThing.find(:all, :conditions => [ "tracking_user_id = ? and track_medium = ?", user.id, 'email_daily' ])
for track_thing in track_things
@@ -56,7 +56,7 @@ class TrackMailer < ApplicationMailer
#
# We only use track_things_sent_emails records which are less than 14 days old.
# In the search query loop below, we also only use items described in last 7 days.
- # An item described that recently definitely can't appear in track_things_sent_emails
+ # An item described that recently definitely can't appear in track_things_sent_emails
# earlier, so this is safe (with a week long margin of error). If the alerts break
# for a whole week, then they will miss some items. Tough.
done_info_request_events = {}
@@ -70,7 +70,7 @@ class TrackMailer < ApplicationMailer
# Query for things in this track. We use described_at for the
# ordering, so we catch anything new (before described), or
# anything whose new status has been described.
- xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 100, 1)
+ xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 100, 1)
# Go through looking for unalerted things
alert_results = []
for result in xapian_object.results
@@ -86,7 +86,7 @@ class TrackMailer < ApplicationMailer
alert_results.push(result)
end
# If there were more alerts for this track, then store them
- if alert_results.size > 0
+ if alert_results.size > 0
email_about_things.push([track_thing, alert_results, xapian_object])
end
end
diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb
index 58d70ed86..d0fc62e12 100644
--- a/app/models/track_thing.rb
+++ b/app/models/track_thing.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: track_things
#
@@ -35,17 +35,17 @@ class TrackThing < ActiveRecord::Base
has_many :track_things_sent_emails
- validates_inclusion_of :track_type, :in => [
- 'request_updates',
+ validates_inclusion_of :track_type, :in => [
+ 'request_updates',
'all_new_requests',
'all_successful_requests',
- 'public_body_updates',
+ 'public_body_updates',
'user_updates',
'search_query'
]
- validates_inclusion_of :track_medium, :in => [
- 'email_daily',
+ validates_inclusion_of :track_medium, :in => [
+ 'email_daily',
'feed'
]
@@ -69,7 +69,7 @@ class TrackThing < ActiveRecord::Base
end
def track_query_description
- # XXX this is very brittle... we should probably ask users
+ # XXX this is very brittle... we should probably ask users
# simply to name their tracks when they make them?
original_text = parsed_text = self.track_query.gsub(/([()]|OR)/, "")
filters = parsed_text.scan /\b\S+:\S+\b/
@@ -101,14 +101,14 @@ class TrackThing < ActiveRecord::Base
end
if filter =~ /waiting/
statuses << _("awaiting a response")
- end
+ end
end
if filters.empty?
parsed_text = original_text
end
descriptions = []
if varieties.include? _("requests")
- descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).join(_(' or ')))
+ descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).sort.join(_(' or ')))
varieties -= [_("requests")]
end
if descriptions.empty? and varieties.empty?
@@ -116,7 +116,7 @@ class TrackThing < ActiveRecord::Base
end
descriptions += Array(varieties)
parsed_text = parsed_text.strip
- descriptions = descriptions.join(_(" or "))
+ descriptions = descriptions.sort.join(_(" or "))
if !parsed_text.empty?
descriptions += _("{{list_of_things}} matching text '{{search_query}}'", :list_of_things => "", :search_query => parsed_text)
end
@@ -146,11 +146,15 @@ class TrackThing < ActiveRecord::Base
return track_thing
end
- def TrackThing.create_track_for_public_body(public_body)
+ def TrackThing.create_track_for_public_body(public_body, event_type = nil)
track_thing = TrackThing.new
track_thing.track_type = 'public_body_updates'
track_thing.public_body = public_body
- track_thing.track_query = "requested_from:" + public_body.url_name
+ query = "requested_from:" + public_body.url_name
+ if InfoRequestEvent.enumerate_event_types.include?(event_type)
+ query += " variety:" + event_type
+ end
+ track_thing.track_query = query
return track_thing
end
@@ -171,10 +175,10 @@ class TrackThing < ActiveRecord::Base
query += " variety:sent"
when "users"
query += " variety:user"
- when "authorities"
- query += " variety:authority"
+ when "bodies"
+ query += " variety:authority"
end
- end
+ end
track_thing.track_query = query
# XXX should extract requested_by:, request:, requested_from:
# and stick their values into the respective relations.
@@ -192,15 +196,15 @@ class TrackThing < ActiveRecord::Base
@params = {
# Website
:list_description => _("'{{link_to_request}}', a request", :link_to_request => "<a href=\"/request/" + CGI.escapeHTML(self.info_request.url_title) + "\">" + CGI.escapeHTML(self.info_request.title) + "</a>"), # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how
- :verb_on_page => _("Track this request by email"),
- :verb_on_page_already => _("You are already tracking this request by email"),
+ :verb_on_page => _("Follow this request"),
+ :verb_on_page_already => _("You are already following this request"),
# Email
:title_in_email => _("New updates for the request '{{request_title}}'", :request_title => self.info_request.title),
:title_in_rss => _("New updates for the request '{{request_title}}'", :request_title => self.info_request.title),
# Authentication
- :web => _("To follow updates to the request '{{request_title}}'", :request_title => CGI.escapeHTML(self.info_request.title)),
- :email => _("Then you will be emailed whenever the request '{{request_title}}' is updated.", :request_title => CGI.escapeHTML(self.info_request.title)),
- :email_subject => _("Confirm you want to follow updates to the request '{{request_title}}'", :request_title => self.info_request.title),
+ :web => _("To follow the request '{{request_title}}'", :request_title => CGI.escapeHTML(self.info_request.title)),
+ :email => _("Then you will be updated whenever the request '{{request_title}}' is updated.", :request_title => CGI.escapeHTML(self.info_request.title)),
+ :email_subject => _("Confirm you want to follow the request '{{request_title}}'", :request_title => self.info_request.title),
# RSS sorting
:feed_sortby => 'newest'
}
@@ -208,15 +212,15 @@ class TrackThing < ActiveRecord::Base
@params = {
# Website
:list_description => _("any <a href=\"/list\">new requests</a>"),
- :verb_on_page => _("Email me when there are new requests"),
- :verb_on_page_already => _("You are being emailed when there are new requests"),
+ :verb_on_page => _("Follow all new requests"),
+ :verb_on_page_already => _("You are already following new requests"),
# Email
:title_in_email => _("New Freedom of Information requests"),
:title_in_rss => _("New Freedom of Information requests"),
# Authentication
- :web => _("To be emailed about any new requests"),
- :email => _("Then you will be emailed whenever anyone makes a new FOI request."),
- :email_subject => _("Confirm you want to be emailed about new requests"),
+ :web => _("To follow new requests"),
+ :email => _("Then you will be following all new FOI requests."),
+ :email_subject => _("Confirm you want to follow new requests"),
# RSS sorting
:feed_sortby => 'newest'
}
@@ -224,15 +228,15 @@ class TrackThing < ActiveRecord::Base
@params = {
# Website
:list_description => _("any <a href=\"/list/successful\">successful requests</a>"),
- :verb_on_page => _("Email me new successful responses "),
- :verb_on_page_already => _("You are being emailed about any new successful responses"),
+ :verb_on_page => _("Follow new successful responses"),
+ :verb_on_page_already => _("You are following all new successful responses"),
# Email
:title_in_email => _("Successful Freedom of Information requests"),
:title_in_rss => _("Successful Freedom of Information requests"),
# Authentication
- :web => _("To be emailed about any successful requests"),
- :email => _("Then you will be emailed whenever an FOI request succeeds."),
- :email_subject => _("Confirm you want to be emailed when an FOI request succeeds"),
+ :web => _("To follow all successful requests"),
+ :email => _("Then you will be notified whenever an FOI request succeeds."),
+ :email_subject => _("Confirm you want to follow all successful FOI requests"),
# RSS sorting - used described date, as newest would give a
# date for responses possibly days before description, so
# wouldn't appear at top of list when description (known
@@ -243,15 +247,15 @@ class TrackThing < ActiveRecord::Base
@params = {
# Website
:list_description => _("'{{link_to_authority}}', a public authority", :link_to_authority => "<a href=\"/body/" + CGI.escapeHTML(self.public_body.url_name) + "\">" + CGI.escapeHTML(self.public_body.name) + "</a>"), # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how
- :verb_on_page => _("Track requests to {{public_body_name}} by email",:public_body_name=>CGI.escapeHTML(self.public_body.name)),
- :verb_on_page_already => _("You are already tracking requests to {{public_body_name}} by email", :public_body_name=>CGI.escapeHTML(self.public_body.name)),
+ :verb_on_page => _("Follow requests to {{public_body_name}}",:public_body_name=>CGI.escapeHTML(self.public_body.name)),
+ :verb_on_page_already => _("You are already following requests to {{public_body_name}}", :public_body_name=>CGI.escapeHTML(self.public_body.name)),
# Email
:title_in_email => self.public_body.law_only_short + " requests to '" + self.public_body.name + "'",
:title_in_rss => self.public_body.law_only_short + " requests to '" + self.public_body.name + "'",
# Authentication
- :web => _("To be emailed about requests made using {{site_name}} to the public authority '{{public_body_name}}'", :site_name=>MySociety::Config.get('SITE_NAME', 'Alaveteli'), :public_body_name=>CGI.escapeHTML(self.public_body.name)),
- :email => _("Then you will be emailed whenever someone requests something or gets a response from '{{public_body_name}}'.", :public_body_name=>CGI.escapeHTML(self.public_body.name)),
- :email_subject => _("Confirm you want to be emailed about requests to '{{public_body_name}}'", :public_body_name=>self.public_body.name),
+ :web => _("To follow requests made using {{site_name}} to the public authority '{{public_body_name}}'", :site_name=>MySociety::Config.get('SITE_NAME', 'Alaveteli'), :public_body_name=>CGI.escapeHTML(self.public_body.name)),
+ :email => _("Then you will be notified whenever someone requests something or gets a response from '{{public_body_name}}'.", :public_body_name=>CGI.escapeHTML(self.public_body.name)),
+ :email_subject => _("Confirm you want to follow requests to '{{public_body_name}}'", :public_body_name=>self.public_body.name),
# RSS sorting
:feed_sortby => 'newest'
}
@@ -259,15 +263,15 @@ class TrackThing < ActiveRecord::Base
@params = {
# Website
:list_description => _("'{{link_to_user}}', a person", :link_to_user => "<a href=\"/user/" + CGI.escapeHTML(self.tracked_user.url_name) + "\">" + CGI.escapeHTML(self.tracked_user.name) + "</a>"), # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how
- :verb_on_page => _("Track this person by email"),
- :verb_on_page_already => _("You are already tracking this person by email"),
+ :verb_on_page => _("Follow this person"),
+ :verb_on_page_already => _("You are already following this person"),
# Email
:title_in_email => _("FOI requests by '{{user_name}}'", :user_name=>self.tracked_user.name),
:title_in_rss => _("FOI requests by '{{user_name}}'", :user_name=>self.tracked_user.name),
# Authentication
- :web => _("To be emailed about requests by '{{user_name}}'", :user_name=>CGI.escapeHTML(self.tracked_user.name)),
- :email => _("Then you will be emailed whenever '{{user_name}}' requests something or gets a response.", :user_name=>CGI.escapeHTML(self.tracked_user.name)),
- :email_subject => _("Confirm you want to be emailed about requests by '{{user_name}}'", :user_name=>self.tracked_user.name),
+ :web => _("To follow requests by '{{user_name}}'", :user_name=>CGI.escapeHTML(self.tracked_user.name)),
+ :email => _("Then you will be notified whenever '{{user_name}}' requests something or gets a response.", :user_name=>CGI.escapeHTML(self.tracked_user.name)),
+ :email_subject => _("Confirm you want to follow requests by '{{user_name}}'", :user_name=>self.tracked_user.name),
# RSS sorting
:feed_sortby => 'newest'
}
@@ -275,15 +279,15 @@ class TrackThing < ActiveRecord::Base
@params = {
# Website
:list_description => "<a href=\"/search/" + CGI.escapeHTML(self.track_query) + "/newest/advanced\">" + self.track_query_description + "</a>", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how
- :verb_on_page => _("Track things matching this search by email"),
- :verb_on_page_already => _("You are already tracking things matching this search by email"),
+ :verb_on_page => _("Follow things matching this search"),
+ :verb_on_page_already => _("You are already following things matching this search"),
# Email
:title_in_email => _("Requests or responses matching your saved search"),
:title_in_rss => _("Requests or responses matching your saved search"),
# Authentication
:web => _("To follow requests and responses matching your search"),
- :email => _("Then you will be emailed whenever a new request or response matches your search."),
- :email_subject => _("Confirm you want to be emailed about new requests or responses matching your search"),
+ :email => _("Then you will be notified whenever a new request or response matches your search."),
+ :email_subject => _("Confirm you want to follow new requests or responses matching your search"),
# RSS sorting - XXX hmmm, we don't really know which to use
# here for sorting. Might be a query term (e.g. 'cctv'), in
# which case newest is good, or might be something like
diff --git a/app/models/track_things_sent_email.rb b/app/models/track_things_sent_email.rb
index 777339d75..24297f57b 100644
--- a/app/models/track_things_sent_email.rb
+++ b/app/models/track_things_sent_email.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: track_things_sent_emails
#
diff --git a/app/models/user.rb b/app/models/user.rb
index 59a84b7aa..a21676f68 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: users
#
@@ -20,6 +20,8 @@
# email_bounced_at :datetime
# email_bounce_message :text default(""), not null
# no_limit :boolean default(FALSE), not null
+# receive_email_alerts :boolean default(TRUE), not null
+# user_similarity_id :integer
#
# models/user.rb:
@@ -52,22 +54,22 @@ class User < ActiveRecord::Base
attr_accessor :password_confirmation, :no_xapian_reindex
validates_confirmation_of :password, :message => _("Please enter the same password twice")
- validates_inclusion_of :admin_level, :in => [
+ validates_inclusion_of :admin_level, :in => [
'none',
- 'super',
+ 'super',
], :message => N_('Admin level is not included in list')
acts_as_xapian :texts => [ :name, :about_me ],
- :values => [
+ :values => [
[ :created_at_numeric, 1, "created_at", :number ] # for sorting
],
:terms => [ [ :variety, 'V', "variety" ] ],
:if => :indexed_by_search?
def created_at_numeric
# format it here as no datetime support in Xapian's value ranges
- return self.created_at.strftime("%Y%m%d%H%M%S")
+ return self.created_at.strftime("%Y%m%d%H%M%S")
end
-
+
def variety
"user"
end
@@ -79,7 +81,7 @@ class User < ActiveRecord::Base
if self.new_record?
# make alert emails go out at a random time for each new user, so
# overall they are spread out throughout the day.
- self.last_daily_track_email = User.random_time_in_last_day
+ self.last_daily_track_email = User.random_time_in_last_day
end
end
@@ -101,7 +103,7 @@ class User < ActiveRecord::Base
end
end
end
-
+
def get_locale
if !self.locale.nil?
locale = self.locale
@@ -117,10 +119,10 @@ class User < ActiveRecord::Base
def validate
if self.email != "" && !MySociety::Validate.is_valid_email(self.email)
- errors.add(:email, _("Please enter a valid email address"))
+ errors.add(:email, _("Please enter a valid email address"))
end
if MySociety::Validate.is_valid_email(self.name)
- errors.add(:name, _("Please enter your name, not your email address, in the name field."))
+ errors.add(:name, _("Please enter your name, not your email address, in the name field."))
end
end
@@ -139,7 +141,7 @@ class User < ActiveRecord::Base
end
# Return user given login email, password and other form parameters (e.g. name)
- #
+ #
# The specific_user_login parameter says that login as a particular user is
# expected, so no parallel registration form is being displayed.
def User.authenticate_from_form(params, specific_user_login = false)
@@ -235,10 +237,10 @@ class User < ActiveRecord::Base
# changed more than a day ago)
def get_undescribed_requests
self.info_requests.find(
- :all,
- :conditions => [ 'awaiting_description = ? and ' + InfoRequest.last_event_time_clause + ' < ?',
- true, Time.now() - 1.day
- ]
+ :all,
+ :conditions => [ 'awaiting_description = ? and ' + InfoRequest.last_event_time_clause + ' < ?',
+ true, Time.now() - 1.day
+ ]
)
end
@@ -256,7 +258,7 @@ class User < ActiveRecord::Base
def owns_every_request?
self.admin_level == 'super'
end
-
+
def User.owns_every_request?(user)
!user.nil? && user.owns_every_request?
end
@@ -271,7 +273,7 @@ class User < ActiveRecord::Base
def User.stay_logged_in_on_redirect?(user)
!user.nil? && user.admin_level == 'super'
end
-
+
# Does the user get "(admin)" links on each page on the main site?
def admin_page_links?
self.admin_level == 'super'
@@ -287,21 +289,21 @@ class User < ActiveRecord::Base
def exceeded_limit?
# Some users have no limit
return false if self.no_limit
-
+
# Has the user issued as many as MAX_REQUESTS_PER_USER_PER_DAY requests in the past 24 hours?
daily_limit = MySociety::Config.get("MAX_REQUESTS_PER_USER_PER_DAY")
return false if daily_limit.nil?
recent_requests = InfoRequest.count(:conditions => ["user_id = ? and created_at > now() - '1 day'::interval", self.id])
-
+
return (recent_requests >= daily_limit)
end
def next_request_permitted_at
return nil if self.no_limit
-
+
daily_limit = MySociety::Config.get("MAX_REQUESTS_PER_USER_PER_DAY")
n_most_recent_requests = InfoRequest.all(:conditions => ["user_id = ? and created_at > now() - '1 day'::interval", self.id], :order => "created_at DESC", :limit => daily_limit)
return nil if n_most_recent_requests.size < daily_limit
-
+
nth_most_recent_request = n_most_recent_requests[-1]
return nth_most_recent_request.created_at + 1.day
end
@@ -375,7 +377,7 @@ class User < ActiveRecord::Base
end
def json_for_api
- return {
+ return {
:id => self.id,
:url_name => self.url_name,
:name => self.name,
@@ -391,36 +393,55 @@ class User < ActiveRecord::Base
self.email_bounce_message = message
self.save!
end
-
+
def should_be_emailed?
return (self.email_confirmed && self.email_bounced_at.nil?)
end
-
+
def indexed_by_search?
return self.email_confirmed
end
+ def for_admin_column(complete = false)
+ if complete
+ columns = self.class.content_columns
+ else
+ columns = self.class.content_columns.map{|c| c if %w(created_at updated_at admin_level email_confirmed).include?(c.name) }.compact
+ end
+ columns.each do |column|
+ yield(column.human_name, self.send(column.name), column.type.to_s, column.name)
+ end
+ end
+
## Private instance methods
private
def create_new_salt
self.salt = self.object_id.to_s + rand.to_s
end
-
+
## Class methods
def User.encrypted_password(password, salt)
string_to_hash = password + salt # XXX need to add a secret here too?
Digest::SHA1.hexdigest(string_to_hash)
end
-
+
def User.record_bounce_for_email(email, message)
user = User.find_user_by_email(email)
return false if user.nil?
-
+
if user.email_bounced_at.nil?
user.record_bounce(message)
end
return true
end
+
+ after_save(:purge_in_cache)
+ def purge_in_cache
+ if self.name_changed?
+ self.info_requests.each {|x| x.purge_in_cache}
+ end
+ end
+
end
diff --git a/app/models/user_info_request_sent_alert.rb b/app/models/user_info_request_sent_alert.rb
index 5f23355bf..a97fd5d44 100644
--- a/app/models/user_info_request_sent_alert.rb
+++ b/app/models/user_info_request_sent_alert.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 108
+# Schema version: 114
#
# Table name: user_info_request_sent_alerts
#
@@ -23,7 +23,7 @@ class UserInfoRequestSentAlert < ActiveRecord::Base
belongs_to :user
belongs_to :info_request
- validates_inclusion_of :alert_type, :in => [
+ validates_inclusion_of :alert_type, :in => [
'overdue_1', # tell user that info request has become overdue
'very_overdue_1', # tell user that info request has become very overdue
'new_response_reminder_1', # reminder user to classify the recent response
diff --git a/app/views/admin_general/debug.rhtml b/app/views/admin_general/debug.rhtml
index 40fe33616..d7bf1c6da 100644
--- a/app/views/admin_general/debug.rhtml
+++ b/app/views/admin_general/debug.rhtml
@@ -7,6 +7,8 @@
<h2>Version numbers</h2>
<p>
+Alaveteli version: <%= link_to @current_version, @github_origin + @current_version %>
+<br>
Alaveteli branch: <%= link_to @current_branch, @github_origin + @current_branch %>
<br>
Alaveteli commit: <%= link_to @current_commit, @github_origin + @current_commit %>
diff --git a/app/views/admin_general/index.rhtml b/app/views/admin_general/index.rhtml
index 1a4b8ba96..48bd7f694 100644
--- a/app/views/admin_general/index.rhtml
+++ b/app/views/admin_general/index.rhtml
@@ -46,6 +46,20 @@
</ul>
<% end %>
+<% if @attention_requests.size > 0 %>
+ <h3>Review requests which have been marked as requiring your attention by users (<%=@error_message_requests.size%> total)</h3>
+
+ <ul>
+ <% for @request in @attention_requests %>
+ <li>
+ <%= request_both_links(@request)%>
+ &ndash; <%=simple_date(@request.get_last_event.created_at)%>
+ </li>
+ <% end %>
+ </ul>
+<% end %>
+
+
<% if @requires_admin_requests.size > 0 %>
<h3>These require administrator attention (<%=@requires_admin_requests.size%> total)</h3>
diff --git a/app/views/admin_general/timeline.rhtml b/app/views/admin_general/timeline.rhtml
index 39a4b3e36..eecab4823 100644
--- a/app/views/admin_general/timeline.rhtml
+++ b/app/views/admin_general/timeline.rhtml
@@ -65,6 +65,8 @@
had incoming message deleted by administrator <strong><%=h event.params[:editor] %></strong>.
<% elsif event.event_type == 'destroy_outgoing' %>
had outgoing message deleted by administrator <strong><%=h event.params[:editor] %></strong>.
+ <% elsif event.event_type == 'hide' %>
+ was hidden by administrator <strong><%=h event.params[:editor] %></strong>.
<% elsif event.event_type == 'redeliver_outgoing' %>
had incoming message redelivered to another request by administrator <strong><%=h event.params[:editor] %></strong>.
<% elsif event.event_type == 'response' %>
diff --git a/app/views/admin_request/_incoming_message_actions.rhtml b/app/views/admin_request/_incoming_message_actions.rhtml
index c23b4060a..569132861 100644
--- a/app/views/admin_request/_incoming_message_actions.rhtml
+++ b/app/views/admin_request/_incoming_message_actions.rhtml
@@ -1,6 +1,6 @@
<% form_tag '../redeliver_incoming' do %>
<div>
- id or url_title of request:
+ id or url_title of request (or a list of requests, comma-separated):
<% if @info_requests && @info_requests.size == 1 %>
<%= text_field_tag 'url_title', @info_requests[0].url_title, { :size => 20 } %>
<% else %>
diff --git a/app/views/admin_request/edit.rhtml b/app/views/admin_request/edit.rhtml
index b659c676d..4026ee712 100644
--- a/app/views/admin_request/edit.rhtml
+++ b/app/views/admin_request/edit.rhtml
@@ -22,20 +22,7 @@
</p>
<p><label for="info_request_described_state"><strong>Described state</strong></label>
- <%= select( 'info_request', "described_state",
- [
- 'waiting_response',
- 'waiting_clarification',
- 'gone_postal',
- 'not_held',
- 'rejected',
- 'successful',
- 'partially_successful',
- 'internal_review',
- 'error_message',
- 'requires_admin',
- 'user_withdrawn'
- ]) %>;
+ <%= select( 'info_request', "described_state", InfoRequest.enumerate_states ) %>;
<label for="info_request_awaiting_description"><strong>Awaiting description</strong></label>
<%= select('info_request', "awaiting_description", [["Yes - needs state updating",true],["No - state is up to date",false]]) %>
<br/>(don't forget to change 'awaiting description' when you set described state)<br/>
@@ -60,7 +47,7 @@
<hr>
-<% form_tag '../fully_destroy/' + @info_request.id.to_s do %>
+<% form_tag '../destroy/' + @info_request.id.to_s do %>
<p>
<strong>This is permanent and irreversible!</strong> <%= submit_tag 'Destory request entirely' %>
<br>Use it mainly if someone posts private information, e.g. made a Data Protection request. It
diff --git a/app/views/admin_request/hidden_user_explanation.rhtml b/app/views/admin_request/hidden_user_explanation.rhtml
new file mode 100644
index 000000000..64387ffee
--- /dev/null
+++ b/app/views/admin_request/hidden_user_explanation.rhtml
@@ -0,0 +1,9 @@
+Dear <%= name_to %>,
+
+Your request '<%= info_request.title %>' at <%= info_request_url %> has been reviewed by moderators.
+
+We consider it <% if reason == 'not_foi' %>is not a valid FOI request<% else %>to be vexatious<% end%>, and have therefore hidden it from other users. You will still be able to view it while logged in to the site. Please reply to this email if you would like to discuss this decision further.
+
+Yours,
+
+The <%= site_name %> team.
diff --git a/app/views/contact_mailer/from_admin_message.rhtml b/app/views/contact_mailer/from_admin_message.rhtml
new file mode 100644
index 000000000..bdb48d580
--- /dev/null
+++ b/app/views/contact_mailer/from_admin_message.rhtml
@@ -0,0 +1,2 @@
+<%= @message.strip %>
+
diff --git a/app/views/general/_locale_switcher.rhtml b/app/views/general/_locale_switcher.rhtml
index 27e492e84..2521b5eb5 100644
--- a/app/views/general/_locale_switcher.rhtml
+++ b/app/views/general/_locale_switcher.rhtml
@@ -1,11 +1,13 @@
- <% if FastGettext.default_available_locales.length > 1 && !params.empty? %>
- <div id="user_locale_switcher">
- <% for possible_locale in FastGettext.default_available_locales %>
- <% if possible_locale == I18n.locale.to_s %>
- <span class="active"><%= locale_name(possible_locale) %></span>
- <% else %>
- <a href="<%= locale_switcher(possible_locale, params) %>"><%= locale_name(possible_locale) %></a>
- <% end %>
- <% end %>
+ <% if FastGettext.default_available_locales.length > 1 && !params.empty? %>
+ <div id="user_locale_switcher">
+ <div class="btn-group">
+ <% for possible_locale in FastGettext.default_available_locales %>
+ <% if possible_locale == I18n.locale.to_s %>
+ <a href="#" class="btn disabled"><%= locale_name(possible_locale) %></a>
+ <% else %>
+ <a href="<%= locale_switcher(possible_locale, params) %>" class="btn"><%= locale_name(possible_locale) %></a>
+ <% end %>
+ <% end %>
</div>
- <% end %>
+ </div>
+ <% end %>
diff --git a/app/views/general/_orglink.rhtml b/app/views/general/_orglink.rhtml
index 7d74dbaac..fbe688d85 100644
--- a/app/views/general/_orglink.rhtml
+++ b/app/views/general/_orglink.rhtml
@@ -1,2 +1,2 @@
-<%-# Put the link to your organisation here, or leave blank -%>
-<%= link_to image_tag('logo.png'), frontpage_url, :id=>'logo' %>
+<%# Put the link to your organisation here, or leave blank %>
+<%= link_to image_tag('logo.png'), frontpage_url, :id=>'logo' %>
diff --git a/app/views/general/search.rhtml b/app/views/general/search.rhtml
index 90ace809e..a1f8c8f04 100644
--- a/app/views/general/search.rhtml
+++ b/app/views/general/search.rhtml
@@ -131,8 +131,7 @@
</p>
<% end %>
</div> <!-- header left -->
-
-<% if @track_thing && (@xapian_bodies_hits > 0 || @xapian_users_hits > 0 || @total_hits == 0)%>
+<% if !@track_thing.nil? %>
<div id="header_right">
<h2><%= _('Track this search')%></h2>
<%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => false, :location => 'main' } %>
diff --git a/app/views/layouts/admin.rhtml b/app/views/layouts/admin.rhtml
index 42ca5dbbb..d85eecbf2 100644
--- a/app/views/layouts/admin.rhtml
+++ b/app/views/layouts/admin.rhtml
@@ -9,19 +9,19 @@
<%= stylesheet_link_tag 'admin-theme/jquery-ui-1.8.15.custom.css', :rel => 'stylesheet'%>
<%= stylesheet_link_tag 'admin', :title => "Main", :rel => "stylesheet" %>
</head>
- <body>
+ <body class="admin">
<p>
<strong><%= link_to 'Alaveteli', main_url('/') %> admin:</strong>
- <%= link_to 'Summary', admin_general_index_path %>
- | <%= link_to 'Timeline', admin_timeline_path %>
- | <%= link_to 'Stats', admin_stats_path %>
- | <%= link_to 'Debug', admin_debug_path %>
+ <%= link_to 'Summary', admin_url("") %>
+ | <%= link_to 'Timeline', admin_url("timeline") %>
+ | <%= link_to 'Stats', admin_url("stats") %>
+ | <%= link_to 'Debug', admin_url("debug") %>
<strong>View:</strong>
- <%= link_to 'Authorities', admin_body_list_path %>
- | <%= link_to 'Requests', admin_request_list_path %>
- | <%= link_to 'Users', admin_user_list_path %>
- | <%= link_to 'Tracks', admin_track_list_path %>
+ <%= link_to 'Authorities', admin_url("body/list") %>
+ | <%= link_to 'Requests', admin_url("request/list") %>
+ | <%= link_to 'Users', admin_url("user/list") %>
+ | <%= link_to 'Tracks', admin_url("track/list") %>
</p>
<%= render :partial => 'general/locale_switcher' %>
diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml
index f439b27d2..ed0a52e85 100644
--- a/app/views/layouts/default.rhtml
+++ b/app/views/layouts/default.rhtml
@@ -58,7 +58,7 @@
<%= render :partial => 'general/before_head_end' %>
</head>
- <body <%= "class='front'" if params[:action] == 'frontpage' %>>
+ <body class="<%= 'admin' if !session[:using_admin].nil?%> <%= 'front' if params[:action] == 'frontpage' %>">
<!-- XXX: move to a separate file -->
<% if force_registration_on_new_request && !@user %>
@@ -104,6 +104,7 @@
<% if @user %>
<%=link_to _("My requests"), show_user_requests_path(:url_name => @user.url_name) %>
<%=link_to _("My profile"), show_user_profile_path(:url_name => @user.url_name) %>
+ <%=link_to _("My wall"), show_user_wall_path(:url_name => @user.url_name) %>
<% end %>
@@ -146,7 +147,6 @@
<%= render :partial => 'general/footer' %>
- <%= render :partial => 'general/before_body_end' %>
</div>
<div id="other-country-notice"></div>
<div id="link_box"><span class="close-button">X</span>
@@ -154,6 +154,22 @@
<br />
<input type="text">
</div>
+ <%
+ ga_code = MySociety::Config.get('GA_CODE', '')
+
+ unless ga_code.empty? %>
+ <script>
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
+ </script>
+ <script>
+ var pageTracker = _gat._getTracker("<%=ga_code%>");
+ pageTracker._trackPageview();
+ </script>
+
+ <% end %>
+
+ <%= render :partial => 'general/before_body_end' %>
</body>
</html>
diff --git a/app/views/public_body/show.rhtml b/app/views/public_body/show.rhtml
index 5f20a9717..63bd5f7fc 100644
--- a/app/views/public_body/show.rhtml
+++ b/app/views/public_body/show.rhtml
@@ -4,7 +4,7 @@
<h2><%= _('Follow this authority')%></h2>
<% follower_count = TrackThing.count(:all, :conditions => ["public_body_id = ?", @public_body.id]) %>
- <p><%= n_("There is %d person following this authority", "There are %d people following this authority", follower_count) % follower_count %></p>
+ <p><%= n_("<span id='follow_count'>%d</span> person is following this authority", "<span id='follow_count'>%d</span> people are following this authority", follower_count) % follower_count %></p>
<%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => false, :location => 'sidebar' } %>
<h2><%= _('More about this authority')%></h2>
diff --git a/app/views/request/_bubble.rhtml b/app/views/request/_bubble.rhtml
index 87079e9ea..331c2163e 100644
--- a/app/views/request/_bubble.rhtml
+++ b/app/views/request/_bubble.rhtml
@@ -13,7 +13,7 @@
:file_name => a.display_filename + '.html')
%>
<% img_filename = "icon_" + a.content_type.sub('/', '_') + "_large.png"
- full_filename = File.join(File.dirname(__FILE__), "../../../public/images", img_filename)
+ full_filename = File.expand_path(File.join(File.dirname(__FILE__), "../../../public/images", img_filename))
if File.exist?(full_filename) %>
<a href="<%=attachment_url%>"><img class="attachment_image" alt="Attachment" src="/images/<%=img_filename%>"></a>
<% else %>
diff --git a/app/views/request/_sidebar.rhtml b/app/views/request/_sidebar.rhtml
index 758387b09..d6d5e8f12 100644
--- a/app/views/request/_sidebar.rhtml
+++ b/app/views/request/_sidebar.rhtml
@@ -1,10 +1,33 @@
<div id="right_column">
+ <div id="follow_box">
<h2><%= _('Follow this request') %></h2>
<% follower_count = TrackThing.count(:all, :conditions => ["info_request_id = ?", @info_request.id]) + 1 %>
<p><%= n_("There is %d person following this request", "There are %d people following this request", follower_count) % follower_count %></p>
<%= render :partial => 'track/tracking_links', :locals => { :track_thing => @track_thing, :own_request => @info_request.user == @user, :location => 'sidebar' } %>
-
+ </div>
+ <% if @info_request.described_state != "attention_requested" %>
+ <h2><%= _('Offensive? Unsuitable?') %></h2>
+ <% if @info_request.attention_requested %>
+ <% if @info_request.prominence == 'hidden' %>
+ <%# The eccentric formatting of the following string is in order that it be identical
+ to the corresponding string in request/show.rhtml %>
+ <p><%= _('This request has prominence \'hidden\'. You can only see it because you are logged
+ in as a super user.') %></p>
+ <% elsif @info_request.prominence == 'requester_only' %>
+ <%# The eccentric formatting of the following string is in order that it be identical
+ to the corresponding string in request/show.rhtml %>
+ <p><%= _('This request is hidden, so that only you the requester can see it. Please
+ <a href="%s">contact us</a> if you are not sure why.') % [help_requesting_path] %></p>
+ <% else %>
+ <p><%= _('This request has been marked for review by the site administrators, who have not hidden it at this time. If you believe it should be hidden, please <a href="%s">contact us</a>.') % [help_requesting_path] %></p>
+ <% end %>
+ <% else %>
+ <p><%= _('Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href="/help/about">read more</a>).') %>
+ <p><%= ('If you believe this request is not suitable, you can report it for attention by the site administrators') %></p>
+ <%= link_to _("Report this request"), report_path, :class => "link_button_green", :method => "POST" %>
+ <% end %>
+ <% end %>
<h2><%= _("Act on what you've learnt") %></h2>
<div class="act_link">
diff --git a/app/views/request/_wall_listing.rhtml b/app/views/request/_wall_listing.rhtml
new file mode 100644
index 000000000..9cde234c0
--- /dev/null
+++ b/app/views/request/_wall_listing.rhtml
@@ -0,0 +1,30 @@
+<% if @highlight_words.nil?
+ @highlight_words = []
+end %>
+
+<div class="request_listing">
+ <div class="request_left">
+ <div class="requester">
+ <% if event.event_type == 'sent' %>
+ <%= _('A new request, <em><a href="{{request_url}}">{{request_title}}</a></em>, was sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>user_link_absolute(info_request.user),:date=>simple_date(event.created_at),:request_url=>request_url(info_request),:request_title=>info_request.title) %>
+ <% elsif event.event_type == 'followup_sent' %>
+ <%= _('A <a href="{{request_url}}">follow up</a> to <em>{{request_title}}</em> was sent to {{public_body_name}} by {{info_request_user}} on {{date}}.',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>user_link_absolute(info_request.user),:date=>simple_date(event.created_at),:request_url=>outgoing_message_url(event.outgoing_message),:request_title=>info_request.title) %>
+ <% elsif event.event_type == 'response' %>
+ <%= _('A <a href="{{request_url}}">response</a> to <em>{{request_title}}</em> was sent by {{public_body_name}} to {{info_request_user}} on {{date}}. The request status is: {{request_status}}',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>user_link_absolute(info_request.user),:date=>simple_date(event.created_at),:request_url=>incoming_message_url(event.incoming_message_selective_columns("incoming_messages.id")),:request_title=>info_request.title,:request_status=>info_request.display_status) %>
+ <% elsif event.event_type == 'comment' %>
+ <%= _('An <a href="{{request_url}}">annotation</a> to <em>{{request_title}}</em> was made by {{event_comment_user}} on {{date}}',:public_body_name=>public_body_link_absolute(info_request.public_body),:info_request_user=>user_link_absolute(info_request.user),:event_comment_user=>user_link_absolute(event.comment.user),:date=>simple_date(event.created_at),:request_url=>comment_url(event.comment),:request_title=>info_request.title) %>
+ <% else %>
+ <%# Events of other types will not be indexed: see InfoRequestEvent#indexed_by_search?
+ However, it can happen that we see other types of event transiently here in the period
+ between a change being made and the update-xapian-index job being run. %>
+ <!-- Event of type '<%= event.event_type %>', id=<%= event.id %> -->
+ <% end %>
+ </div>
+ </div>
+ <div class="request_right">
+ <span class="desc">
+ <%= highlight_and_excerpt(event.search_text_main(true), @highlight_words, 150) %>
+ </span>
+ </div>
+</div>
+
diff --git a/app/views/request/show.rhtml b/app/views/request/show.rhtml
index c5d040fb7..27ad0700e 100644
--- a/app/views/request/show.rhtml
+++ b/app/views/request/show.rhtml
@@ -1,4 +1,6 @@
-<% @title = "#{h(@info_request.title)} - a Freedom of Information request to #{h(@info_request.public_body.name)}" %>
+<% @title = _("{{title}} - a Freedom of Information request to {{public_body}}",
+ :title => h(@info_request.title),
+ :public_body => (@info_request.public_body.name)) %>
<% if @info_request.prominence == 'hidden' %>
<p id="hidden_request">
@@ -72,7 +74,7 @@
<%= _('normally') %>
<% end %>
<%= _('no later than') %> <strong><%= simple_date(@info_request.date_response_required_by) %></strong>
- (<%= link_to "details", "/help/requesting#quickly_response" %>).
+ (<%= link_to _("details"), "/help/requesting#quickly_response" %>).
<% elsif @status == 'waiting_response_overdue' %>
<%= _('Response to this request is <strong>delayed</strong>.') %>
<%= _('By law, {{public_body_link}} should normally have responded <strong>promptly</strong> and',:public_body_link=>public_body_link(@info_request.public_body)) %>
@@ -116,6 +118,12 @@
<% elsif @status == 'user_withdrawn' %>
<%= _('This request has been <strong>withdrawn</strong> by the person who made it.
There may be an explanation in the correspondence below.') %>
+ <% elsif @status == 'attention_requested' %>
+ <%= _('This request has been <strong>reported</strong> as needing administrator attention (perhaps because it is vexatious, or a request for personal information)') %>
+ <% elsif @status == 'vexatious' %>
+ <%= _('This request has been <strong>hidden</strong> from the site, because an administrator considers it vexatious') %>
+ <% elsif @status == 'not_foi' %>
+ <%= _('This request has been <strong>hidden</strong> from the site, because an administrator considers it not to be an FOI request') %>
<% else %>
<%= render :partial => 'general/custom_state_descriptions', :locals => { :status => @status } %>
<% end %>
diff --git a/app/views/request_mailer/not_clarified_alert.rhtml b/app/views/request_mailer/not_clarified_alert.rhtml
index 82d15ba76..2408452b3 100644
--- a/app/views/request_mailer/not_clarified_alert.rhtml
+++ b/app/views/request_mailer/not_clarified_alert.rhtml
@@ -1,5 +1,7 @@
-<%=@info_request.public_body.name%> <%=('has asked you to explain part of your')%> <%=@info_request.law_used_short%> <%= _('request.')%>
-<%= _('To do this, first click on the link below.')%>
+<%= _('{{public_body}} has asked you to explain part of your {{law_used}} request.',
+ :public_body => @info_request.public_body.name,
+ :law_used => @info_request.law_used_short ) %>
+<%= _('To do this, first click on the link below.') %>
<%=@url%>
diff --git a/app/views/request_mailer/requires_admin.rhtml b/app/views/request_mailer/requires_admin.rhtml
index acd37f405..06a798792 100644
--- a/app/views/request_mailer/requires_admin.rhtml
+++ b/app/views/request_mailer/requires_admin.rhtml
@@ -1,5 +1,5 @@
---------------------------------------------------------------------
-<%=@info_request.user.name%> <%= _('has reported an')%> <%=@info_request.law_used_short%>
+<%=@reported_by.name%> <%= _('has reported an')%> <%=@info_request.law_used_short%>
<%= _('response as needing administrator attention. Take a look, and reply to this
email to let them know what you are going to do about it.')%>
diff --git a/app/views/track/_tracking_links.rhtml b/app/views/track/_tracking_links.rhtml
index f50a8bbbf..39f346eff 100644
--- a/app/views/track/_tracking_links.rhtml
+++ b/app/views/track/_tracking_links.rhtml
@@ -7,18 +7,17 @@
<% if own_request %>
<p><%= _('This is your own request, so you will be automatically emailed when new responses arrive.')%></p>
<% elsif existing_track %>
- <% form_tag({:controller => 'track', :action => 'update', :track_id => existing_track.id}, :class => "feed_form feed_form_" + location) do %>
- <p>
- <%= track_thing.params[:verb_on_page_already] %>
- <%= hidden_field_tag 'track_medium', "delete" %>
- <%= hidden_field_tag 'r', request.request_uri %>
- <%= submit_tag "unsubscribe" %>
- </p>
- <% end %>
+ <p><%= track_thing.params[:verb_on_page_already] %></p>
+ <div class="feed_link feed_link_<%=location%>">
+ <%= link_to "Unsubscribe", {:controller => 'track', :action => 'update', :track_id => existing_track.id, :track_medium => "delete", :r => request.request_uri}, :class => "link_button_green" %>
+ </div>
<% elsif track_thing %>
<div class="feed_link feed_link_<%=location%>">
- <%= link_to '<img src="/images/email-16.png" alt="">', do_track_url(track_thing) %>
- <%= link_to _("Follow by email"), do_track_url(track_thing) %>
+ <% if defined? follower_count && follower_count > 0 %>
+ <%= link_to _("I like this request"), do_track_url(track_thing), :class => "link_button_green" %>
+ <% else %>
+ <%= link_to _("Follow"), do_track_url(track_thing), :class => "link_button_green" %>
+ <% end %>
</div>
<div class="feed_link feed_link_<%=location%>">
diff --git a/app/views/user/_change_receive_email.rhtml b/app/views/user/_change_receive_email.rhtml
new file mode 100644
index 000000000..83e5d8601
--- /dev/null
+++ b/app/views/user/_change_receive_email.rhtml
@@ -0,0 +1,16 @@
+<% form_tag(:controller=>"user", :action=>"set_receive_email_alerts") do %>
+ <div>
+ <% if @user.receive_email_alerts %>
+ <%= _('You are currently receiving notification of new activity on your wall by email.', :wall_url => show_user_wall_path) %><br><br>
+ <%= hidden_field_tag 'receive_email_alerts', 'false' %>
+ <%= hidden_field_tag 'came_from', request.url %>
+ <%= submit_tag _("Turn off email alerts") %>
+ <% else %>
+ <%= _('Items matching the following conditions are currently displayed on your wall.') %><br><br>
+ <%= hidden_field_tag 'receive_email_alerts', 'true' %>
+ <%= hidden_field_tag 'came_from', request.url %>
+ <%= submit_tag _("Also send me alerts by email") %>
+ <% end %>
+ </div>
+<% end %>
+
diff --git a/app/views/user/confirm.rhtml b/app/views/user/confirm.rhtml
index bdaf5c8e9..bc70a1f36 100644
--- a/app/views/user/confirm.rhtml
+++ b/app/views/user/confirm.rhtml
@@ -1,6 +1,6 @@
-<% @title = h("Now check your email!") %>
+<% @title = _("Now check your email!") %>
-<h1 class="confirmation_heading">Now check your email!</h1>
+<h1 class="confirmation_heading"><%= _("Now check your email!") %></h1>
<p class="confirmation_message">
<%= _('We\'ve sent you an email, and you\'ll need to click the link in it before you can
diff --git a/app/views/user/rate_limited.rhtml b/app/views/user/rate_limited.rhtml
index 2a770d62e..d5accf114 100644
--- a/app/views/user/rate_limited.rhtml
+++ b/app/views/user/rate_limited.rhtml
@@ -1,4 +1,4 @@
-<% @title = "Too many requests" %>
+<% @title = _("Too many requests") %>
<h1><%=@title%></h1>
diff --git a/app/views/user/show.rhtml b/app/views/user/show.rhtml
index 8f1803442..d723196d3 100644
--- a/app/views/user/show.rhtml
+++ b/app/views/user/show.rhtml
@@ -1,7 +1,7 @@
<% if @show_requests %>
- <% @title = h(@display_user.name) + " - Freedom of Information requests" %>
+ <% @title = h(@display_user.name) + _(" - Freedom of Information requests") %>
<% else %>
- <% @title = h(@display_user.name) + " - user profile" %>
+ <% @title = h(@display_user.name) + _(" - user profile") %>
<% end %>
<% if (@same_name_users.size >= 1) %>
@@ -139,7 +139,7 @@
<% if !@xapian_requests.nil? %>
<% if @xapian_requests.results.empty? %>
<% if @page == 1 %>
- <h2 class="foi_results" id="foi_requests"><%= @is_you ? 'Freedom of Information requests made by you' : 'Freedom of Information requests made by this person' %> <%= @match_phrase %>
+ <h2 class="foi_results" id="foi_requests"><%= @is_you ? _('Freedom of Information requests made by you') : _('Freedom of Information requests made by this person') %> <%= @match_phrase %>
</h2>
<p><%= @is_you ? _('You have made no Freedom of Information requests using this site.') : _('This person has made no Freedom of Information requests using this site.') %>
<%= @page_desc %>
@@ -192,11 +192,12 @@
</div>
<% end %>
<% if @show_profile && @is_you %>
+ <h2 id="email_subscriptions"> <%= _("Things you're following")%></h2>
+ <%= render :partial => 'change_receive_email' %>
+ <br>
<% if @track_things.empty? %>
- <h2 id="email_subscriptions"> <%= _('Your email subscriptions')%></h2>
- <p><%= _('None made.')%></p>
+ <p><%= _("You're not following anything.")%></p>
<% else %>
- <h2 id="email_subscriptions"> Your <%=pluralize(@track_things.size, _('email subscription')) %> </h2>
<% if @track_things_grouped.size == 1 %>
<% form_tag({:controller => 'track', :action => 'delete_all_type'}, :class => "feed_form") do %>
<h3>
diff --git a/app/views/user/sign.rhtml b/app/views/user/sign.rhtml
index bfd0fa63e..4704ea95a 100644
--- a/app/views/user/sign.rhtml
+++ b/app/views/user/sign.rhtml
@@ -10,7 +10,10 @@
<%= @post_redirect.reason_params[:web] %>,
<%= _('please sign in as ')%><%= link_to h(@post_redirect.reason_params[:user_name]), @post_redirect.reason_params[:user_url] %>.
<% end %>
- </p>
+ </p>
+ <% if @post_redirect.post_params["controller"] == "admin_general" %>
+ <p id="superuser_message">Don't have a superuser account yet? <%= link_to "Sign in as the emergency user", @post_redirect.uri + "?emergency=1" %></p>
+ <% end %>
<%= render :partial => 'signin', :locals => { :sign_in_as_existing_user => true } %>
diff --git a/app/views/user/wall.rhtml b/app/views/user/wall.rhtml
new file mode 100644
index 000000000..190cc0a6d
--- /dev/null
+++ b/app/views/user/wall.rhtml
@@ -0,0 +1,16 @@
+<% @title = h(@display_user.name) + _(" - wall") %>
+<% if @is_you %>
+<div class="medium_column">
+ <p><%= _('You can change the requests and users you are following on <a href="{{profile_url}}">your profile page</a>.', :profile_url => show_user_profile_path) %>
+ <%= render :partial => 'change_receive_email' %>
+</div>
+<% end %>
+<div id="user_profile_search">
+ <% if !@feed_results.nil? %>
+ <% for result in @feed_results %>
+ <%= render :partial => 'request/wall_listing', :locals => { :event => result, :info_request => result.info_request } %>
+ <% end %>
+ <% end %>
+
+
+</div>