mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Added navigational formats to specify when it should return a 302 and when a 401, closes #234 and #249.
This commit is contained in:
parent
a65fd873dd
commit
bff64a6291
9 changed files with 63 additions and 30 deletions
|
@ -18,6 +18,7 @@
|
|||
* No need to append ?unauthenticated=true in URLs anymore since Flash was moved to a middleware in Rails 3.
|
||||
* :activatable is included by default in your models.
|
||||
* Allow to set cookie domain for the remember token. (by github.com/mantas)
|
||||
* Added navigational formats to specify when it should return a 302 and when a 401.
|
||||
|
||||
* bug fix
|
||||
* Fix a bug with STI.
|
||||
|
|
|
@ -147,6 +147,9 @@ module Devise
|
|||
mattr_accessor :token_authentication_key
|
||||
@@token_authentication_key = :auth_token
|
||||
|
||||
mattr_accessor :navigational_formats
|
||||
@@navigational_formats = [:html]
|
||||
|
||||
# Private methods to interface with Warden.
|
||||
mattr_accessor :warden_config
|
||||
@@warden_config = nil
|
||||
|
|
|
@ -64,7 +64,7 @@ module Devise
|
|||
end
|
||||
|
||||
def http_auth?
|
||||
request.authorization
|
||||
!Devise.navigational_formats.include?(request.format.to_sym) || request.xhr?
|
||||
end
|
||||
|
||||
def http_auth_body
|
||||
|
@ -97,7 +97,7 @@ module Devise
|
|||
# yet, but we still need to store the uri based on scope, so different scopes
|
||||
# would never use the same uri to redirect.
|
||||
def store_location!
|
||||
session[:"#{scope}_return_to"] = attempted_path if request && request.get?
|
||||
session[:"#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,11 @@ Devise.setup do |config|
|
|||
# Configure the e-mail address which will be shown in DeviseMailer.
|
||||
config.mailer_sender = "please-change-me@config-initializers-devise.com"
|
||||
|
||||
# ==> ORM configuration
|
||||
# Load and configure the ORM. Supports :active_record (default), :mongoid
|
||||
# (bson_ext recommended) and :data_mapper (experimental).
|
||||
require 'devise/orm/<%= options[:orm] %>'
|
||||
|
||||
# ==> Configuration for any authentication mechanism
|
||||
# Configure which keys are used when authenticating an user. By default is
|
||||
# just :email. You can configure it to use [:username, :subdomain], so for
|
||||
|
@ -85,11 +90,7 @@ Devise.setup do |config|
|
|||
# Defines name of the authentication token params key
|
||||
# config.token_authentication_key = :auth_token
|
||||
|
||||
# ==> General configuration
|
||||
# Load and configure the ORM. Supports :active_record (default), :mongoid
|
||||
# (bson_ext recommended) and :data_mapper (experimental).
|
||||
require 'devise/orm/<%= options[:orm] %>'
|
||||
|
||||
# ==> Scopes configuration
|
||||
# Turn scoped views on. Before rendering "sessions/new", it will first check for
|
||||
# "sessions/users/new". It's turned off by default because it's slower if you
|
||||
# are using only default views.
|
||||
|
@ -105,6 +106,15 @@ Devise.setup do |config|
|
|||
# role declared in your routes.
|
||||
# config.default_scope = :user
|
||||
|
||||
# ==> Navigation configuration
|
||||
# Lists the formats that should be treated as navigational. Formats like
|
||||
# :html, should redirect to the sign in page when the user does not have
|
||||
# access, but formats like :xml or :json, should return 401.
|
||||
# If you have any extra navigational formats, like :iphone or :mobile, you
|
||||
# should add them to the navigational formats lists. Default is [:html]
|
||||
# config.navigational_formats = [:html, :iphone]
|
||||
|
||||
# ==> Warden configuration
|
||||
# If you want to use other strategies, that are not (yet) supported by Devise,
|
||||
# you can configure them inside the config.warden block. The example below
|
||||
# allows you to setup OAuth, using http://github.com/roman/warden_oauth
|
||||
|
|
|
@ -8,11 +8,12 @@ class FailureTest < ActiveSupport::TestCase
|
|||
|
||||
def call_failure(env_params={})
|
||||
env = {
|
||||
'warden.options' => { :scope => :user },
|
||||
'REQUEST_URI' => 'http://test.host/',
|
||||
'HTTP_HOST' => 'test.host',
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'warden.options' => { :scope => :user },
|
||||
'rack.session' => {},
|
||||
'action_dispatch.request.formats' => Array(env_params.delete('formats') || :html),
|
||||
'rack.input' => "",
|
||||
'warden' => OpenStruct.new(:message => nil)
|
||||
}.merge!(env_params)
|
||||
|
@ -21,11 +22,6 @@ class FailureTest < ActiveSupport::TestCase
|
|||
@request = ActionDispatch::Request.new(env)
|
||||
end
|
||||
|
||||
def call_failure_with_http(env_params={})
|
||||
env = { "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("foo:bar")}" }
|
||||
call_failure(env_params.merge!(env))
|
||||
end
|
||||
|
||||
context 'When redirecting' do
|
||||
test 'return 302 status' do
|
||||
call_failure
|
||||
|
@ -61,22 +57,41 @@ class FailureTest < ActiveSupport::TestCase
|
|||
assert_match /redirected/, @response.last.body
|
||||
assert_match /users\/sign_in/, @response.last.body
|
||||
end
|
||||
|
||||
test 'works for any navigational format' do
|
||||
swap Devise, :navigational_formats => [:xml] do
|
||||
call_failure('formats' => :xml)
|
||||
assert_equal 302, @response.first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'For HTTP request' do
|
||||
test 'return 401 status' do
|
||||
call_failure_with_http
|
||||
call_failure('formats' => :xml)
|
||||
assert_equal 401, @response.first
|
||||
end
|
||||
|
||||
test 'return WWW-authenticate headers' do
|
||||
call_failure_with_http
|
||||
call_failure('formats' => :xml)
|
||||
assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
|
||||
end
|
||||
|
||||
test 'uses the proxy failure message as response body' do
|
||||
call_failure_with_http('warden' => OpenStruct.new(:message => :invalid))
|
||||
assert_equal 'Invalid email or password.', @response.third.body
|
||||
call_failure('formats' => :xml, 'warden' => OpenStruct.new(:message => :invalid))
|
||||
assert_match '<error>Invalid email or password.</error>', @response.third.body
|
||||
end
|
||||
|
||||
test 'works for any non navigational format' do
|
||||
swap Devise, :navigational_formats => [] do
|
||||
call_failure('formats' => :html)
|
||||
assert_equal 401, @response.first
|
||||
end
|
||||
end
|
||||
|
||||
test 'works for xml http requests' do
|
||||
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
|
||||
assert_equal 401, @response.first
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -155,7 +155,6 @@ class AuthenticationTest < ActionController::IntegrationTest
|
|||
|
||||
test 'redirect to default url if no other was configured' do
|
||||
sign_in_as_user
|
||||
|
||||
assert_template 'home/index'
|
||||
assert_nil session[:"user_return_to"]
|
||||
end
|
||||
|
@ -188,6 +187,12 @@ class AuthenticationTest < ActionController::IntegrationTest
|
|||
assert_nil session[:"user_return_to"]
|
||||
end
|
||||
|
||||
test 'xml http requests does not store urls for redirect' do
|
||||
get users_path, {}, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'
|
||||
assert_equal 401, response.status
|
||||
assert_nil session[:"user_return_to"]
|
||||
end
|
||||
|
||||
test 'redirect to configured home path for a given scope after sign in' do
|
||||
sign_in_as_admin
|
||||
assert_equal "/admin_area/home", @request.path
|
||||
|
|
|
@ -5,8 +5,7 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
|
|||
test 'sign in should authenticate with http' do
|
||||
sign_in_as_new_user_with_http
|
||||
assert_response :success
|
||||
assert_template 'users/index'
|
||||
assert_contain 'Welcome'
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
|
||||
|
@ -17,10 +16,10 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
|
|||
end
|
||||
|
||||
test 'uses the request format as response content type' do
|
||||
sign_in_as_new_user_with_http("unknown", "123456", :xml)
|
||||
sign_in_as_new_user_with_http("unknown")
|
||||
assert_equal 401, status
|
||||
assert_equal "application/xml; charset=utf-8", headers["Content-Type"]
|
||||
assert response.body.include?("<error>Invalid email or password.</error>")
|
||||
assert_match "<error>Invalid email or password.</error>", response.body
|
||||
end
|
||||
|
||||
test 'returns a custom response with www-authenticate and chosen realm' do
|
||||
|
@ -33,19 +32,18 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
|
|||
|
||||
test 'sign in should authenticate with http even with specific authentication keys' do
|
||||
swap Devise, :authentication_keys => [:username] do
|
||||
sign_in_as_new_user_with_http "usertest"
|
||||
sign_in_as_new_user_with_http("usertest")
|
||||
assert_response :success
|
||||
assert_template 'users/index'
|
||||
assert_contain 'Welcome'
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sign_in_as_new_user_with_http(username="user@test.com", password="123456", format=:html)
|
||||
def sign_in_as_new_user_with_http(username="user@test.com", password="123456")
|
||||
user = create_user
|
||||
get users_path(:format => format), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("#{username}:#{password}")}"
|
||||
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("#{username}:#{password}")}"
|
||||
user
|
||||
end
|
||||
end
|
|
@ -18,8 +18,7 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
|||
sign_in_as_new_user_with_token(:http_auth => true)
|
||||
|
||||
assert_response :success
|
||||
assert_template 'users/index'
|
||||
assert_contain 'Welcome'
|
||||
assert_match '<email>user@test.com</email>', response.body
|
||||
assert warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
@ -78,7 +77,7 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
|||
|
||||
if options[:http_auth]
|
||||
header = "Basic #{ActiveSupport::Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
|
||||
get users_path, {}, "HTTP_AUTHORIZATION" => header
|
||||
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
|
||||
else
|
||||
visit users_path(options[:auth_token_key].to_sym => options[:auth_token])
|
||||
end
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
class UsersController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
respond_to :html, :xml
|
||||
|
||||
def index
|
||||
user_session[:cart] = "Cart"
|
||||
respond_with(current_user)
|
||||
end
|
||||
|
||||
def expire
|
||||
|
|
Loading…
Reference in a new issue