Skip to content

Commit

Permalink
Start to add helpers for OAuth tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Jul 26, 2010
1 parent eb3118e commit ef841ca
Show file tree
Hide file tree
Showing 17 changed files with 174 additions and 85 deletions.
7 changes: 7 additions & 0 deletions app/controllers/devise/registrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ def destroy

protected

# Build a devise resource passing in the session. Useful to move
# temporary session data to the newly created user.
def build_resource(hash=nil)
hash ||= params[resource_name] || {}
self.resource = resource_class.new_with_session(hash, session)
end

# Authenticates the current scope and gets a copy of the current resource.
# We need to use a copy because we don't want actions like update changing
# the current user in place.
Expand Down
2 changes: 1 addition & 1 deletion lib/devise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def self.add_mapping(resource, options)
mapping = Devise::Mapping.new(resource, options)
@@mappings[mapping.name] = mapping
@@default_scope ||= mapping.name
@@helpers.each { |h| h.define_helpers(mapping.name) }
@@helpers.each { |h| h.define_helpers(mapping) }
mapping
end

Expand Down
2 changes: 2 additions & 0 deletions lib/devise/controllers/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ module Helpers
# before_filter :authenticate_admin! # Tell devise to use :admin map
#
def self.define_helpers(mapping) #:nodoc:
mapping = mapping.name

class_eval <<-METHODS, __FILE__, __LINE__ + 1
def authenticate_#{mapping}!
warden.authenticate!(:scope => :#{mapping})
Expand Down
2 changes: 1 addition & 1 deletion lib/devise/controllers/internal_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def resource=(new_resource)
# Build a devise resource.
def build_resource(hash=nil)
hash ||= params[resource_name] || {}
self.resource = resource_class.new_with_session(hash, session)
self.resource = resource_class.new(hash)
end

# Helper for use in before_filters where no authentication is required.
Expand Down
6 changes: 0 additions & 6 deletions lib/devise/models/authenticatable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@ def http_authenticatable?(strategy)
http_authenticatable.include?(strategy) : http_authenticatable
end

# By default discards all information sent by the session by calling
# new with params.
def new_with_session(params, session)
new(params)
end

# Find first record based on conditions given (ie by the sign in form).
# Overwrite to add customized conditions, create a join, or maybe use a
# namedscope to filter records while authenticating.
Expand Down
13 changes: 13 additions & 0 deletions lib/devise/models/registerable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ module Models
# Registerable is responsible for everything related to registering a new
# resource (ie user sign up).
module Registerable
extend ActiveSupport::Concern

module ClassMethods
# A convenience method that receives both parameters and session to
# initialize an user. This can be used by OAuth, for example, to send
# in the user token and be stored on initialization.
#
# By default discards all information sent by the session by calling
# new with params.
def new_with_session(params, session)
new(params)
end
end
end
end
end
11 changes: 11 additions & 0 deletions lib/devise/oauth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,16 @@ module Oauth
autoload :Helpers, "devise/oauth/helpers"
autoload :InternalHelpers, "devise/oauth/internal_helpers"
autoload :UrlHelpers, "devise/oauth/url_helpers"
autoload :TestHelpers, "devise/oauth/test_helpers"

class << self
delegate :short_circuit_authorizers!, :unshort_circuit_authorizers!, :to => "Devise::Oauth::TestHelpers"

def test_mode!
Faraday.default_adapter = :test
ActiveSupport.on_load(:action_controller) { include Devise::Oauth::TestHelpers }
ActiveSupport.on_load(:action_view) { include Devise::Oauth::TestHelpers }
end
end
end
end
1 change: 0 additions & 1 deletion lib/devise/oauth/internal_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ def callback_action
clean_up_passwords(resource)
render_for_oauth
else
session[oauth_session_key] = access_token.token
set_oauth_flash_message :alert, :skipped
redirect_to after_oauth_skipped_path_for(resource_name)
end
Expand Down
29 changes: 29 additions & 0 deletions lib/devise/oauth/test_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Devise
module Oauth
module TestHelpers #:nodoc:
def self.short_circuit_authorizers!
module_eval <<-ALIASES, __FILE__, __LINE__ + 1
def oauth_authorize_url(scope, provider)
oauth_callback_url(scope, provider, :code => "12345")
end
ALIASES

Devise.mappings.each_value do |m|
next unless m.oauthable?

module_eval <<-ALIASES, __FILE__, __LINE__ + 1
def #{m.name}_oauth_authorize_url(provider)
#{m.name}_oauth_callback_url(provider, :code => "12345")
end
ALIASES
end
end

def self.unshort_circuit_authorizers!
module_eval do
instance_methods.each { |m| remove_method(m) }
end
end
end
end
end
6 changes: 4 additions & 2 deletions lib/devise/oauth/url_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ module Devise
module Oauth
module UrlHelpers
def self.define_helpers(mapping)
return unless mapping.oauthable?

class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
def #{mapping}_oauth_authorize_url(provider, options={})
def #{mapping.name}_oauth_authorize_url(provider, options={})
if config = Devise.oauth_configs[provider.to_sym]
options[:redirect_uri] ||= #{mapping}_oauth_callback_url(provider.to_s)
options[:redirect_uri] ||= #{mapping.name}_oauth_callback_url(provider.to_s)
config.authorize_url(options)
else
raise ArgumentError, "Could not find oauth provider \#{provider.inspect}"
Expand Down
124 changes: 57 additions & 67 deletions test/integration/authenticatable_test.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
require 'test_helper'

class AuthenticationSanityTest < ActionController::IntegrationTest

def setup
Devise.sign_out_all_scopes = false
end

def teardown
Devise.sign_out_all_scopes = false
end

test 'home should be accessible without sign in' do
visit '/'
assert_response :success
Expand All @@ -18,74 +9,74 @@ def teardown

test 'sign in as user should not authenticate admin scope' do
sign_in_as_user

assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end

test 'sign in as admin should not authenticate user scope' do
sign_in_as_admin

assert warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
end

test 'sign in as both user and admin at same time' do
sign_in_as_user
sign_in_as_admin

assert warden.authenticated?(:user)
assert warden.authenticated?(:admin)
end

test 'sign out as user should not touch admin authentication if sign_out_all_scopes is false' do
sign_in_as_user
sign_in_as_admin

get destroy_user_session_path
assert_not warden.authenticated?(:user)
assert warden.authenticated?(:admin)
swap Devise, :sign_out_all_scopes => false do
sign_in_as_user
sign_in_as_admin
get destroy_user_session_path
assert_not warden.authenticated?(:user)
assert warden.authenticated?(:admin)
end
end

test 'sign out as admin should not touch user authentication if sign_out_all_scopes is false' do
sign_in_as_user
sign_in_as_admin
swap Devise, :sign_out_all_scopes => false do
sign_in_as_user
sign_in_as_admin

get destroy_admin_session_path
assert_not warden.authenticated?(:admin)
assert warden.authenticated?(:user)
get destroy_admin_session_path
assert_not warden.authenticated?(:admin)
assert warden.authenticated?(:user)
end
end

test 'sign out as user should also sign out admin if sign_out_all_scopes is true' do
Devise.sign_out_all_scopes = true
sign_in_as_user
sign_in_as_admin
swap Devise, :sign_out_all_scopes => true do
sign_in_as_user
sign_in_as_admin

get destroy_user_session_path
assert_not warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
get destroy_user_session_path
assert_not warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
end

test 'sign out as admin should also sign out user if sign_out_all_scopes is true' do
Devise.sign_out_all_scopes = true
sign_in_as_user
sign_in_as_admin
swap Devise, :sign_out_all_scopes => true do
sign_in_as_user
sign_in_as_admin

get destroy_admin_session_path
assert_not warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
get destroy_admin_session_path
assert_not warden.authenticated?(:admin)
assert_not warden.authenticated?(:user)
end
end

test 'not signed in as admin should not be able to access admins actions' do
get admins_path

assert_redirected_to new_admin_session_path
assert_not warden.authenticated?(:admin)
end

test 'not signed in as admin should not be able to access private route restricted to admins' do
get private_path

assert_redirected_to new_admin_session_path
assert_not warden.authenticated?(:admin)
end
Expand All @@ -94,7 +85,6 @@ def teardown
sign_in_as_user
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)

get private_path
assert_redirected_to new_admin_session_path
end
Expand Down Expand Up @@ -236,6 +226,25 @@ class AuthenticationSessionTest < ActionController::IntegrationTest
get '/users'
assert_equal "Cart", @controller.user_session[:cart]
end

test 'does not explode when invalid user class is stored in session' do
klass = User
paths = ActiveSupport::Dependencies.autoload_paths.dup

begin
sign_in_as_user
assert warden.authenticated?(:user)

Object.send :remove_const, :User
ActiveSupport::Dependencies.autoload_paths.clear

visit "/users"
assert_not warden.authenticated?(:user)
ensure
Object.const_set(:User, klass)
ActiveSupport::Dependencies.autoload_paths.replace(paths)
end
end
end

class AuthenticationWithScopesTest < ActionController::IntegrationTest
Expand Down Expand Up @@ -277,18 +286,6 @@ class AuthenticationWithScopesTest < ActionController::IntegrationTest
end
end
end

test 'uses the mapping from router' do
sign_in_as_user :visit => "/as/sign_in"
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end

test 'uses the mapping from nested devise_for call' do
sign_in_as_user :visit => "/devise_for/sign_in"
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
end

class AuthenticationOthersTest < ActionController::IntegrationTest
Expand Down Expand Up @@ -317,28 +314,21 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
end
end

test 'registration in xml format' do
test 'registration in xml format works when recognizing path' do
assert_nothing_raised do
post user_registration_path(:format => 'xml', :user => {:email => "test@example.com", :password => "invalid"} )
end
end

test 'does not explode when invalid user class is stored in session' do
klass = User
paths = ActiveSupport::Dependencies.autoload_paths.dup

begin
sign_in_as_user
assert warden.authenticated?(:user)

Object.send :remove_const, :User
ActiveSupport::Dependencies.autoload_paths.clear
test 'uses the mapping from router' do
sign_in_as_user :visit => "/as/sign_in"
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end

visit "/users"
assert_not warden.authenticated?(:user)
ensure
Object.const_set(:User, klass)
ActiveSupport::Dependencies.autoload_paths.replace(paths)
end
test 'uses the mapping from nested devise_for call' do
sign_in_as_user :visit => "/devise_for/sign_in"
assert warden.authenticated?(:user)
assert_not warden.authenticated?(:admin)
end
end
31 changes: 31 additions & 0 deletions test/integration/oauthable_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'test_helper'

class OAuthableTest < ActionController::IntegrationTest
FACEBOOK_INFO = {
:username => 'usertest',
:email => 'user@test.com'
}

ACCESS_TOKEN = {
:access_token => "plataformatec"
}

stubs = Faraday::Adapter::Test::Stubs.new do |stub|
stub.post('/oauth/access_token') { [200, {}, ACCESS_TOKEN.to_json] }
stub.get('/me?access_token=plataformatec') { [200, {}, FACEBOOK_INFO.to_json] }
end

User.oauth_configs[:facebook].client.connection.build do |b|
b.adapter :test, stubs
end

setup { Devise::Oauth.short_circuit_authorizers! }
teardown { Devise::Oauth.unshort_circuit_authorizers! }

test "omg" do
assert_difference "User.count", 1 do
get "/users/sign_up"
click_link "Sign in with Facebook"
end
end
end

0 comments on commit ef841ca

Please sign in to comment.