mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Allow devise_for to be scoped with the scope method. This commit requires latest commits in Rails master.
This commit is contained in:
parent
78e7642bd2
commit
2103a673f0
5 changed files with 96 additions and 62 deletions
|
@ -149,6 +149,7 @@ module Devise
|
||||||
mattr_accessor :token_authentication_key
|
mattr_accessor :token_authentication_key
|
||||||
@@token_authentication_key = :auth_token
|
@@token_authentication_key = :auth_token
|
||||||
|
|
||||||
|
# Which formats should be treated as navigational.
|
||||||
mattr_accessor :navigational_formats
|
mattr_accessor :navigational_formats
|
||||||
@@navigational_formats = [:html]
|
@@navigational_formats = [:html]
|
||||||
|
|
||||||
|
@ -157,9 +158,14 @@ module Devise
|
||||||
@@warden_config = nil
|
@@warden_config = nil
|
||||||
@@warden_config_block = nil
|
@@warden_config_block = nil
|
||||||
|
|
||||||
|
# When set to true, signing out an user signs out all other scopes.
|
||||||
mattr_accessor :sign_out_all_scopes
|
mattr_accessor :sign_out_all_scopes
|
||||||
@@sign_out_all_scopes = false
|
@@sign_out_all_scopes = false
|
||||||
|
|
||||||
|
# When set to true, optional segments in Devise no longer raises an error.
|
||||||
|
mattr_accessor :ignore_optional_segments
|
||||||
|
@@ignore_otional_segments = false
|
||||||
|
|
||||||
# Default way to setup Devise. Run rails generate devise_install to create
|
# Default way to setup Devise. Run rails generate devise_install to create
|
||||||
# a fresh initializer with all configuration values.
|
# a fresh initializer with all configuration values.
|
||||||
def self.setup
|
def self.setup
|
||||||
|
|
|
@ -70,6 +70,12 @@ module Devise
|
||||||
|
|
||||||
@path_prefix = "/#{options.delete(:path_prefix)}/".squeeze("/")
|
@path_prefix = "/#{options.delete(:path_prefix)}/".squeeze("/")
|
||||||
|
|
||||||
|
if @path_prefix =~ /\(.*\)/ && Devise.ignore_optional_segments != true
|
||||||
|
raise ScriptError, "It seems that you are scoping devise_for with an optional segment #{@path_prefix.inspect} " <<
|
||||||
|
"which Devise does not support. Please remove the optional segment or alternatively, if you are *sure* of " <<
|
||||||
|
"what you are doing, you can set config.ignore_optional_segments = true in your devise initializer."
|
||||||
|
end
|
||||||
|
|
||||||
@controllers = Hash.new { |h,k| h[k] = "devise/#{k}" }
|
@controllers = Hash.new { |h,k| h[k] = "devise/#{k}" }
|
||||||
@controllers.merge!(options.delete(:controllers) || {})
|
@controllers.merge!(options.delete(:controllers) || {})
|
||||||
|
|
||||||
|
@ -111,11 +117,6 @@ module Devise
|
||||||
self.path_prefix.count("/")
|
self.path_prefix.count("/")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the raw path using path_prefix and as.
|
|
||||||
def full_path
|
|
||||||
path_prefix + path.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def authenticatable?
|
def authenticatable?
|
||||||
@authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
|
@authenticatable ||= self.modules.any? { |m| m.to_s =~ /authenticatable/ }
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,9 +15,10 @@ module ActionDispatch::Routing
|
||||||
# generate all needed routes for devise, based on what modules you have
|
# generate all needed routes for devise, based on what modules you have
|
||||||
# defined in your model.
|
# defined in your model.
|
||||||
#
|
#
|
||||||
# Examples: Let's say you have an User model configured to use
|
# ==== Examples
|
||||||
# authenticatable, confirmable and recoverable modules. After creating this
|
#
|
||||||
# inside your routes:
|
# Let's say you have an User model configured to use authenticatable,
|
||||||
|
# confirmable and recoverable modules. After creating this inside your routes:
|
||||||
#
|
#
|
||||||
# devise_for :users
|
# devise_for :users
|
||||||
#
|
#
|
||||||
|
@ -25,20 +26,22 @@ module ActionDispatch::Routing
|
||||||
# needed routes:
|
# needed routes:
|
||||||
#
|
#
|
||||||
# # Session routes for Authenticatable (default)
|
# # Session routes for Authenticatable (default)
|
||||||
# new_user_session GET /users/sign_in {:controller=>"sessions", :action=>"new"}
|
# new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
|
||||||
# user_session POST /users/sign_in {:controller=>"sessions", :action=>"create"}
|
# user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
|
||||||
# destroy_user_session GET /users/sign_out {:controller=>"sessions", :action=>"destroy"}
|
# destroy_user_session GET /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
|
||||||
#
|
#
|
||||||
# # Password routes for Recoverable, if User model has :recoverable configured
|
# # Password routes for Recoverable, if User model has :recoverable configured
|
||||||
# new_user_password GET /users/password/new(.:format) {:controller=>"passwords", :action=>"new"}
|
# new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
|
||||||
# edit_user_password GET /users/password/edit(.:format) {:controller=>"passwords", :action=>"edit"}
|
# edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
|
||||||
# user_password PUT /users/password(.:format) {:controller=>"passwords", :action=>"update"}
|
# user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
|
||||||
# POST /users/password(.:format) {:controller=>"passwords", :action=>"create"}
|
# POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
|
||||||
#
|
#
|
||||||
# # Confirmation routes for Confirmable, if User model has :confirmable configured
|
# # Confirmation routes for Confirmable, if User model has :confirmable configured
|
||||||
# new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"confirmations", :action=>"new"}
|
# new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
|
||||||
# user_confirmation GET /users/confirmation(.:format) {:controller=>"confirmations", :action=>"show"}
|
# user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
|
||||||
# POST /users/confirmation(.:format) {:controller=>"confirmations", :action=>"create"}
|
# POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
|
||||||
|
#
|
||||||
|
# ==== Options
|
||||||
#
|
#
|
||||||
# You can configure your routes with some options:
|
# You can configure your routes with some options:
|
||||||
#
|
#
|
||||||
|
@ -62,19 +65,6 @@ module ActionDispatch::Routing
|
||||||
#
|
#
|
||||||
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
|
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
|
||||||
#
|
#
|
||||||
# * :path_prefix => the path prefix to be used in all routes.
|
|
||||||
#
|
|
||||||
# devise_for :users, :path_prefix => "/:locale"
|
|
||||||
#
|
|
||||||
# If you are using a dynamic prefix, like :locale above, you need to configure default_url_options in your ApplicationController
|
|
||||||
# class level, so Devise can pick it:
|
|
||||||
#
|
|
||||||
# class ApplicationController < ActionController::Base
|
|
||||||
# def self.default_url_options
|
|
||||||
# { :locale => I18n.locale }
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# * :controllers => the controller which should be used. All routes by default points to Devise controllers.
|
# * :controllers => the controller which should be used. All routes by default points to Devise controllers.
|
||||||
# However, if you want them to point to custom controller, you should do:
|
# However, if you want them to point to custom controller, you should do:
|
||||||
#
|
#
|
||||||
|
@ -84,8 +74,46 @@ module ActionDispatch::Routing
|
||||||
#
|
#
|
||||||
# devise_for :users, :skip => :sessions
|
# devise_for :users, :skip => :sessions
|
||||||
#
|
#
|
||||||
|
# ==== Scoping
|
||||||
|
#
|
||||||
|
# Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:
|
||||||
|
#
|
||||||
|
# scope "/my" do
|
||||||
|
# devise_for :users
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# However, since Devise uses the request path to retrieve the current user, this has a few caveats.
|
||||||
|
# First, if you are using a dynamic segment, as below:
|
||||||
|
#
|
||||||
|
# scope ":locale" do
|
||||||
|
# devise_for :users
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# You are required to configure default_url_options in your ApplicationController class level, so
|
||||||
|
# Devise can pick it:
|
||||||
|
#
|
||||||
|
# class ApplicationController < ActionController::Base
|
||||||
|
# def self.default_url_options
|
||||||
|
# { :locale => I18n.locale }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Finally, Devise does not (and cannot) support optional segments, either static or dynamic. That
|
||||||
|
# said, the following does not work:
|
||||||
|
#
|
||||||
|
# scope "(/:locale)" do
|
||||||
|
# devise_for :users
|
||||||
|
# end
|
||||||
|
#
|
||||||
def devise_for(*resources)
|
def devise_for(*resources)
|
||||||
options = resources.extract_options!
|
options = resources.extract_options!
|
||||||
|
|
||||||
|
if options.key?(:path_prefix)
|
||||||
|
ActiveSupport::Deprecation.warn "Giving :path_prefix to devise_for is deprecated and has no effect. " <<
|
||||||
|
"Please use scope from the new router DSL instead."
|
||||||
|
end
|
||||||
|
|
||||||
|
options[:path_prefix] = @scope[:path]
|
||||||
resources.map!(&:to_sym)
|
resources.map!(&:to_sym)
|
||||||
|
|
||||||
resources.each do |resource|
|
resources.each do |resource|
|
||||||
|
@ -106,12 +134,18 @@ module ActionDispatch::Routing
|
||||||
routes = mapping.routes
|
routes = mapping.routes
|
||||||
routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
|
routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
|
||||||
|
|
||||||
routes.each do |mod|
|
scope mapping.path.to_s, :as => mapping.name do
|
||||||
send(:"devise_#{mod}", mapping, mapping.controllers)
|
routes.each { |mod| send(:"devise_#{mod}", mapping, mapping.controllers) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Allow you to add authentication request from the router:
|
||||||
|
#
|
||||||
|
# authenticate(:user) do
|
||||||
|
# resources :post
|
||||||
|
# end
|
||||||
|
#
|
||||||
def authenticate(scope)
|
def authenticate(scope)
|
||||||
constraint = lambda do |request|
|
constraint = lambda do |request|
|
||||||
request.env["warden"].authenticate!(:scope => scope)
|
request.env["warden"].authenticate!(:scope => scope)
|
||||||
|
@ -125,36 +159,31 @@ module ActionDispatch::Routing
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def devise_session(mapping, controllers)
|
def devise_session(mapping, controllers)
|
||||||
scope mapping.full_path do
|
scope :controller => controllers[:sessions], :as => :session do
|
||||||
get mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#new", :as => :"new_#{mapping.name}_session"
|
get :new, :path => mapping.path_names[:sign_in]
|
||||||
post mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#create", :as => :"#{mapping.name}_session"
|
post :create, :path => mapping.path_names[:sign_in], :as => ""
|
||||||
get mapping.path_names[:sign_out], :to => "#{controllers[:sessions]}#destroy", :as => :"destroy_#{mapping.name}_session"
|
get :destroy, :path => mapping.path_names[:sign_out]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def devise_password(mapping, controllers)
|
def devise_password(mapping, controllers)
|
||||||
scope mapping.full_path, :as => mapping.name do
|
resource :password, :only => [:new, :create, :edit, :update],
|
||||||
resource :password, :only => [:new, :create, :edit, :update], :path => mapping.path_names[:password], :controller => controllers[:passwords]
|
:path => mapping.path_names[:password], :controller => controllers[:passwords]
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def devise_confirmation(mapping, controllers)
|
def devise_confirmation(mapping, controllers)
|
||||||
scope mapping.full_path, :as => mapping.name do
|
resource :confirmation, :only => [:new, :create, :show],
|
||||||
resource :confirmation, :only => [:new, :create, :show], :path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
|
:path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def devise_unlock(mapping, controllers)
|
def devise_unlock(mapping, controllers)
|
||||||
scope mapping.full_path, :as => mapping.name do
|
resource :unlock, :only => [:new, :create, :show],
|
||||||
resource :unlock, :only => [:new, :create, :show], :path => mapping.path_names[:unlock], :controller => controllers[:unlocks]
|
:path => mapping.path_names[:unlock], :controller => controllers[:unlocks]
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def devise_registration(mapping, controllers)
|
def devise_registration(mapping, controllers)
|
||||||
scope mapping.full_path[1..-1], :as => mapping.name do
|
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
|
||||||
resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
|
:path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
|
||||||
:path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def raise_no_devise_method_error!(klass)
|
def raise_no_devise_method_error!(klass)
|
||||||
|
|
|
@ -97,11 +97,6 @@ class MappingTest < ActiveSupport::TestCase
|
||||||
assert_equal 2, Devise.mappings[:manager].segment_position
|
assert_equal 2, Devise.mappings[:manager].segment_position
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'path is returned with path prefix and as' do
|
|
||||||
assert_equal '/users', Devise.mappings[:user].full_path
|
|
||||||
assert_equal '/:locale/accounts', Devise.mappings[:manager].full_path
|
|
||||||
end
|
|
||||||
|
|
||||||
test 'magic predicates' do
|
test 'magic predicates' do
|
||||||
mapping = Devise.mappings[:user]
|
mapping = Devise.mappings[:user]
|
||||||
assert mapping.authenticatable?
|
assert mapping.authenticatable?
|
||||||
|
|
|
@ -8,13 +8,16 @@ Rails::Application.routes.draw do
|
||||||
|
|
||||||
devise_for :users
|
devise_for :users
|
||||||
devise_for :admin, :path => "admin_area", :controllers => { :sessions => "sessions" }, :skip => :passwords
|
devise_for :admin, :path => "admin_area", :controllers => { :sessions => "sessions" }, :skip => :passwords
|
||||||
devise_for :accounts, :singular => "manager", :path_prefix => ":locale", :class_name => "User",
|
|
||||||
:path_names => {
|
scope ":locale" do
|
||||||
:sign_in => "login", :sign_out => "logout",
|
devise_for :accounts, :singular => "manager", :class_name => "User",
|
||||||
:password => "secret", :confirmation => "verification",
|
:path_names => {
|
||||||
:unlock => "unblock", :sign_up => "register",
|
:sign_in => "login", :sign_out => "logout",
|
||||||
:registration => "management"
|
:password => "secret", :confirmation => "verification",
|
||||||
}
|
:unlock => "unblock", :sign_up => "register",
|
||||||
|
:registration => "management"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
match "/admin_area/home", :to => "admins#index", :as => :admin_root
|
match "/admin_area/home", :to => "admins#index", :as => :admin_root
|
||||||
match "/sign_in", :to => "devise/sessions#new"
|
match "/sign_in", :to => "devise/sessions#new"
|
||||||
|
|
Loading…
Reference in a new issue