aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/base
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/base')
-rw-r--r--actionpack/lib/action_controller/base/base.rb59
-rw-r--r--actionpack/lib/action_controller/base/chained/flash.rb74
-rw-r--r--actionpack/lib/action_controller/base/filter_parameter_logging.rb97
-rw-r--r--actionpack/lib/action_controller/base/helpers.rb22
-rw-r--r--actionpack/lib/action_controller/base/mime_responds.rb210
-rw-r--r--actionpack/lib/action_controller/base/request_forgery_protection.rb24
-rw-r--r--actionpack/lib/action_controller/base/streaming.rb8
-rw-r--r--actionpack/lib/action_controller/base/verification.rb9
8 files changed, 296 insertions, 207 deletions
diff --git a/actionpack/lib/action_controller/base/base.rb b/actionpack/lib/action_controller/base/base.rb
index c59068c628..67369eb122 100644
--- a/actionpack/lib/action_controller/base/base.rb
+++ b/actionpack/lib/action_controller/base/base.rb
@@ -242,7 +242,6 @@ module ActionController #:nodoc:
# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets,
# and images to a dedicated asset server away from the main web server. Example:
# ActionController::Base.asset_host = "http://assets.example.com"
- @@asset_host = ""
cattr_accessor :asset_host
# All requests are considered local by default, so everyone will be exposed to detailed debugging screens on errors.
@@ -448,55 +447,6 @@ module ActionController #:nodoc:
@view_paths = superclass.view_paths.dup if @view_paths.nil?
@view_paths.push(*path)
end
-
- # Replace sensitive parameter data from the request log.
- # Filters parameters that have any of the arguments as a substring.
- # Looks in all subhashes of the param hash for keys to filter.
- # If a block is given, each key and value of the parameter hash and all
- # subhashes is passed to it, the value or key
- # can be replaced using String#replace or similar method.
- #
- # Examples:
- # filter_parameter_logging
- # => Does nothing, just slows the logging process down
- #
- # filter_parameter_logging :password
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
- #
- # filter_parameter_logging :foo, "bar"
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- #
- # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
- # => reverses the value to all keys matching /secret/i
- #
- # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
- # => reverses the value to all keys matching /secret/i, and
- # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- def filter_parameter_logging(*filter_words, &block)
- parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
-
- define_method(:filter_parameters) do |unfiltered_parameters|
- filtered_parameters = {}
-
- unfiltered_parameters.each do |key, value|
- if key =~ parameter_filter
- filtered_parameters[key] = '[FILTERED]'
- elsif value.is_a?(Hash)
- filtered_parameters[key] = filter_parameters(value)
- elsif block_given?
- key = key.dup
- value = value.dup if value
- yield key, value
- filtered_parameters[key] = value
- else
- filtered_parameters[key] = value
- end
- end
-
- filtered_parameters
- end
- protected :filter_parameters
- end
@@exempt_from_layout = [ActionView::TemplateHandlers::RJS]
@@ -853,13 +803,6 @@ module ActionController #:nodoc:
logger.info(request_id)
end
- def log_processing_for_parameters
- parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
- parameters = parameters.except!(:controller, :action, :format, :_method)
-
- logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
- end
-
def default_render #:nodoc:
render
end
@@ -933,7 +876,7 @@ module ActionController #:nodoc:
[ Filters, Layout, Renderer, Redirector, Responder, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
Cookies, Caching, Verification, Streaming, SessionManagement,
HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods, RecordIdentifier,
- RequestForgeryProtection, Translation
+ RequestForgeryProtection, Translation, FilterParameterLogging
].each do |mod|
include mod
end
diff --git a/actionpack/lib/action_controller/base/chained/flash.rb b/actionpack/lib/action_controller/base/chained/flash.rb
index 56ee9c67e2..6bd482d85a 100644
--- a/actionpack/lib/action_controller/base/chained/flash.rb
+++ b/actionpack/lib/action_controller/base/chained/flash.rb
@@ -26,9 +26,18 @@ module ActionController #:nodoc:
#
# See docs on the FlashHash class for more details about the flash.
module Flash
- def self.included(base)
- base.class_eval do
- include InstanceMethods
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ depends_on Session if defined?(ActionController::Http)
+
+ included do
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ include InstanceMethodsForNewBase
+ else
+ include InstanceMethodsForBase
+
alias_method_chain :perform_action, :flash
alias_method_chain :reset_session, :flash
end
@@ -135,29 +144,50 @@ module ActionController #:nodoc:
end
end
- module InstanceMethods #:nodoc:
+ module InstanceMethodsForBase #:nodoc:
protected
- def perform_action_with_flash
- perform_action_without_flash
- remove_instance_variable(:@_flash) if defined? @_flash
- end
- def reset_session_with_flash
- reset_session_without_flash
- remove_instance_variable(:@_flash) if defined? @_flash
- end
+ def perform_action_with_flash
+ perform_action_without_flash
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
- # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
- # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
- # to put a new one.
- def flash #:doc:
- unless defined? @_flash
- @_flash = session["flash"] ||= FlashHash.new
- @_flash.sweep
- end
+ def reset_session_with_flash
+ reset_session_without_flash
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
+ end
- @_flash
- end
+ module InstanceMethodsForNewBase #:nodoc:
+ protected
+
+ def reset_session
+ super
+ remove_flash_instance_variable
+ end
+
+ def process_action(method_name)
+ super
+ remove_flash_instance_variable
+ end
+
+ def remove_flash_instance_variable
+ remove_instance_variable(:@_flash) if defined?(@_flash)
+ end
+ end
+
+ protected
+
+ # Access the contents of the flash. Use <tt>flash["notice"]</tt> to
+ # read a notice you put there or <tt>flash["notice"] = "hello"</tt>
+ # to put a new one.
+ def flash #:doc:
+ unless defined?(@_flash)
+ @_flash = session["flash"] ||= FlashHash.new
+ @_flash.sweep
+ end
+
+ @_flash
end
end
end
diff --git a/actionpack/lib/action_controller/base/filter_parameter_logging.rb b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
new file mode 100644
index 0000000000..f5a678ca03
--- /dev/null
+++ b/actionpack/lib/action_controller/base/filter_parameter_logging.rb
@@ -0,0 +1,97 @@
+module ActionController
+ module FilterParameterLogging
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Logger
+ end
+
+ included do
+ if defined?(ActionController::Http)
+ include InstanceMethodsForNewBase
+ end
+ end
+
+ module ClassMethods
+ # Replace sensitive parameter data from the request log.
+ # Filters parameters that have any of the arguments as a substring.
+ # Looks in all subhashes of the param hash for keys to filter.
+ # If a block is given, each key and value of the parameter hash and all
+ # subhashes is passed to it, the value or key
+ # can be replaced using String#replace or similar method.
+ #
+ # Examples:
+ # filter_parameter_logging
+ # => Does nothing, just slows the logging process down
+ #
+ # filter_parameter_logging :password
+ # => replaces the value to all keys matching /password/i with "[FILTERED]"
+ #
+ # filter_parameter_logging :foo, "bar"
+ # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ #
+ # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }
+ # => reverses the value to all keys matching /secret/i
+ #
+ # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i }
+ # => reverses the value to all keys matching /secret/i, and
+ # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ def filter_parameter_logging(*filter_words, &block)
+ parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0
+
+ define_method(:filter_parameters) do |unfiltered_parameters|
+ filtered_parameters = {}
+
+ unfiltered_parameters.each do |key, value|
+ if key =~ parameter_filter
+ filtered_parameters[key] = '[FILTERED]'
+ elsif value.is_a?(Hash)
+ filtered_parameters[key] = filter_parameters(value)
+ elsif block_given?
+ key = key.dup
+ value = value.dup if value
+ yield key, value
+ filtered_parameters[key] = value
+ else
+ filtered_parameters[key] = value
+ end
+ end
+
+ filtered_parameters
+ end
+ protected :filter_parameters
+ end
+ end
+
+ module InstanceMethodsForNewBase
+ # TODO : Fix the order of information inside such that it's exactly same as the old base
+ def process(*)
+ ret = super
+
+ if logger
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
+ parameters = parameters.except!(:controller, :action, :format, :_method, :only_path)
+
+ unless parameters.empty?
+ # TODO : Move DelayedLog to AS
+ log = AbstractController::Logger::DelayedLog.new { " Parameters: #{parameters.inspect}" }
+ logger.info(log)
+ end
+ end
+
+ ret
+ end
+ end
+
+ private
+
+ # TODO : This method is not needed for the new base
+ def log_processing_for_parameters
+ parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
+ parameters = parameters.except!(:controller, :action, :format, :_method)
+
+ logger.info " Parameters: #{parameters.inspect}" unless parameters.empty?
+ end
+ end
+end
diff --git a/actionpack/lib/action_controller/base/helpers.rb b/actionpack/lib/action_controller/base/helpers.rb
index ba65032f6a..96fa7896a9 100644
--- a/actionpack/lib/action_controller/base/helpers.rb
+++ b/actionpack/lib/action_controller/base/helpers.rb
@@ -3,23 +3,19 @@ require 'active_support/dependencies'
# FIXME: helper { ... } is broken on Ruby 1.9
module ActionController #:nodoc:
module Helpers #:nodoc:
- def self.included(base)
+ extend ActiveSupport::DependencyModule
+
+ included do
# Initialize the base module to aggregate its helpers.
- base.class_inheritable_accessor :master_helper_module
- base.master_helper_module = Module.new
+ class_inheritable_accessor :master_helper_module
+ self.master_helper_module = Module.new
# Set the default directory for helpers
- base.class_inheritable_accessor :helpers_dir
- base.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
-
- # Extend base with class methods to declare helpers.
- base.extend(ClassMethods)
+ class_inheritable_accessor :helpers_dir
+ self.helpers_dir = (defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/app/helpers" : "app/helpers")
- base.class_eval do
- # Wrap inherited to create a new master helper module for subclasses.
- class << self
- alias_method_chain :inherited, :helper
- end
+ class << self
+ alias_method_chain :inherited, :helper
end
end
diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb
index 1003e61a0b..3c17dda1a1 100644
--- a/actionpack/lib/action_controller/base/mime_responds.rb
+++ b/actionpack/lib/action_controller/base/mime_responds.rb
@@ -1,111 +1,103 @@
module ActionController #:nodoc:
module MimeResponds #:nodoc:
- def self.included(base)
- base.module_eval do
- include ActionController::MimeResponds::InstanceMethods
- end
- end
-
- module InstanceMethods
- # Without web-service support, an action which collects the data for displaying a list of people
- # might look something like this:
- #
- # def index
- # @people = Person.find(:all)
- # end
- #
- # Here's the same action, with web-service support baked in:
- #
- # def index
- # @people = Person.find(:all)
- #
- # respond_to do |format|
- # format.html
- # format.xml { render :xml => @people.to_xml }
- # end
- # end
- #
- # What that says is, "if the client wants HTML in response to this action, just respond as we
- # would have before, but if the client wants XML, return them the list of people in XML format."
- # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
- #
- # Supposing you have an action that adds a new person, optionally creating their company
- # (by name) if it does not already exist, without web-services, it might look like this:
- #
- # def create
- # @company = Company.find_or_create_by_name(params[:company][:name])
- # @person = @company.people.create(params[:person])
- #
- # redirect_to(person_list_url)
- # end
- #
- # Here's the same action, with web-service support baked in:
- #
- # def create
- # company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
- # @person = @company.people.create(params[:person])
- #
- # respond_to do |format|
- # format.html { redirect_to(person_list_url) }
- # format.js
- # format.xml { render :xml => @person.to_xml(:include => @company) }
- # end
- # end
- #
- # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
- # (format.js), then it is an RJS request and we render the RJS template associated with this action.
- # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
- # include the person's company in the rendered XML, so you get something like this:
- #
- # <person>
- # <id>...</id>
- # ...
- # <company>
- # <id>...</id>
- # <name>...</name>
- # ...
- # </company>
- # </person>
- #
- # Note, however, the extra bit at the top of that action:
- #
- # company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
- #
- # This is because the incoming XML document (if a web-service request is in process) can only contain a
- # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
- #
- # person[name]=...&person[company][name]=...&...
- #
- # And, like this (xml-encoded):
- #
- # <person>
- # <name>...</name>
- # <company>
- # <name>...</name>
- # </company>
- # </person>
- #
- # In other words, we make the request so that it operates on a single entity's person. Then, in the action,
- # we extract the company data from the request, find or create the company, and then create the new person
- # with the remaining data.
- #
- # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
- # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
- # and accept Rails' defaults, life will be much easier.
- #
- # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
- # environment.rb as follows.
- #
- # Mime::Type.register "image/jpg", :jpg
- def respond_to(*types, &block)
- raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
- block ||= lambda { |responder| types.each { |type| responder.send(type) } }
- responder = Responder.new(self)
- block.call(responder)
- responder.respond
- end
+ # Without web-service support, an action which collects the data for displaying a list of people
+ # might look something like this:
+ #
+ # def index
+ # @people = Person.find(:all)
+ # end
+ #
+ # Here's the same action, with web-service support baked in:
+ #
+ # def index
+ # @people = Person.find(:all)
+ #
+ # respond_to do |format|
+ # format.html
+ # format.xml { render :xml => @people.to_xml }
+ # end
+ # end
+ #
+ # What that says is, "if the client wants HTML in response to this action, just respond as we
+ # would have before, but if the client wants XML, return them the list of people in XML format."
+ # (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
+ #
+ # Supposing you have an action that adds a new person, optionally creating their company
+ # (by name) if it does not already exist, without web-services, it might look like this:
+ #
+ # def create
+ # @company = Company.find_or_create_by_name(params[:company][:name])
+ # @person = @company.people.create(params[:person])
+ #
+ # redirect_to(person_list_url)
+ # end
+ #
+ # Here's the same action, with web-service support baked in:
+ #
+ # def create
+ # company = params[:person].delete(:company)
+ # @company = Company.find_or_create_by_name(company[:name])
+ # @person = @company.people.create(params[:person])
+ #
+ # respond_to do |format|
+ # format.html { redirect_to(person_list_url) }
+ # format.js
+ # format.xml { render :xml => @person.to_xml(:include => @company) }
+ # end
+ # end
+ #
+ # If the client wants HTML, we just redirect them back to the person list. If they want Javascript
+ # (format.js), then it is an RJS request and we render the RJS template associated with this action.
+ # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
+ # include the person's company in the rendered XML, so you get something like this:
+ #
+ # <person>
+ # <id>...</id>
+ # ...
+ # <company>
+ # <id>...</id>
+ # <name>...</name>
+ # ...
+ # </company>
+ # </person>
+ #
+ # Note, however, the extra bit at the top of that action:
+ #
+ # company = params[:person].delete(:company)
+ # @company = Company.find_or_create_by_name(company[:name])
+ #
+ # This is because the incoming XML document (if a web-service request is in process) can only contain a
+ # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
+ #
+ # person[name]=...&person[company][name]=...&...
+ #
+ # And, like this (xml-encoded):
+ #
+ # <person>
+ # <name>...</name>
+ # <company>
+ # <name>...</name>
+ # </company>
+ # </person>
+ #
+ # In other words, we make the request so that it operates on a single entity's person. Then, in the action,
+ # we extract the company data from the request, find or create the company, and then create the new person
+ # with the remaining data.
+ #
+ # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
+ # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
+ # and accept Rails' defaults, life will be much easier.
+ #
+ # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
+ # environment.rb as follows.
+ #
+ # Mime::Type.register "image/jpg", :jpg
+ def respond_to(*types, &block)
+ raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
+ block ||= lambda { |responder| types.each { |type| responder.send(type) } }
+ responder = Responder.new(self)
+ block.call(responder)
+ responder.respond
end
class Responder #:nodoc:
@@ -127,8 +119,14 @@ module ActionController #:nodoc:
@order << mime_type
@responses[mime_type] ||= Proc.new do
+ # TODO: Remove this when new base is merged in
+ if defined?(Http)
+ @controller.formats = [mime_type.to_sym]
+ end
+
@controller.template.formats = [mime_type.to_sym]
@response.content_type = mime_type.to_s
+
block_given? ? block.call : @controller.send(:render, :action => @controller.action_name)
end
end
diff --git a/actionpack/lib/action_controller/base/request_forgery_protection.rb b/actionpack/lib/action_controller/base/request_forgery_protection.rb
index 3067122ceb..0a0e20e1f1 100644
--- a/actionpack/lib/action_controller/base/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/base/request_forgery_protection.rb
@@ -3,12 +3,26 @@ module ActionController #:nodoc:
end
module RequestForgeryProtection
- def self.included(base)
- base.class_eval do
- helper_method :form_authenticity_token
- helper_method :protect_against_forgery?
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Helpers, Session
+ end
+
+ included do
+ if defined?(ActionController::Http)
+ # Sets the token parameter name for RequestForgery. Calling +protect_from_forgery+
+ # sets it to <tt>:authenticity_token</tt> by default.
+ cattr_accessor :request_forgery_protection_token
+
+ # Controls whether request forgergy protection is turned on or not. Turned off by default only in test mode.
+ class_inheritable_accessor :allow_forgery_protection
+ self.allow_forgery_protection = true
end
- base.extend(ClassMethods)
+
+ helper_method :form_authenticity_token
+ helper_method :protect_against_forgery?
end
# Protecting controller actions from CSRF attacks by ensuring that all forms are coming from the current web application, not a
diff --git a/actionpack/lib/action_controller/base/streaming.rb b/actionpack/lib/action_controller/base/streaming.rb
index 9f80f48c3d..5872ba99a2 100644
--- a/actionpack/lib/action_controller/base/streaming.rb
+++ b/actionpack/lib/action_controller/base/streaming.rb
@@ -2,6 +2,13 @@ module ActionController #:nodoc:
# Methods for sending arbitrary data and for streaming files to the browser,
# instead of rendering.
module Streaming
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on ActionController::Renderer
+ end
+
DEFAULT_SEND_FILE_OPTIONS = {
:type => 'application/octet-stream'.freeze,
:disposition => 'attachment'.freeze,
@@ -88,6 +95,7 @@ module ActionController #:nodoc:
head options[:status], X_SENDFILE_HEADER => path
else
if options[:stream]
+ # TODO : Make render :text => proc {} work with the new base
render :status => options[:status], :text => Proc.new { |response, output|
logger.info "Streaming file #{path}" unless logger.nil?
len = options[:buffer_size] || 4096
diff --git a/actionpack/lib/action_controller/base/verification.rb b/actionpack/lib/action_controller/base/verification.rb
index c62b81b666..3fa5a105b1 100644
--- a/actionpack/lib/action_controller/base/verification.rb
+++ b/actionpack/lib/action_controller/base/verification.rb
@@ -1,7 +1,10 @@
module ActionController #:nodoc:
module Verification #:nodoc:
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
+ extend ActiveSupport::DependencyModule
+
+ # TODO : Remove the defined? check when new base is the main base
+ if defined?(ActionController::Http)
+ depends_on AbstractController::Callbacks, Session, Flash, Renderer
end
# This module provides a class-level method for specifying that certain
@@ -102,7 +105,7 @@ module ActionController #:nodoc:
end
def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
- [*options[:params] ].find { |v| params[v].nil? } ||
+ [*options[:params] ].find { |v| v && params[v.to_sym].nil? } ||
[*options[:session]].find { |v| session[v].nil? } ||
[*options[:flash] ].find { |v| flash[v].nil? }
end