diff options
Diffstat (limited to 'app')
46 files changed, 360 insertions, 137 deletions
diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb index e192d097c..c83ae0f37 100644 --- a/app/controllers/admin_general_controller.rb +++ b/app/controllers/admin_general_controller.rb @@ -30,6 +30,7 @@ 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, :conditions => ["prominence = 'normal'"]) @@ -80,6 +81,7 @@ class AdminGeneralController < AdminController def debug @current_commit = `git log -1 --format="%H"` @current_branch = `git branch | grep "\*" | awk '{print $2}'` + @current_version = `git describe --always --tags` 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 diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb index 3c700c567..522e1cd39 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 @@ -162,32 +173,36 @@ class AdminRequestController < AdminController 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 @@ -297,7 +312,7 @@ class AdminRequestController < AdminController # 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,24 @@ class AdminRequestController < AdminController redirect_to request_admin_url(info_request_event.info_request) end + def hide_request + ActiveRecord::Base.transaction do + explanation = params[:explanation] + info_request = InfoRequest.find(params[:id]) + info_request.set_described_state(params[:reason]) + info_request.prominence = "requester_only" + info_request.save! + + ContactMailer.deliver_from_admin_message( + info_request.user, + "hello", + 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/request_controller.rb b/app/controllers/request_controller.rb index af142c530..94fbcde29 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -654,6 +654,19 @@ class RequestController < ApplicationController end end + def report_request + info_request = InfoRequest.find_by_url_title(params[:url_title]) + if !info_request.attention_requested + info_request.set_described_state('attention_requested') + 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 diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 225790d71..28dd2143d 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -21,4 +21,15 @@ class ServicesController < ApplicationController 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/helpers/application_helper.rb b/app/helpers/application_helper.rb index df89a372c..df016a249 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 : {} @@ -113,5 +116,19 @@ 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) + "#{I18n.l(date, :format => "%e %B %Y %H:%M:%S")} (#{_('{{length_of_time}} ago', :length_of_time => time_ago_in_words(date))})" + end + end diff --git a/app/helpers/link_to_helper.rb b/app/helpers/link_to_helper.rb index 914b4dc12..f621721b6 100755 --- a/app/helpers/link_to_helper.rb +++ b/app/helpers/link_to_helper.rb @@ -17,14 +17,18 @@ module LinkToHelper 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 @@ -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)) @@ -86,8 +90,8 @@ module LinkToHelper 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 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 80f0d7289..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 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 80db96c64..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 # 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 74c213c7a..800fe54e4 100644 --- a/app/models/contact_mailer.rb +++ b/app/models/contact_mailer.rb @@ -42,4 +42,16 @@ 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, + } + 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 2c6bea4f8..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 # 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 1906b56db..f3e3d7e00 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 # diff --git a/app/models/holiday.rb b/app/models/holiday.rb index 1fa599c13..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 # diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index 8de6e5ba8..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 @@ -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. @@ -674,7 +674,6 @@ class IncomingMessage < ActiveRecord::Base 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 text = text.gsub(/\r\n/, "\n") @@ -865,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! @@ -1029,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 @@ -1133,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 3b86f4cb3..095a1b1af 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,6 +17,7 @@ # 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) # @@ -88,7 +89,10 @@ class InfoRequest < ActiveRecord::Base 'internal_review', 'error_message', 'requires_admin', - 'user_withdrawn' + 'user_withdrawn', + 'attention_requested', + 'vexatious', + 'not_foi' ] if @@custom_states_loaded states += InfoRequest.theme_extra_states @@ -503,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? @@ -511,6 +515,9 @@ 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) ActiveRecord::Base.transaction do @@ -667,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 @@ -803,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) @@ -1059,6 +1076,11 @@ public req.save() end 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 9ce191f6b..a410328b0 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 # @@ -39,25 +39,26 @@ class InfoRequestEvent < ActiveRecord::Base 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) - 'manual', # you did something in the db by hand - - 'response', - 'comment', - 'status_update', + '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' ] end + validates_inclusion_of :event_type, :in => enumerate_event_types # user described state (also update in info_request) @@ -440,7 +441,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_message.rb b/app/models/outgoing_message.rb index 29445d587..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 # @@ -271,6 +271,12 @@ class OutgoingMessage < ActiveRecord::Base 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 2b636453f..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 # diff --git a/app/models/profile_photo.rb b/app/models/profile_photo.rb index 6c66d868a..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 # diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 0e21037ef..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 # @@ -189,6 +189,25 @@ 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 ], @@ -552,6 +571,12 @@ class PublicBody < ActiveRecord::Base 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 index 088d5b84b..48a16f9e6 100644 --- a/app/models/purge_request.rb +++ b/app/models/purge_request.rb @@ -1,3 +1,15 @@ +# == 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 # @@ -37,3 +49,4 @@ end + diff --git a/app/models/raw_email.rb b/app/models/raw_email.rb index 29122e692..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 # diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb index e336111ee..8e6e65a26 100644 --- a/app/models/request_mailer.rb +++ b/app/models/request_mailer.rb @@ -48,7 +48,7 @@ class RequestMailer < ApplicationMailer def requires_admin(info_request) @from = info_request.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 } @@ -155,7 +155,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 diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb index 797902443..7f6bc9a7e 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 # 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 cd8d3e721..57fce429c 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: @@ -400,6 +402,17 @@ class User < ActiveRecord::Base 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) + end + end + ## Private instance methods private diff --git a/app/models/user_info_request_sent_alert.rb b/app/models/user_info_request_sent_alert.rb index 15cac515f..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 # 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)%> + – <%=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_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..aaea49fb6 --- /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. 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/layouts/admin.rhtml b/app/views/layouts/admin.rhtml index 42ca5dbbb..65670538d 100644 --- a/app/views/layouts/admin.rhtml +++ b/app/views/layouts/admin.rhtml @@ -9,7 +9,7 @@ <%= 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> diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml index 7d36b74a3..bc9dfb02d 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 %> diff --git a/app/views/request/_sidebar.rhtml b/app/views/request/_sidebar.rhtml index 5304ec312..bca142fa9 100644 --- a/app/views/request/_sidebar.rhtml +++ b/app/views/request/_sidebar.rhtml @@ -3,9 +3,19 @@ <h2><%= _('Follow this request') %></h2> <% follower_count = TrackThing.count(:all, :conditions => ["info_request_id = ?", @info_request.id]) + 1 %> - <p class="follow_count"><%= n_("<span id='follow_count'>%d</span> person is following this request", "<span id='follow_count'>%d</span> people are 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', :follower_count => follower_count } %> - </div> + <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 %> + <p><%= ('The site administrators have reviewed this request and consider it to be suitable for the website.') %></p> + <% 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" %> + <% end %> + <% end %> <h2><%= _("Act on what you've learnt") %></h2> <div class="act_link"> diff --git a/app/views/request/show.rhtml b/app/views/request/show.rhtml index 611704ebe..27ad0700e 100644 --- a/app/views/request/show.rhtml +++ b/app/views/request/show.rhtml @@ -74,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)) %> @@ -118,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/track/_tracking_links.rhtml b/app/views/track/_tracking_links.rhtml index 18d4b372a..39f346eff 100644 --- a/app/views/track/_tracking_links.rhtml +++ b/app/views/track/_tracking_links.rhtml @@ -14,7 +14,7 @@ <% elsif track_thing %> <div class="feed_link feed_link_<%=location%>"> <% if defined? follower_count && follower_count > 0 %> - <%= link_to _("I want to know, too"), do_track_url(track_thing), :class => "link_button_green" %> + <%= 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 %> 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> |