From 4d8f5ea1659dbb7a2729d320283a9b2cb6827c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 6 Jan 2010 14:31:00 +0100 Subject: [PATCH] Add an easy way to configure an application to sign in users through "/sign_in". First, configure your routes: map.devise_for :users map.sign_in "/sign_in", :controller => "sessions", :action => "new" Then, in config/initializers/devise.rb: config.use_default_scope = true The default scope is always the first declaration in routes.rb, but if you need to change it, you can also do it through the initializer: config.default_scope = :user --- CHANGELOG.rdoc | 1 + generators/devise_install/templates/devise.rb | 16 +++++++++--- lib/devise.rb | 8 ++++-- lib/devise/controllers/helpers.rb | 6 ++++- lib/devise/mapping.rb | 2 +- test/integration/authenticatable_test.rb | 26 ++++++++++++++----- .../config/initializers/new_rails_defaults.rb | 5 +++- test/rails_app/config/routes.rb | 1 + 8 files changed, 51 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 67202382..dffa838c 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,5 +1,6 @@ * enhancements * Warden 0.8.0 compatibility + * Add an easy for map.connect 'sign_in', :controller => "sessions", :action => "new" to work * deprecation * Removed DeviseMailer.sender diff --git a/generators/devise_install/templates/devise.rb b/generators/devise_install/templates/devise.rb index 900855eb..dfc8eb88 100644 --- a/generators/devise_install/templates/devise.rb +++ b/generators/devise_install/templates/devise.rb @@ -10,6 +10,9 @@ Devise.setup do |config| # to check the docs for a complete set. config.all = [:authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable] + # Configure the e-mail address which will be shown in DeviseMailer. + config.mailer_sender = "please-change-me@config-initializers-devise.com" + # Invoke `rake secret` and use the printed value to setup a pepper to generate # the encrypted password. By default no pepper is used. # config.pepper = "rake secret output" @@ -42,9 +45,6 @@ Devise.setup do |config| # time the user will be asked for credentials again. # config.timeout_in = 10.minutes - # Configure the e-mail address which will be shown in DeviseMailer. - config.mailer_sender = "please-change-me@config-initializers-devise.com" - # Load and configure the ORM. Supports :active_record, :data_mapper and :mongo_mapper. # require 'devise/orm/mongo_mapper' # config.orm = :mongo_mapper @@ -54,6 +54,16 @@ Devise.setup do |config| # are using only default views. # config.scoped_views = true + # By default, devise detects the role accessed based on the url. So whenever + # accessing "/users/sign_in", it knows you are accessing an User. This makes + # routes as "/sign_in" not possible, unless you tell Devise to use the default + # scope, setting true below. + # config.use_default_scope = true + + # Configure the default scope used by Devise. By default it's the first devise + # role declared in your routes. + # config.default_scope = :user + # 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 diff --git a/lib/devise.rb b/lib/devise.rb index 8c64901b..338bfca5 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -103,11 +103,15 @@ module Devise mattr_accessor :scoped_views @@scoped_views = false - # The default scope which is used by warden + # Tell when to use the default scope, if one cannot be found from routes. + mattr_accessor :use_default_scope + @@use_default_scope + + # The default scope which is used by warden. mattr_accessor :default_scope @@default_scope = nil - # Address which sends Devise e-mails + # Address which sends Devise e-mails. mattr_accessor :mailer_sender @@mailer_sender diff --git a/lib/devise/controllers/helpers.rb b/lib/devise/controllers/helpers.rb index e3ee4012..8f51360d 100644 --- a/lib/devise/controllers/helpers.rb +++ b/lib/devise/controllers/helpers.rb @@ -35,7 +35,11 @@ module Devise # Attempt to find the mapped route for devise based on request path def devise_mapping - @devise_mapping ||= Devise::Mapping.find_by_path(request.path) + @devise_mapping ||= begin + mapping = Devise::Mapping.find_by_path(request.path) + mapping ||= Devise.mappings[Devise.default_scope] if Devise.use_default_scope + mapping + end end # Overwrites devise_controller? to return true diff --git a/lib/devise/mapping.rb b/lib/devise/mapping.rb index 183bbd48..8c984e2c 100644 --- a/lib/devise/mapping.rb +++ b/lib/devise/mapping.rb @@ -29,7 +29,7 @@ module Devise def self.find_by_path(path) Devise.mappings.each_value do |mapping| route = path.split("/")[mapping.as_position] - return mapping if mapping.as == route.to_sym + return mapping if route && mapping.as == route.to_sym end nil end diff --git a/test/integration/authenticatable_test.rb b/test/integration/authenticatable_test.rb index 1b72c134..674cd1fc 100644 --- a/test/integration/authenticatable_test.rb +++ b/test/integration/authenticatable_test.rb @@ -154,12 +154,6 @@ class AuthenticationTest < ActionController::IntegrationTest assert_contain 'You need to sign in or sign up before continuing.' end - test 'render 404 on roles without permission' do - get 'admin_area/password/new' - assert_response :not_found - assert_not_contain 'Send me reset password instructions' - end - test 'return to default url if no other was requested' do sign_in_as_user @@ -221,4 +215,24 @@ class AuthenticationTest < ActionController::IntegrationTest end end end + + test 'render 404 on roles without permission' do + get 'admin_area/password/new' + assert_response :not_found + assert_not_contain 'Send me reset password instructions' + end + + test 'render 404 on roles without mapping' do + get 'sign_in' + assert_response :not_found + assert_not_contain 'Sign in' + end + + test 'uses the mapping from the default scope if specified' do + swap Devise, :use_default_scope => true do + get 'sign_in' + assert_response :ok + assert_contain 'Sign in' + end + end end diff --git a/test/rails_app/config/initializers/new_rails_defaults.rb b/test/rails_app/config/initializers/new_rails_defaults.rb index c94db0a6..d0df8b9e 100644 --- a/test/rails_app/config/initializers/new_rails_defaults.rb +++ b/test/rails_app/config/initializers/new_rails_defaults.rb @@ -18,4 +18,7 @@ ActiveSupport.use_standard_json_time_format = true # Don't escape HTML entities in JSON, leave that for the #json_escape helper. # if you're including raw json in an HTML page. -ActiveSupport.escape_html_entities_in_json = false \ No newline at end of file +ActiveSupport.escape_html_entities_in_json = false + +# Clean up silencers +Rails.backtrace_cleaner.remove_silencers! \ No newline at end of file diff --git a/test/rails_app/config/routes.rb b/test/rails_app/config/routes.rb index 30542845..add3dab2 100644 --- a/test/rails_app/config/routes.rb +++ b/test/rails_app/config/routes.rb @@ -12,6 +12,7 @@ ActionController::Routing::Routes.draw do |map| map.connect '/admin_area/password/new', :controller => "passwords", :action => "new" map.admin_root '/admin_area/home', :controller => "admins", :action => "index" + map.connect '/sign_in', :controller => "sessions", :action => "new" map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end