diff options
Diffstat (limited to 'app/controllers')
-rw-r--r-- | app/controllers/admin_general_controller.rb | 4 | ||||
-rw-r--r-- | app/controllers/admin_public_body_controller.rb | 10 | ||||
-rw-r--r-- | app/controllers/admin_user_controller.rb | 1 | ||||
-rw-r--r-- | app/controllers/application_controller.rb | 103 | ||||
-rw-r--r-- | app/controllers/general_controller.rb | 74 | ||||
-rw-r--r-- | app/controllers/help_controller.rb | 16 | ||||
-rw-r--r-- | app/controllers/public_body_controller.rb | 24 | ||||
-rw-r--r-- | app/controllers/request_controller.rb | 86 | ||||
-rw-r--r-- | app/controllers/services_controller.rb | 10 | ||||
-rw-r--r-- | app/controllers/track_controller.rb | 9 | ||||
-rw-r--r-- | app/controllers/user_controller.rb | 67 |
11 files changed, 253 insertions, 151 deletions
diff --git a/app/controllers/admin_general_controller.rb b/app/controllers/admin_general_controller.rb index ae51e0923..0b7e9bec0 100644 --- a/app/controllers/admin_general_controller.rb +++ b/app/controllers/admin_general_controller.rb @@ -78,6 +78,10 @@ class AdminGeneralController < AdminController end def debug + @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 end end diff --git a/app/controllers/admin_public_body_controller.rb b/app/controllers/admin_public_body_controller.rb index e249cef11..bf7c07905 100644 --- a/app/controllers/admin_public_body_controller.rb +++ b/app/controllers/admin_public_body_controller.rb @@ -27,12 +27,12 @@ class AdminPublicBodyController < AdminController 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.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 - @public_bodies_by_tag = PublicBody::Translation.find_by_tag(@query) end + @public_bodies_by_tag = PublicBody.find_by_tag(@query) end def list @@ -56,7 +56,7 @@ class AdminPublicBodyController < AdminController flash[:notice] = "Added tag to table of bodies." end - redirect_to admin_url('body/list') + "?query=" + @query + (@page.nil? ? "" : "&page=" + @page) # XXX construct this URL properly + redirect_to admin_body_list_url(:query => @query, :page => @page) end def missing_scheme @@ -127,14 +127,14 @@ class AdminPublicBodyController < AdminController if public_body.info_requests.size > 0 flash[:notice] = "There are requests associated with the authority, so can't destroy it" - redirect_to admin_url('body/show/' + public_body.id.to_s) + redirect_to admin_body_show_url(public_body) return end public_body.tag_string = "" public_body.destroy flash[:notice] = "PublicBody was successfully destroyed." - redirect_to admin_url('body/list') + redirect_to admin_body_list_url end end diff --git a/app/controllers/admin_user_controller.rb b/app/controllers/admin_user_controller.rb index 5d90e74fe..12b4e553f 100644 --- a/app/controllers/admin_user_controller.rb +++ b/app/controllers/admin_user_controller.rb @@ -45,6 +45,7 @@ class AdminUserController < AdminController @admin_user.admin_level = params[:admin_user][:admin_level] @admin_user.ban_text = params[:admin_user][:ban_text] @admin_user.about_me = params[:admin_user][:about_me] + @admin_user.no_limit = params[:admin_user][:no_limit] if @admin_user.valid? @admin_user.save! diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b7457c48e..b681f455d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -11,10 +11,15 @@ require 'open-uri' class ApplicationController < ActionController::Base + class PermissionDenied < StandardError + end # Standard headers, footers and navigation for whole site layout "default" include FastGettext::Translation # make functions like _, n_, N_ etc available) - + + # 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 @@ -84,6 +89,7 @@ class ApplicationController < ActionController::Base def record_memory record_memory = MySociety::Config.get('DEBUG_RECORD_MEMORY', false) if record_memory + logger.info "Processing request for #{request.url} with Rails process #{Process.pid}" File.read("/proc/#{Process.pid}/status").match(/VmRSS:\s+(\d+)/) rss_before_action = $1.to_i yield @@ -117,8 +123,11 @@ class ApplicationController < ActionController::Base case exception when ActiveRecord::RecordNotFound, ActionController::UnknownAction, ActionController::RoutingError @status = 404 + when PermissionDenied + @status = 403 else @status = 500 + notify_about_exception exception end # Display user appropriate error message @exception_backtrace = exception.backtrace.join("\n") @@ -169,11 +178,13 @@ class ApplicationController < ActionController::Base end def foi_fragment_cache_path(param) - path = foi_fragment_cache_part_path(param) - path = "/views" + path - foi_cache_path = File.join(File.dirname(__FILE__), '../../cache') - return File.join(foi_cache_path, path) + 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 + return File.join(File.split(path).map{|x| x[0...max_file_length]}) end + def foi_fragment_cache_all_for_request(info_request) # return stub path so admin can expire it first_three_digits = info_request.id.to_s()[0..2] @@ -185,10 +196,12 @@ class ApplicationController < ActionController::Base return File.exists?(key_path) end def foi_fragment_cache_read(key_path) - cached = File.read(key_path) + logger.info "Reading from fragment cache #{key_path}" + return File.read(key_path) end def foi_fragment_cache_write(key_path, content) FileUtils.mkdir_p(File.dirname(key_path)) + logger.info "Writing to fragment cache #{key_path}" File.atomic_write(key_path) do |f| f.write(content) end @@ -341,9 +354,7 @@ class ApplicationController < ActionController::Base @sortby = sortby # Work out sorting method - order_pair = order_to_sort_by(@sortby) - order = order_pair[0] - ascending = order_pair[1] + order, ascending = order_to_sort_by(@sortby) # Peform the search @per_page = per_page @@ -352,23 +363,71 @@ class ApplicationController < ActionController::Base else @page = this_page end - return InfoRequest.full_search(models, @query, order, ascending, collapse, @per_page, @page) + result = InfoRequest.full_search(models, @query, order, ascending, collapse, @per_page, @page) + result.results # Touch the results to load them, otherwise accessing them from the view + # might fail later if the database has subsequently been reopened. + return result end def get_search_page_from_params return (params[:page] || "1").to_i end + def perform_search_typeahead(query, model) + @page = get_search_page_from_params + @per_page = 10 + query_words = query.split(/ +(?![-+]+)/) + if query_words.last.nil? || query_words.last.strip.length < 3 + xapian_requests = nil + else + if model == PublicBody + collapse = nil + elsif model == InfoRequestEvent + collapse = 'request_collapse' + end + options = { + :offset => (@page - 1) * @per_page, + :limit => @per_page, + :sort_by_prefix => nil, + :sort_by_ascending => true, + :collapse_by_prefix => collapse, + } + ActsAsXapian.readable_init + old_default_op = ActsAsXapian.query_parser.default_op + ActsAsXapian.query_parser.default_op = Xapian::Query::OP_OR + begin + user_query = ActsAsXapian.query_parser.parse_query( + query.strip + '*', + Xapian::QueryParser::FLAG_LOVEHATE | Xapian::QueryParser::FLAG_WILDCARD | + Xapian::QueryParser::FLAG_SPELLING_CORRECTION) + xapian_requests = ActsAsXapian::Search.new([model], query, options, user_query) + rescue RuntimeError => e + 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 | + Xapian::QueryParser::FLAG_SPELLING_CORRECTION) + xapian_requests = ActsAsXapian::Search.new([model], query, options, user_query) + end + end + ActsAsXapian.query_parser.default_op = old_default_op + end + return xapian_requests + end + # Store last visited pages, for contact form; but only for logged in users, as otherwise this breaks caching def set_last_request(info_request) if !session[:user_id].nil? - session[:last_request_id] = info_request.id - session[:last_body_id] = nil + cookies["last_request_id"] = info_request.id + cookies["last_body_id"] = nil end end def set_last_body(public_body) if !session[:user_id].nil? - session[:last_request_id] = nil - session[:last_body_id] = public_body.id + cookies["last_request_id"] = nil + cookies["last_body_id"] = public_body.id end end @@ -406,7 +465,7 @@ class ApplicationController < ActionController::Base params[:latest_status] = [params[:latest_status]] end if params[:latest_status].include?("recent") || params[:latest_status].include?("all") - query += " variety:sent" + query += " (variety:sent OR variety:followup_sent OR variety:response OR variety:comment)" end if params[:latest_status].include? "successful" statuses << ['latest_status:successful', 'latest_status:partially_successful'] @@ -415,7 +474,7 @@ class ApplicationController < ActionController::Base statuses << ['latest_status:rejected', 'latest_status:not_held'] end if params[:latest_status].include? "awaiting" - statuses << ['latest_status:waiting_response', 'latest_status:waiting_clarification', 'waiting_classification:true'] + statuses << ['latest_status:waiting_response', 'latest_status:waiting_clarification', 'waiting_classification:true', 'latest_status:internal_review','latest_status:gone_postal', 'latest_status:error_message', 'latest_status:requires_admin'] end if params[:latest_status].include? "internal_review" statuses << ['status:internal_review'] @@ -475,12 +534,22 @@ class ApplicationController < ActionController::Base default = MySociety::Config.get('ISO_COUNTRY_CODE', '') country = "" if !gaze.empty? - country = open("#{gaze}/gaze-rest?f=get_country_from_ip;ip=#{request.remote_ip}").read.strip + country = quietly_try_to_open("#{gaze}/gaze-rest?f=get_country_from_ip;ip=#{request.remote_ip}") end country = default if country.empty? 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/general_controller.rb b/app/controllers/general_controller.rb index 194a1cec0..82b1b8629 100644 --- a/app/controllers/general_controller.rb +++ b/app/controllers/general_controller.rb @@ -32,12 +32,12 @@ class GeneralController < ApplicationController 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", - :limit => 32, - :conditions => conditions, - :joins => :translations - ) + :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, @@ -45,20 +45,21 @@ class GeneralController < ApplicationController :joins => :translations) end end - # Get some successful requests # + # Get some successful requests begin query = 'variety:response (status:successful OR status:partially_successful)' - # query = 'variety:response' # XXX debug - sortby = "described" + sortby = "newest" max_count = 5 xapian_object = perform_search([InfoRequestEvent], query, sortby, 'request_title_collapse', max_count) @request_events = xapian_object.results.map { |r| r[:model] } - @request_events = @request_events.sort_by { |e| e.described_at }.reverse + + # If there are not yet enough successful requests, fill out the list with + # other requests if @request_events.count < max_count query = 'variety:sent' xapian_object = perform_search([InfoRequestEvent], query, sortby, 'request_title_collapse', max_count-@request_events.count) more_events = xapian_object.results.map { |r| r[:model] } - @request_events += more_events.sort_by { |e| e.described_at }.reverse + @request_events += more_events end rescue @request_events = [] @@ -71,48 +72,34 @@ class GeneralController < ApplicationController medium_cache @feed_autodetect = [] @feed_url = "#{MySociety::Config.get('BLOG_FEED', '')}?lang=#{self.locale_from_params()}" + @blog_items = [] if not @feed_url.empty? - content = open(@feed_url).read - @data = XmlSimple.xml_in(content) - @channel = @data['channel'][0] - @blog_items = @channel['item'] - @feed_autodetect = [{:url => @feed_url, :title => "#{site_name} blog"}] - else - @blog_items = [] + content = quietly_try_to_open(@feed_url) + if !content.empty? + @data = XmlSimple.xml_in(content) + @channel = @data['channel'][0] + @blog_items = @channel['item'] + @feed_autodetect = [{:url => @feed_url, :title => "#{site_name} blog"}] + end end @twitter_user = MySociety::Config.get('TWITTER_USERNAME', '') end # Just does a redirect from ?query= search to /query def search_redirect - if params[:advanced].nil? - @query, _ = make_query_from_params - else - @query, _ = params[:query] - end - @sortby = params[:sortby] - path = request.path.split("/") - if path.size > 0 && (['newest', 'described', 'relevant'].include?(path[-1])) - @sort_postfix = path.pop - end - if path.size > 0 && (['bodies', 'requests', 'users', 'all'].include?(path[-1])) - @variety_postfix = path.pop - end - @variety_postfix = "bodies" if @variety_postfix.nil? && !params[:bodies].nil? - @variety_postfix = "requests" if @variety_postfix.nil? - if @variety_postfix != "users" - @common_query = get_tags_from_params - end - [:latest_status, :request_variety, :request_date_after, :request_date_before, :query, :tags].each do |x| - session[x] = params[x] - end + @query = params.delete(:query) if @query.nil? || @query.empty? @query = nil @page = 1 @advanced = !params[:advanced].nil? render :action => "search" else - redirect_to search_url(@query, @variety_postfix, @sort_postfix, params[:advanced]) + query_parts = @query.split("/") + if !['bodies', 'requests', 'users', 'all'].include?(query_parts[-1]) + redirect_to search_url([@query, "all"], params) + else + redirect_to search_url(@query, params) + end end end @@ -120,13 +107,6 @@ class GeneralController < ApplicationController def search # XXX Why is this so complicated with arrays and stuff? Look at the route # in config/routes.rb for comments. - if !params[:commit].nil? - search_redirect - return - end - [:latest_status, :request_variety, :request_date_after, :request_date_before, :query, :tags].each do |x| - params[x] = session[x] if params[x].nil? - end combined = params[:combined] @sortby = nil @bodies = @requests = @users = true diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index c6d246b4c..b08438b52 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -26,20 +26,20 @@ class HelpController < ApplicationController # if they clicked remove for link to request/body, remove it if params[:remove] @last_request = nil - session[:last_request_id] = nil - session[:last_body_id] = nil + cookies["last_request_id"] = nil + cookies["last_body_id"] = nil end # look up link to request/body - @last_request_id = session[:last_request_id].to_i - if @last_request_id > 0 - @last_request = InfoRequest.find(@last_request_id) + last_request_id = cookies["last_request_id"].to_i + if last_request_id > 0 + @last_request = InfoRequest.find(last_request_id) else @last_request = nil end - @last_body_id = session[:last_body_id].to_i - if @last_body_id > 0 - @last_body = PublicBody.find(@last_body_id) + last_body_id = cookies["last_body_id"].to_i + if last_body_id > 0 + @last_body = PublicBody.find(last_body_id) else @last_body = nil end diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index 62229a441..00d1cc1e0 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # app/controllers/public_body_controller.rb: # Show information about a public body. # @@ -117,19 +118,22 @@ class PublicBodyController < ApplicationController and has_tag_string_tags.model = \'PublicBody\' and has_tag_string_tags.name = ?) > 0', @query, @query, default_locale, @tag] end + if @tag == "all" @description = "" elsif @tag.size == 1 - @description = _("beginning with") + " '" + @tag + "'" + @description = _("beginning with ‘{{first_letter}}’", :first_letter=>@tag) else - @description = PublicBodyCategories::get().by_tag()[@tag] - if @description.nil? - @description = @tag + category_name = PublicBodyCategories::get().by_tag()[@tag] + if category_name.nil? + @description = _("matching the tag ‘{{tag_name}}’", :tag_name=>@tag) + else + @description = _("in the category ‘{{category_name}}’", :category_name=>category_name) end end PublicBody.with_locale(@locale) do @public_bodies = PublicBody.paginate( - :order => "public_body_translations.name", :page => params[:page], :per_page => 1000, # fit all councils on one page + :order => "public_body_translations.name", :page => params[:page], :per_page => 100, :conditions => conditions, :joins => :translations ) @@ -185,14 +189,8 @@ class PublicBodyController < ApplicationController def search_typeahead # Since acts_as_xapian doesn't support the Partial match flag, we work around it # by making the last work a wildcard, which is quite the same - query = params[:q] - query = query.split(' ') - if query.last.nil? || query.last.strip.length < 3 - @xapian_requests = nil - else - query = query.join(' OR ') # XXX: HACK for OR instead of default AND! - @xapian_requests = perform_search([PublicBody], query, 'relevant', nil, 5) - end + query = params[:query] + @xapian_requests = perform_search_typeahead(query, PublicBody) render :partial => "public_body/search_ahead" end end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index dad5e81cd..2295d6718 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -13,6 +13,9 @@ require 'open-uri' class RequestController < ApplicationController before_filter :check_read_only, :only => [ :new, :show_response, :describe_state, :upload_response ] protect_from_forgery :only => [ :new, :show_response, :describe_state, :upload_response ] # See ActionController::RequestForgeryProtection for details + + MAX_RESULTS = 500 + PER_PAGE = 25 @@custom_states_loaded = false begin @@ -35,11 +38,9 @@ class RequestController < ApplicationController # do nothing - as "authenticated?" has done the redirect to signin page for us return end - if !params[:query].nil? - query = params[:query] + '*' - query = query.split(' ').join(' OR ') # XXX: HACK for OR instead of default AND! - @xapian_requests = perform_search([PublicBody], query, 'relevant', nil, 5) + query = params[:query] + @xapian_requests = perform_search_typeahead(query, PublicBody) end medium_cache end @@ -73,8 +74,9 @@ class RequestController < ApplicationController @info_request_events = @info_request.info_request_events @status = @info_request.calculate_status @collapse_quotes = params[:unfold] ? false : true - @update_status = params[:update_status] ? true : false + @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, @@ -107,7 +109,6 @@ class RequestController < ApplicationController # For send followup link at bottom @last_response = @info_request.get_last_response - @is_owning_user = @info_request.is_owning_user?(authenticated_user) respond_to do |format| format.html { @has_json = true; render :template => 'request/show'} format.json { render :json => @info_request.json_for_api(true) } @@ -119,11 +120,14 @@ class RequestController < ApplicationController def details long_cache @info_request = InfoRequest.find_by_url_title(params[:url_title]) - if !@info_request.user_can_view?(authenticated_user) - render :template => 'request/hidden', :status => 410 # gone - return + if @info_request.nil? + raise ActiveRecord::RecordNotFound.new("Request not found") + else + if !@info_request.user_can_view?(authenticated_user) + render :template => 'request/hidden', :status => 410 # gone + return + end end - @columns = ['id', 'event_type', 'created_at', 'described_state', 'last_described_at', 'calculated_state' ] end @@ -150,15 +154,26 @@ class RequestController < ApplicationController def list medium_cache @view = params[:view] + @page = get_search_page_from_params if !@page # used in cache case, as perform_search sets @page as side effect + 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}.") + end + params[:latest_status] = @view query = make_query_from_params @title = _("View and search requests") sortby = "newest" - @page = get_search_page_from_params if !@page # used in cache case, as perform_search sets @page as side effect - behavior_cache :tag => [@view, @page] do + @cache_tag = Digest::MD5.hexdigest(query + @page.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) @@ -192,14 +207,28 @@ class RequestController < ApplicationController end # Banned from making new requests? + user_exceeded_limit = false if !authenticated_user.nil? && !authenticated_user.can_file_requests? - @details = authenticated_user.can_fail_html - render :template => 'user/banned' - return + # If the reason the user cannot make new requests is that they are + # rate-limited, it’s possible they composed a request before they + # logged in and we want to include the text of the request so they + # can squirrel it away for tomorrow, so we detect this later after + # we have constructed the InfoRequest. + user_exceeded_limit = authenticated_user.exceeded_limit? + if !user_exceeded_limit + @details = authenticated_user.can_fail_html + render :template => 'user/banned' + return + end end # First time we get to the page, just display it if params[:submitted_new_request].nil? || params[:reedit] + if user_exceeded_limit + render :template => 'user/rate_limited' + return + end + params[:info_request] = { } if !params[:info_request] # Read parameters in - first the public body (by URL name or id) @@ -299,6 +328,11 @@ class RequestController < ApplicationController return end + if user_exceeded_limit + render :template => 'user/rate_limited' + return + end + if !authenticated?( :web => _("To send your FOI request"), :email => _("Then your FOI request to {{public_body_name}} will be sent.",:public_body_name=>@info_request.public_body.name), @@ -602,7 +636,9 @@ class RequestController < ApplicationController def authenticate_attachment # Test for hidden incoming_message = IncomingMessage.find(params[:incoming_message_id]) + raise ActiveRecord::RecordNotFound.new("Message not found") if incoming_message.nil? if !incoming_message.info_request.user_can_view?(authenticated_user) + @info_request = incoming_message.info_request # used by view render :template => 'request/hidden', :status => 410 # gone end end @@ -615,8 +651,8 @@ class RequestController < ApplicationController else key = params.merge(:only_path => true) key_path = foi_fragment_cache_path(key) - if foi_fragment_cache_exists?(key_path) + raise PermissionDenied.new("Directory listing not allowed") if File.directory?(key_path) cached = foi_fragment_cache_read(key_path) response.content_type = AlaveteliFileTypes.filename_to_mimetype(params[:file_name].join("/")) || 'application/octet-stream' render_for_text(cached) @@ -676,10 +712,15 @@ class RequestController < ApplicationController # Internal function def get_attachment_internal(html_conversion) @incoming_message = IncomingMessage.find(params[:incoming_message_id]) + @requested_request = InfoRequest.find(params[:id]) @incoming_message.parse_raw_email! @info_request = @incoming_message.info_request if @incoming_message.info_request_id != params[:id].to_i - raise sprintf("Incoming message %d does not belong to request %d", @incoming_message.info_request_id, params[:id]) + # Note that params[:id] might not be an integer, though + # if we’ve got this far then it must begin with an integer + # and that integer must be the id number of an actual request. + message = "Incoming message %d does not belong to request '%s'" % [@incoming_message.info_request_id, params[:id]] + raise ActiveRecord::RecordNotFound.new(message) end @part_number = params[:part].to_i @filename = params[:file_name].join("/") @@ -756,13 +797,7 @@ class RequestController < ApplicationController # Since acts_as_xapian doesn't support the Partial match flag, we work around it # by making the last work a wildcard, which is quite the same query = params[:q] - query = query.split(' ') - if query.last.nil? || query.last.strip.length < 3 - @xapian_requests = nil - else - query = query.join(' OR ') # XXX: HACK for OR instead of default AND! - @xapian_requests = perform_search([InfoRequestEvent], query, 'relevant', 'request_collapse', 5) - end + @xapian_requests = perform_search_typeahead(query, InfoRequestEvent) render :partial => "request/search_ahead.rhtml" end @@ -815,7 +850,8 @@ class RequestController < ApplicationController for message in info_request.incoming_messages attachments = message.get_attachments_for_display for attachment in attachments - zipfile.get_output_stream(attachment.display_filename) { |f| + filename = "#{attachment.url_part_number}_#{attachment.display_filename}" + zipfile.get_output_stream(filename) { |f| f.puts(attachment.body) } end diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 6fb20336e..225790d71 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -1,12 +1,4 @@ -# 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 -# will be available for all controllers. -# -# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. -# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ -# -# $Id: application.rb,v 1.59 2009-09-17 13:01:56 francis Exp $ +# controllers/services_controller.rb: require 'open-uri' diff --git a/app/controllers/track_controller.rb b/app/controllers/track_controller.rb index e06701a5f..e39a0489d 100644 --- a/app/controllers/track_controller.rb +++ b/app/controllers/track_controller.rb @@ -46,7 +46,14 @@ class TrackController < ApplicationController # Track all updates to a particular public body def track_public_body - @public_body = PublicBody.find_by_url_name(params[:url_name]) + @public_body = PublicBody.find_by_url_name_with_historic(params[:url_name]) + 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]) + return + end + @track_thing = TrackThing.create_track_for_public_body(@public_body) return atom_feed_internal if params[:feed] == 'feed' diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 96dbfba74..f49fc9165 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -23,7 +23,17 @@ class UserController < ApplicationController redirect_to :url_name => MySociety::Format.simplify_url_part(params[:url_name], 'user', 32), :status => :moved_permanently return end - + if params[:view].nil? + @show_requests = true + @show_profile = true + elsif params[:view] == 'profile' + @show_profile = true + @show_requests = false + elsif params[:view] == 'requests' + @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]) @@ -34,31 +44,33 @@ class UserController < ApplicationController # 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 - if !params[:user_query].nil? - requests_query += " " + params[:user_query] - comments_query += " " + params[:user_query] - @match_phrase = _("{{search_results}} matching '{{query}}'", :search_results => "", :query => params[:user_query]) - 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 - @page_desc = "" + if @show_requests + begin + requests_query = 'requested_by:' + @display_user.url_name + comments_query = 'commented_by:' + @display_user.url_name + if !params[:user_query].nil? + requests_query += " " + params[:user_query] + comments_query += " " + params[:user_query] + @match_phrase = _("{{search_results}} matching '{{query}}'", :search_results => "", :query => params[:user_query]) + 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 + @page_desc = "" + end + rescue + @xapian_requests = nil + @xapian_comments = nil end - rescue - @xapian_requests = nil - @xapian_comments = nil - end - # Track corresponding to this page - @track_thing = TrackThing.create_track_for_user(@display_user) - @feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ] + # Track corresponding to this page + @track_thing = TrackThing.create_track_for_user(@display_user) + @feed_autodetect = [ { :url => do_track_url(@track_thing, 'feed'), :title => @track_thing.params[:title_in_rss], :has_json => true } ] + end # 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') @@ -104,8 +116,10 @@ class UserController < ApplicationController render :action => 'sign' return else - @user_signin = User.authenticate_from_form(params[:user_signin], @post_redirect.reason_params[:user_name] ? true : false) - if @user_signin.errors.size > 0 + if !@post_redirect.nil? + @user_signin = User.authenticate_from_form(params[:user_signin], @post_redirect.reason_params[:user_name] ? true : false) + end + if @post_redirect.nil? || @user_signin.errors.size > 0 # Failed to authenticate render :action => 'sign' return @@ -475,7 +489,8 @@ class UserController < ApplicationController raise ActiveRecord::RecordNotFound.new("user not found, url_name=" + params[:url_name]) end if !@display_user.profile_photo - raise "user has no profile photo, url_name=" + params[:url_name] + raise ActiveRecord::RecordNotFound.new("user has no profile photo, url_name=" + params[:url_name]) + end response.content_type = "image/png" |