diff options
Diffstat (limited to 'actionpack')
19 files changed, 91 insertions, 68 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 0a31e34d3d..e0076225ba 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,10 @@ +* Fix rake routes not showing the right format when + nesting multiple routes. + + See #18373. + + *Ravil Bayramgalin* + * Add ability to override default form builder for a controller. class AdminController < ApplicationController diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 909ed19a49..32c3c9652f 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -74,16 +74,16 @@ module ActionController end end - def authenticate_or_request_with_http_basic(realm = "Application", &login_procedure) - authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm) + def authenticate_or_request_with_http_basic(realm = "Application", message = nil, &login_procedure) + authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm, message) end def authenticate_with_http_basic(&login_procedure) HttpAuthentication::Basic.authenticate(request, &login_procedure) end - def request_http_basic_authentication(realm = "Application") - HttpAuthentication::Basic.authentication_request(self, realm) + def request_http_basic_authentication(realm = "Application", message = nil) + HttpAuthentication::Basic.authentication_request(self, realm, message) end end @@ -117,10 +117,11 @@ module ActionController "Basic #{::Base64.strict_encode64("#{user_name}:#{password}")}" end - def authentication_request(controller, realm) + def authentication_request(controller, realm, message) + message ||= "HTTP Basic: Access denied.\n" controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.tr('"'.freeze, "".freeze)}") controller.status = 401 - controller.response_body = "HTTP Basic: Access denied.\n" + controller.response_body = message end end @@ -170,8 +171,8 @@ module ActionController extend self module ControllerMethods - def authenticate_or_request_with_http_digest(realm = "Application", &password_procedure) - authenticate_with_http_digest(realm, &password_procedure) || request_http_digest_authentication(realm) + def authenticate_or_request_with_http_digest(realm = "Application", message = nil, &password_procedure) + authenticate_with_http_digest(realm, &password_procedure) || request_http_digest_authentication(realm, message) end # Authenticate with HTTP Digest, returns true or false @@ -401,16 +402,16 @@ module ActionController extend self module ControllerMethods - def authenticate_or_request_with_http_token(realm = "Application", &login_procedure) - authenticate_with_http_token(&login_procedure) || request_http_token_authentication(realm) + def authenticate_or_request_with_http_token(realm = "Application", message = nil, &login_procedure) + authenticate_with_http_token(&login_procedure) || request_http_token_authentication(realm, message) end def authenticate_with_http_token(&login_procedure) Token.authenticate(self, &login_procedure) end - def request_http_token_authentication(realm = "Application") - Token.authentication_request(self, realm) + def request_http_token_authentication(realm = "Application", message = nil) + Token.authentication_request(self, realm, message) end end @@ -498,9 +499,10 @@ module ActionController # realm - String realm to use in the header. # # Returns nothing. - def authentication_request(controller, realm) + def authentication_request(controller, realm, message = nil) + message ||= "HTTP Token: Access denied.\n" controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"'.freeze, "".freeze)}") - controller.__send__ :render, :text => "HTTP Token: Access denied.\n", :status => :unauthorized + controller.__send__ :render, :text => message, :status => :unauthorized end end end diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 663a969f72..31c8856437 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -15,9 +15,9 @@ module ActionController #:nodoc: # access. When a request reaches your application, \Rails verifies the received # token with the token in the session. All requests are checked except GET requests # as these should be idempotent. Keep in mind that all session-oriented requests - # should be CSRF protected, including Javascript and HTML requests. + # should be CSRF protected, including JavaScript and HTML requests. # - # Since HTML and Javascript requests are typically made from the browser, we + # Since HTML and JavaScript requests are typically made from the browser, we # need to ensure to verify request authenticity for the web browser. We can # use session-oriented authentication for these types requests, by using # the `protect_form_forgery` method in our controllers. @@ -40,7 +40,8 @@ module ActionController #:nodoc: # # CSRF protection is turned on with the <tt>protect_from_forgery</tt> method. # By default <tt>protect_from_forgery</tt> protects your session with - # <tt>:null_session</tt> method, which provides an empty session during request + # <tt>:null_session</tt> method, which provides an empty session + # during request. # # We may want to disable CSRF protection for APIs since they are typically # designed to be state-less. That is, the requestion API client will handle @@ -96,10 +97,10 @@ module ActionController #:nodoc: # Valid Options: # # * <tt>:only/:except</tt> - Only apply forgery protection to a subset of actions. Like <tt>only: [ :create, :create_all ]</tt>. - # * <tt>:if/:unless</tt> - Turn off the forgery protection entirely depending on the passed proc or method reference. + # * <tt>:if/:unless</tt> - Turn off the forgery protection entirely depending on the passed Proc or method reference. # * <tt>:prepend</tt> - By default, the verification of the authentication token is added to the front of the # callback chain. If you need to make the verification depend on other callbacks, like authentication methods - # (say cookies vs oauth), this might not work for you. Pass <tt>prepend: false</tt> to just add the + # (say cookies vs OAuth), this might not work for you. Pass <tt>prepend: false</tt> to just add the # verification callback in the position of the protect_from_forgery call. This means any callbacks added # before are run first. # * <tt>:with</tt> - Set the method to handle unverified request. diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 33c24999f9..ca7ba90c40 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -604,7 +604,7 @@ module ActionController def process(action, *args) check_required_ivars - if kwarg_request?(*args) + if kwarg_request?(args) parameters, session, body, flash, http_method, format, xhr = args[0].values_at(:params, :session, :body, :flash, :method, :format, :xhr) else http_method, parameters, session, flash = args @@ -745,7 +745,7 @@ module ActionController private def process_with_kwargs(http_method, action, *args) - if kwarg_request?(*args) + if kwarg_request?(args) args.first.merge!(method: http_method) process(action, *args) else @@ -757,7 +757,7 @@ module ActionController end REQUEST_KWARGS = %i(params session flash method body xhr) - def kwarg_request?(*args) + def kwarg_request?(args) args[0].respond_to?(:keys) && ( (args[0].key?(:format) && args[0].keys.size == 1) || args[0].keys.any? { |k| REQUEST_KWARGS.include?(k) } diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 2b851cc28d..3170389b36 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -16,7 +16,7 @@ module ActionDispatch # env["action_dispatch.parameter_filter"] = [:foo, "bar"] # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]" # - # env["action_dispatch.parameter_filter"] = lambda do |k,v| + # env["action_dispatch.parameter_filter"] = -> (k, v) do # v.reverse! if k =~ /secret/i # end # => reverses the value to all keys matching /secret/i diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb index 4d5c18984a..4698ff8cc7 100644 --- a/actionpack/lib/action_dispatch/journey/route.rb +++ b/actionpack/lib/action_dispatch/journey/route.rb @@ -36,7 +36,7 @@ module ActionDispatch def requirements # :nodoc: # needed for rails `rake routes` - path.requirements.merge(@defaults).delete_if { |_,v| + @defaults.merge(path.requirements).delete_if { |_,v| /.+?/ == v } end diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index b1f0f5fc28..dd1f140051 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -79,6 +79,9 @@ module ActionDispatch # domain: %w(.example.com .example.org) # Allow the cookie # # for concrete domain names. # + # * <tt>:tld_length</tt> - When using <tt>:domain => :all</tt>, this option can be used to explicitly + # set the TLD length when using a short (<= 3 character) domain that is being interpreted as part of a TLD. + # For example, to share cookies between user1.lvh.me and user2.lvh.me, set <tt>:tld_length</tt> to 1. # * <tt>:expires</tt> - The time at which this cookie expires, as a \Time object. # * <tt>:secure</tt> - Whether this cookie is only transmitted to HTTPS servers. # Default is +false+. @@ -181,7 +184,7 @@ module ActionDispatch # to the Message{Encryptor,Verifier} allows us to handle the # (de)serialization step within the cookie jar, which gives us the # opportunity to detect and migrate legacy cookies. - module VerifyAndUpgradeLegacySignedMessage + module VerifyAndUpgradeLegacySignedMessage # :nodoc: def initialize(*args) super @legacy_verifier = ActiveSupport::MessageVerifier.new(@options[:secret_token], serializer: ActiveSupport::MessageEncryptor::NullSerializer) @@ -392,7 +395,7 @@ module ActionDispatch end end - class JsonSerializer + class JsonSerializer # :nodoc: def self.load(value) ActiveSupport::JSON.decode(value) end @@ -402,7 +405,7 @@ module ActionDispatch end end - module SerializedCookieJars + module SerializedCookieJars # :nodoc: MARSHAL_SIGNATURE = "\x04\x08".freeze protected @@ -454,12 +457,16 @@ module ActionDispatch @verifier = ActiveSupport::MessageVerifier.new(secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer) end + # Returns the value of the cookie by +name+ if it is untampered, + # returns +nil+ otherwise or if no such cookie exists. def [](name) if signed_message = @parent_jar[name] deserialize name, verify(signed_message) end end + # Signs and sets the cookie named +name+. The second argument may be the cookie's + # value or a hash of options as documented above. def []=(name, options) if options.is_a?(Hash) options.symbolize_keys! @@ -511,12 +518,16 @@ module ActionDispatch @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer) end + # Returns the value of the cookie by +name+ if it is untampered, + # returns +nil+ otherwise or if no such cookie exists. def [](name) if encrypted_message = @parent_jar[name] deserialize name, decrypt_and_verify(encrypted_message) end end + # Encrypts and sets the cookie named +name+. The second argument may be the cookie's + # value or a hash of options as documented above. def []=(name, options) if options.is_a?(Hash) options.symbolize_keys! diff --git a/actionpack/lib/action_dispatch/middleware/reloader.rb b/actionpack/lib/action_dispatch/middleware/reloader.rb index 15b5a48535..6c7fba00cb 100644 --- a/actionpack/lib/action_dispatch/middleware/reloader.rb +++ b/actionpack/lib/action_dispatch/middleware/reloader.rb @@ -11,9 +11,9 @@ module ActionDispatch # the response body. This is important for streaming responses such as the # following: # - # self.response_body = lambda { |response, output| + # self.response_body = -> (response, output) do # # code here which refers to application models - # } + # end # # Cleanup callbacks will not be called until after the response_body lambda # is evaluated, ensuring that it can refer to application models and other diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index c47e5d5245..bc5ef1abc9 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -26,7 +26,7 @@ module ActionDispatch # representing the filename. Otherwise, false is returned. # # Used by the `Static` class to check the existence of a valid file - # in the server's `public/` directory. (See Static#call) + # in the server's `public/` directory (see Static#call). def match?(path) path = URI.parser.unescape(path) return false unless path.valid_encoding? diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb index c513737fc2..48c10a7d4c 100644 --- a/actionpack/lib/action_dispatch/routing/inspector.rb +++ b/actionpack/lib/action_dispatch/routing/inspector.rb @@ -45,7 +45,7 @@ module ActionDispatch end def internal? - controller.to_s =~ %r{\Arails/(info|mailers|welcome)} || path =~ %r{\A#{Rails.application.config.assets.prefix}\z} + controller.to_s =~ %r{\Arails/(info|mailers|welcome)} end def engine? diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 49009a45cc..0a444ddffc 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -418,7 +418,7 @@ module ActionDispatch # A pattern can also point to a +Rack+ endpoint i.e. anything that # responds to +call+: # - # match 'photos/:id', to: lambda {|hash| [200, {}, ["Coming soon"]] }, via: :get + # match 'photos/:id', to: -> (hash) { [200, {}, ["Coming soon"]] }, via: :get # match 'photos/:id', to: PhotoRackApp, via: :get # # Yes, controller actions are just rack endpoints # match 'photos/:id', to: PhotosController.action(:show), via: :get @@ -470,7 +470,7 @@ module ActionDispatch # +call+ or a string representing a controller's action. # # match 'path', to: 'controller#action', via: :get - # match 'path', to: lambda { |env| [200, {}, ["Success!"]] }, via: :get + # match 'path', to: -> (env) { [200, {}, ["Success!"]] }, via: :get # match 'path', to: RackApp, via: :get # # [:on] @@ -899,7 +899,7 @@ module ActionDispatch # # Requests to routes can be constrained based on specific criteria: # - # constraints(lambda { |req| req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do + # constraints(-> (req) { req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do # resources :iphones # end # diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 3800c61dab..b1bd6ae6d5 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -81,7 +81,7 @@ module ActionDispatch # # xhr :get, '/feed', params: { since: 201501011400 } def xml_http_request(request_method, path, *args) - if kwarg_request?(*args) + if kwarg_request?(args) params, headers, env = args.first.values_at(:params, :headers, :env) else params = args[0] @@ -291,7 +291,7 @@ module ActionDispatch end def process_with_kwargs(http_method, path, *args) - if kwarg_request?(*args) + if kwarg_request?(args) process(http_method, path, *args) else non_kwarg_request_warning if args.present? @@ -300,7 +300,7 @@ module ActionDispatch end REQUEST_KWARGS = %i(params headers env xhr) - def kwarg_request?(*args) + def kwarg_request?(args) args[0].respond_to?(:keys) && args[0].keys.any? { |k| REQUEST_KWARGS.include?(k) } end diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb index 20962a90cb..10fbee7582 100644 --- a/actionpack/test/controller/http_basic_authentication_test.rb +++ b/actionpack/test/controller/http_basic_authentication_test.rb @@ -36,7 +36,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase if authenticate_with_http_basic { |username, password| username == 'pretty' && password == 'please' } @logged_in = true else - request_http_basic_authentication("SuperSecret") + request_http_basic_authentication("SuperSecret", "Authentication Failed\n") end end @@ -104,7 +104,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase get :display assert_response :unauthorized - assert_equal "HTTP Basic: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Basic realm="SuperSecret"', @response.headers['WWW-Authenticate'] end @@ -113,7 +113,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase get :display assert_response :unauthorized - assert_equal "HTTP Basic: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Basic realm="SuperSecret"', @response.headers['WWW-Authenticate'] end diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb index a758df2ec6..2521f0322c 100644 --- a/actionpack/test/controller/http_token_authentication_test.rb +++ b/actionpack/test/controller/http_token_authentication_test.rb @@ -30,7 +30,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase if authenticate_with_http_token { |token, options| token == '"quote" pretty' && options[:algorithm] == 'test' } @logged_in = true else - request_http_token_authentication("SuperSecret") + request_http_token_authentication("SuperSecret", "Authentication Failed\n") end end @@ -91,7 +91,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase get :display assert_response :unauthorized - assert_equal "HTTP Token: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Token realm="SuperSecret"', @response.headers['WWW-Authenticate'] end @@ -100,7 +100,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase get :display assert_response :unauthorized - assert_equal "HTTP Token: Access denied.\n", @response.body + assert_equal "Authentication Failed\n", @response.body assert_equal 'Token realm="SuperSecret"', @response.headers['WWW-Authenticate'] end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index efd790de63..ef30f1ea0f 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -1,8 +1,5 @@ require 'abstract_unit' -class WorkshopsController < ActionController::Base -end - class RedirectController < ActionController::Base # empty method not used anywhere to ensure methods like # `status` and `location` aren't called on `redirect_to` calls diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 8887f291cf..f8cf79a257 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -12,14 +12,6 @@ module RequestForgeryProtectionActions render :inline => "<%= button_to('New', '/') %>" end - def external_form - render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => 'external_token') {} %>" - end - - def external_form_without_protection - render :inline => "<%= form_tag('http://farfar.away/form', :authenticity_token => false) {} %>" - end - def unsafe render :text => 'pwn' end @@ -28,14 +20,6 @@ module RequestForgeryProtectionActions render :inline => "<%= csrf_meta_tags %>" end - def external_form_for - render :inline => "<%= form_for(:some_resource, :authenticity_token => 'external_token') {} %>" - end - - def form_for_without_protection - render :inline => "<%= form_for(:some_resource, :authenticity_token => false ) {} %>" - end - def form_for_remote render :inline => "<%= form_for(:some_resource, :remote => true ) {} %>" end @@ -70,7 +54,6 @@ module RequestForgeryProtectionActions negotiate_same_origin end - def rescue_action(e) raise e end end # sample controllers diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 2d08987ca6..9bbfb74e72 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -8,8 +8,6 @@ class MilestonesController < ActionController::Base alias_method :show, :index end -ROUTING = ActionDispatch::Routing - # See RFC 3986, section 3.3 for allowed path characters. class UriReservedCharactersRoutingTest < ActiveSupport::TestCase include RoutingTestHelpers @@ -871,7 +869,7 @@ class RouteSetTest < ActiveSupport::TestCase def default_route_set @default_route_set ||= begin - set = ROUTING::RouteSet.new + set = ActionDispatch::Routing::RouteSet.new set.draw do get '/:controller(/:action(/:id))' end @@ -1748,13 +1746,13 @@ class RouteSetTest < ActiveSupport::TestCase include ActionDispatch::RoutingVerbs - class TestSet < ROUTING::RouteSet + class TestSet < ActionDispatch::Routing::RouteSet def initialize(block) @block = block super() end - class Dispatcher < ROUTING::RouteSet::Dispatcher + class Dispatcher < ActionDispatch::Routing::RouteSet::Dispatcher def initialize(defaults, set, block) super(defaults) @block = block diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb index 3df022c64b..4047214843 100644 --- a/actionpack/test/dispatch/routing/inspector_test.rb +++ b/actionpack/test/dispatch/routing/inspector_test.rb @@ -313,6 +313,22 @@ module ActionDispatch assert_equal ["Prefix Verb URI Pattern Controller#Action", " GET /:controller(/:action) (?-mix:api\\/[^\\/]+)#:action"], output end + + def test_inspect_routes_shows_resources_route_when_assets_disabled + @set = ActionDispatch::Routing::RouteSet.new + app = ActiveSupport::OrderedOptions.new + + Rails.stubs(:application).returns(app) + + output = draw do + get '/cart', to: 'cart#show' + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " cart GET /cart(.:format) cart#show" + ], output + end end end end diff --git a/actionpack/test/journey/route_test.rb b/actionpack/test/journey/route_test.rb index 21d867aca0..0980df06e8 100644 --- a/actionpack/test/journey/route_test.rb +++ b/actionpack/test/journey/route_test.rb @@ -25,6 +25,14 @@ module ActionDispatch end end + def test_path_requirements_override_defaults + strexp = Router::Strexp.build(':name', { name: /love/ }, ['/']) + path = Path::Pattern.new strexp + defaults = { name: 'tender' } + route = Route.new('name', nil, path, nil, defaults) + assert_equal(/love/, route.requirements[:name]) + end + def test_ip_address path = Path::Pattern.from_string '/messages/:id(.:format)' route = Route.new("name", nil, path, {:ip => '192.168.1.1'}, |
