devise 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +10 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.rdoc +94 -0
- data/Gemfile +24 -13
- data/Gemfile.lock +119 -75
- data/MIT-LICENSE +1 -1
- data/README.rdoc +144 -101
- data/Rakefile +3 -24
- data/app/controllers/devise/confirmations_controller.rb +1 -1
- data/app/controllers/devise/omniauth_callbacks_controller.rb +26 -0
- data/app/controllers/devise/passwords_controller.rb +1 -1
- data/app/controllers/devise/registrations_controller.rb +60 -7
- data/app/controllers/devise/sessions_controller.rb +6 -4
- data/app/controllers/devise/unlocks_controller.rb +1 -1
- data/app/helpers/devise_helper.rb +10 -2
- data/app/mailers/devise/mailer.rb +27 -10
- data/app/views/devise/confirmations/new.html.erb +1 -1
- data/app/views/devise/passwords/edit.html.erb +2 -2
- data/app/views/devise/passwords/new.html.erb +1 -1
- data/app/views/devise/registrations/edit.html.erb +1 -1
- data/app/views/devise/registrations/new.html.erb +1 -1
- data/app/views/devise/sessions/new.html.erb +1 -1
- data/app/views/devise/shared/_links.erb +6 -0
- data/app/views/devise/unlocks/new.html.erb +1 -1
- data/config/locales/en.yml +11 -2
- data/devise.gemspec +25 -0
- data/lib/devise/controllers/helpers.rb +119 -116
- data/lib/devise/controllers/internal_helpers.rb +29 -8
- data/lib/devise/controllers/rememberable.rb +52 -0
- data/lib/devise/controllers/scoped_views.rb +4 -6
- data/lib/devise/controllers/url_helpers.rb +3 -5
- data/lib/devise/encryptors/authlogic_sha512.rb +1 -1
- data/lib/devise/encryptors/base.rb +1 -1
- data/lib/devise/encryptors/restful_authentication_sha1.rb +4 -4
- data/lib/devise/failure_app.rb +46 -10
- data/lib/devise/hooks/activatable.rb +2 -2
- data/lib/devise/hooks/forgetable.rb +1 -3
- data/lib/devise/hooks/rememberable.rb +5 -42
- data/lib/devise/hooks/timeoutable.rb +1 -1
- data/lib/devise/mapping.rb +18 -7
- data/lib/devise/models/authenticatable.rb +73 -31
- data/lib/devise/models/confirmable.rb +16 -20
- data/lib/devise/models/database_authenticatable.rb +27 -37
- data/lib/devise/models/encryptable.rb +72 -0
- data/lib/devise/models/lockable.rb +27 -21
- data/lib/devise/models/omniauthable.rb +23 -0
- data/lib/devise/models/recoverable.rb +13 -3
- data/lib/devise/models/registerable.rb +13 -0
- data/lib/devise/models/rememberable.rb +39 -34
- data/lib/devise/models/timeoutable.rb +20 -3
- data/lib/devise/models/token_authenticatable.rb +22 -10
- data/lib/devise/models/validatable.rb +16 -4
- data/lib/devise/models.rb +4 -16
- data/lib/devise/modules.rb +15 -8
- data/lib/devise/omniauth/config.rb +18 -0
- data/lib/devise/omniauth/url_helpers.rb +33 -0
- data/lib/devise/omniauth.rb +32 -0
- data/lib/devise/orm/active_record.rb +2 -0
- data/lib/devise/orm/mongoid.rb +4 -2
- data/lib/devise/rails/routes.rb +67 -20
- data/lib/devise/rails/warden_compat.rb +101 -15
- data/lib/devise/rails.rb +33 -44
- data/lib/devise/schema.rb +16 -16
- data/lib/devise/strategies/authenticatable.rb +48 -7
- data/lib/devise/strategies/database_authenticatable.rb +1 -1
- data/lib/devise/strategies/rememberable.rb +6 -5
- data/lib/devise/strategies/token_authenticatable.rb +6 -2
- data/lib/devise/test_helpers.rb +13 -3
- data/lib/devise/version.rb +1 -1
- data/lib/devise.rb +162 -50
- data/lib/generators/active_record/devise_generator.rb +2 -2
- data/lib/generators/active_record/templates/migration.rb +2 -0
- data/lib/generators/devise/devise_generator.rb +3 -1
- data/lib/generators/devise/orm_helpers.rb +1 -1
- data/lib/generators/devise/views_generator.rb +8 -45
- data/lib/generators/mongoid/devise_generator.rb +2 -2
- data/lib/generators/templates/devise.rb +82 -39
- data/test/controllers/helpers_test.rb +78 -72
- data/test/controllers/internal_helpers_test.rb +29 -8
- data/test/controllers/url_helpers_test.rb +2 -1
- data/test/devise_test.rb +10 -0
- data/test/failure_app_test.rb +86 -22
- data/test/generators/active_record_generator_test.rb +24 -0
- data/test/generators/devise_generator_test.rb +33 -0
- data/test/generators/install_generator_test.rb +13 -0
- data/test/generators/mongoid_generator_test.rb +22 -0
- data/test/generators/views_generator_test.rb +35 -0
- data/test/indifferent_hash.rb +33 -0
- data/test/integration/authenticatable_test.rb +165 -62
- data/test/integration/database_authenticatable_test.rb +22 -0
- data/test/integration/http_authenticatable_test.rb +12 -2
- data/test/integration/omniauthable_test.rb +138 -0
- data/test/integration/recoverable_test.rb +39 -20
- data/test/integration/registerable_test.rb +60 -4
- data/test/integration/rememberable_test.rb +72 -29
- data/test/integration/timeoutable_test.rb +10 -1
- data/test/integration/token_authenticatable_test.rb +55 -6
- data/test/mailers/confirmation_instructions_test.rb +4 -0
- data/test/mailers/reset_password_instructions_test.rb +4 -0
- data/test/mailers/unlock_instructions_test.rb +4 -0
- data/test/mapping_test.rb +37 -3
- data/test/models/confirmable_test.rb +32 -15
- data/test/models/database_authenticatable_test.rb +14 -71
- data/test/models/encryptable_test.rb +65 -0
- data/test/models/lockable_test.rb +48 -11
- data/test/models/recoverable_test.rb +28 -2
- data/test/models/rememberable_test.rb +186 -125
- data/test/models/token_authenticatable_test.rb +19 -1
- data/test/models_test.rb +12 -5
- data/test/omniauth/url_helpers_test.rb +54 -0
- data/test/orm/mongoid.rb +3 -2
- data/test/rails_app/Rakefile +10 -0
- data/test/rails_app/app/active_record/admin.rb +4 -1
- data/test/rails_app/app/active_record/user.rb +5 -4
- data/test/rails_app/app/controllers/{sessions_controller.rb → admins/sessions_controller.rb} +1 -1
- data/test/rails_app/app/controllers/application_controller.rb +0 -1
- data/test/rails_app/app/controllers/home_controller.rb +9 -0
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +14 -0
- data/test/rails_app/app/mongoid/admin.rb +4 -1
- data/test/rails_app/app/mongoid/shim.rb +16 -3
- data/test/rails_app/app/mongoid/user.rb +5 -5
- data/test/rails_app/app/views/admins/index.html.erb +1 -0
- data/test/rails_app/app/views/admins/sessions/new.html.erb +2 -0
- data/test/rails_app/app/views/home/index.html.erb +1 -0
- data/test/rails_app/app/views/home/private.html.erb +1 -0
- data/test/rails_app/app/views/layouts/application.html.erb +24 -0
- data/test/rails_app/app/views/users/index.html.erb +1 -0
- data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +1 -0
- data/test/rails_app/app/views/users/sessions/new.html.erb +1 -0
- data/test/rails_app/config/application.rb +5 -0
- data/test/rails_app/config/boot.rb +2 -2
- data/test/rails_app/config/database.yml +18 -0
- data/test/rails_app/config/initializers/devise.rb +71 -31
- data/test/rails_app/config/routes.rb +14 -6
- data/test/rails_app/config.ru +4 -0
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +21 -17
- data/test/rails_app/db/schema.rb +17 -51
- data/test/rails_app/lib/shared_admin.rb +9 -0
- data/test/rails_app/lib/shared_user.rb +23 -0
- data/test/rails_app/public/404.html +26 -0
- data/test/rails_app/public/422.html +26 -0
- data/test/rails_app/public/500.html +26 -0
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/rails_app/script/rails +10 -0
- data/test/routes_test.rb +42 -9
- data/test/schema_test.rb +33 -0
- data/test/support/integration.rb +4 -4
- data/test/support/locale/en.yml +4 -0
- data/test/support/webrat/integrations/rails.rb +11 -19
- data/test/test_helper.rb +8 -2
- data/test/test_helpers_test.rb +64 -2
- metadata +106 -30
- data/TODO +0 -3
- data/lib/devise/encryptors/bcrypt.rb +0 -19
- data/lib/generators/devise_install_generator.rb +0 -4
- data/lib/generators/devise_views_generator.rb +0 -4
- data/test/support/test_silencer.rb +0 -5
|
@@ -17,17 +17,15 @@ module Devise
|
|
|
17
17
|
|
|
18
18
|
# Render a view for the specified scope. Turned off by default.
|
|
19
19
|
# Accepts just :controller as option.
|
|
20
|
-
def render_with_scope(action,
|
|
21
|
-
controller_name = options.delete(:controller) || self.controller_name
|
|
22
|
-
|
|
20
|
+
def render_with_scope(action, path=self.controller_path)
|
|
23
21
|
if self.class.scoped_views?
|
|
24
22
|
begin
|
|
25
|
-
render :template => "#{devise_mapping.
|
|
23
|
+
render :template => "#{devise_mapping.scoped_path}/#{path.split("/").last}/#{action}"
|
|
26
24
|
rescue ActionView::MissingTemplate
|
|
27
|
-
render :template => "#{
|
|
25
|
+
render :template => "#{path}/#{action}"
|
|
28
26
|
end
|
|
29
27
|
else
|
|
30
|
-
render :template => "#{
|
|
28
|
+
render :template => "#{path}/#{action}"
|
|
31
29
|
end
|
|
32
30
|
end
|
|
33
31
|
end
|
|
@@ -19,13 +19,11 @@ module Devise
|
|
|
19
19
|
# Those helpers are added to your ApplicationController.
|
|
20
20
|
module UrlHelpers
|
|
21
21
|
|
|
22
|
-
Devise::
|
|
22
|
+
Devise::URL_HELPERS.each do |module_name, actions|
|
|
23
23
|
[:path, :url].each do |path_or_url|
|
|
24
|
-
actions = [ nil, :new_ ]
|
|
25
|
-
actions << :edit_ if [:password, :registration].include?(module_name)
|
|
26
|
-
actions << :destroy_ if [:session].include?(module_name)
|
|
27
|
-
|
|
28
24
|
actions.each do |action|
|
|
25
|
+
action = action ? "#{action}_" : ""
|
|
26
|
+
|
|
29
27
|
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
|
30
28
|
def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args)
|
|
31
29
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
@@ -4,7 +4,7 @@ module Devise
|
|
|
4
4
|
module Encryptors
|
|
5
5
|
# = AuthlogicSha512
|
|
6
6
|
# Simulates Authlogic's default encryption mechanism.
|
|
7
|
-
# Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to
|
|
7
|
+
# Warning: it uses Devise's stretches configuration to port Authlogic's one. Should be set to 20 in the initializer to simulate
|
|
8
8
|
# the default behavior.
|
|
9
9
|
class AuthlogicSha512 < Base
|
|
10
10
|
# Gererates a default password digest based on salt, pepper and the
|
|
@@ -5,10 +5,10 @@ module Devise
|
|
|
5
5
|
# = RestfulAuthenticationSha1
|
|
6
6
|
# Simulates Restful Authentication's default encryption mechanism.
|
|
7
7
|
# Warning: it uses Devise's pepper to port the concept of REST_AUTH_SITE_KEY
|
|
8
|
-
# Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
|
|
9
|
-
# the initializer to
|
|
8
|
+
# Warning: it uses Devise's stretches configuration to port the concept of REST_AUTH_DIGEST_STRETCHES. Should be set to 10 in
|
|
9
|
+
# the initializer to simulate the default behavior.
|
|
10
10
|
class RestfulAuthenticationSha1 < Base
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
# Gererates a default password digest based on salt, pepper and the
|
|
13
13
|
# incoming password.
|
|
14
14
|
def self.digest(password, stretches, salt, pepper)
|
|
@@ -19,4 +19,4 @@ module Devise
|
|
|
19
19
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
|
-
end
|
|
22
|
+
end
|
data/lib/devise/failure_app.rb
CHANGED
|
@@ -33,7 +33,7 @@ module Devise
|
|
|
33
33
|
|
|
34
34
|
def http_auth
|
|
35
35
|
self.status = 401
|
|
36
|
-
self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect})
|
|
36
|
+
self.headers["WWW-Authenticate"] = %(Basic realm=#{Devise.http_authentication_realm.inspect}) if http_auth_header?
|
|
37
37
|
self.content_type = request.format.to_s
|
|
38
38
|
self.response_body = http_auth_body
|
|
39
39
|
end
|
|
@@ -41,12 +41,12 @@ module Devise
|
|
|
41
41
|
def recall
|
|
42
42
|
env["PATH_INFO"] = attempted_path
|
|
43
43
|
flash.now[:alert] = i18n_message(:invalid)
|
|
44
|
-
self.response =
|
|
44
|
+
self.response = recall_app(warden_options[:recall]).call(env)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def redirect
|
|
48
48
|
store_location!
|
|
49
|
-
flash[:alert] = i18n_message
|
|
49
|
+
flash[:alert] = i18n_message
|
|
50
50
|
redirect_to redirect_url
|
|
51
51
|
end
|
|
52
52
|
|
|
@@ -64,20 +64,44 @@ module Devise
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def redirect_url
|
|
67
|
-
|
|
67
|
+
if request_format == :html
|
|
68
|
+
send(:"new_#{scope}_session_path")
|
|
69
|
+
else
|
|
70
|
+
send(:"new_#{scope}_session_path", :format => request_format)
|
|
71
|
+
end
|
|
68
72
|
end
|
|
69
73
|
|
|
74
|
+
# Choose whether we should respond in a http authentication fashion,
|
|
75
|
+
# including 401 and optional headers.
|
|
76
|
+
#
|
|
77
|
+
# This method allows the user to explicitly disable http authentication
|
|
78
|
+
# on ajax requests in case they want to redirect on failures instead of
|
|
79
|
+
# handling the errors on their own. This is useful in case your ajax API
|
|
80
|
+
# is the same as your public API and uses a format like JSON (so you
|
|
81
|
+
# cannot mark JSON as a navigational format).
|
|
70
82
|
def http_auth?
|
|
71
|
-
|
|
83
|
+
if request.xhr?
|
|
84
|
+
Devise.http_authenticatable_on_xhr
|
|
85
|
+
else
|
|
86
|
+
!(request_format && Devise.navigational_formats.include?(request_format))
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# It does not make sense to send authenticate headers in ajax requests
|
|
91
|
+
# or if the user disabled them.
|
|
92
|
+
def http_auth_header?
|
|
93
|
+
Devise.mappings[scope].to.http_authenticatable && !request.xhr?
|
|
72
94
|
end
|
|
73
95
|
|
|
74
96
|
def http_auth_body
|
|
75
|
-
|
|
97
|
+
return i18n_message unless request_format
|
|
98
|
+
method = "to_#{request_format}"
|
|
76
99
|
{}.respond_to?(method) ? { :error => i18n_message }.send(method) : i18n_message
|
|
77
100
|
end
|
|
78
101
|
|
|
79
|
-
def
|
|
80
|
-
|
|
102
|
+
def recall_app(app)
|
|
103
|
+
controller, action = app.split("#")
|
|
104
|
+
"#{controller.camelize}Controller".constantize.action(action)
|
|
81
105
|
end
|
|
82
106
|
|
|
83
107
|
def warden
|
|
@@ -89,7 +113,7 @@ module Devise
|
|
|
89
113
|
end
|
|
90
114
|
|
|
91
115
|
def scope
|
|
92
|
-
@scope ||= warden_options[:scope]
|
|
116
|
+
@scope ||= warden_options[:scope] || Devise.default_scope
|
|
93
117
|
end
|
|
94
118
|
|
|
95
119
|
def attempted_path
|
|
@@ -101,7 +125,19 @@ module Devise
|
|
|
101
125
|
# yet, but we still need to store the uri based on scope, so different scopes
|
|
102
126
|
# would never use the same uri to redirect.
|
|
103
127
|
def store_location!
|
|
104
|
-
session[
|
|
128
|
+
session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
MIME_REFERENCES = Mime::HTML.respond_to?(:ref)
|
|
132
|
+
|
|
133
|
+
def request_format
|
|
134
|
+
@request_format ||= if request.format.respond_to?(:ref)
|
|
135
|
+
request.format.ref
|
|
136
|
+
elsif MIME_REFERENCES
|
|
137
|
+
request.format
|
|
138
|
+
else # Rails < 3.0.4
|
|
139
|
+
request.format.to_sym
|
|
140
|
+
end
|
|
105
141
|
end
|
|
106
142
|
end
|
|
107
143
|
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Deny user access whenever his account is not active yet. All strategies that inherits from
|
|
2
|
-
# Devise::Strategies::Authenticatable and uses the validate already check if the user is
|
|
2
|
+
# Devise::Strategies::Authenticatable and uses the validate already check if the user is active_for_authentication?
|
|
3
3
|
# before actively signing him in. However, we need this as hook to validate the user activity
|
|
4
4
|
# in each request and in case the user is using other strategies beside Devise ones.
|
|
5
5
|
Warden::Manager.after_set_user do |record, warden, options|
|
|
6
|
-
if record && record.respond_to?(:
|
|
6
|
+
if record && record.respond_to?(:active_for_authentication?) && !record.active_for_authentication?
|
|
7
7
|
scope = options[:scope]
|
|
8
8
|
warden.logout(scope)
|
|
9
9
|
throw :warden, :scope => scope, :message => record.inactive_message
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
# This avoids forgetting deleted users.
|
|
5
5
|
Warden::Manager.before_logout do |record, warden, options|
|
|
6
6
|
if record.respond_to?(:forget_me!)
|
|
7
|
-
|
|
8
|
-
cookie_options = record.cookie_domain? ? { :domain => record.cookie_domain } : {}
|
|
9
|
-
warden.cookies.delete("remember_#{options[:scope]}_token", cookie_options)
|
|
7
|
+
Devise::Controllers::Rememberable::Proxy.new(warden).forget_me(record)
|
|
10
8
|
end
|
|
11
9
|
end
|
|
@@ -1,43 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
# strategy (like token authenticatable or facebook authenticatable) to turn off remember_me?
|
|
6
|
-
# cookies.
|
|
7
|
-
module Rememberable #:nodoc:
|
|
8
|
-
def success!(resource)
|
|
9
|
-
super
|
|
10
|
-
|
|
11
|
-
if succeeded? && resource.respond_to?(:remember_me!) && remember_me?
|
|
12
|
-
resource.remember_me!(extend_remember_period?)
|
|
13
|
-
|
|
14
|
-
configuration = {
|
|
15
|
-
:value => resource.class.serialize_into_cookie(resource),
|
|
16
|
-
:expires => resource.remember_expires_at,
|
|
17
|
-
:path => "/"
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
configuration[:domain] = resource.cookie_domain if resource.cookie_domain?
|
|
21
|
-
cookies.signed["remember_#{scope}_token"] = configuration
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
protected
|
|
26
|
-
|
|
27
|
-
def succeeded?
|
|
28
|
-
@result == :success
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def extend_remember_period?
|
|
32
|
-
false
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def remember_me?
|
|
36
|
-
valid_params? && Devise::TRUE_VALUES.include?(params_auth_hash[:remember_me])
|
|
37
|
-
end
|
|
38
|
-
end
|
|
1
|
+
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
|
2
|
+
scope = options[:scope]
|
|
3
|
+
if record.respond_to?(:remember_me) && record.remember_me && warden.authenticated?(scope)
|
|
4
|
+
Devise::Controllers::Rememberable::Proxy.new(warden).remember_me(record)
|
|
39
5
|
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
Devise::Strategies::Authenticatable.send :include, Devise::Hooks::Rememberable
|
|
43
|
-
|
|
6
|
+
end
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
Warden::Manager.after_set_user do |record, warden, options|
|
|
7
7
|
scope = options[:scope]
|
|
8
8
|
|
|
9
|
-
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope)
|
|
9
|
+
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
|
|
10
10
|
last_request_at = warden.session(scope)['last_request_at']
|
|
11
11
|
|
|
12
12
|
if record.timedout?(last_request_at)
|
data/lib/devise/mapping.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Devise
|
|
|
22
22
|
# # is the modules included in the class
|
|
23
23
|
#
|
|
24
24
|
class Mapping #:nodoc:
|
|
25
|
-
attr_reader :singular, :
|
|
25
|
+
attr_reader :singular, :scoped_path, :path, :controllers, :path_names, :class_name, :sign_out_via
|
|
26
26
|
alias :name :singular
|
|
27
27
|
|
|
28
28
|
# Receives an object and find a scope for it. If a scope cannot be found,
|
|
@@ -37,15 +37,20 @@ module Devise
|
|
|
37
37
|
Devise.mappings.each_value { |m| return m.name if duck.is_a?(m.to) }
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
raise "Could not find a valid mapping for #{duck}"
|
|
40
|
+
raise "Could not find a valid mapping for #{duck.inspect}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.find_by_path!(path, path_type=:fullpath)
|
|
44
|
+
Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
|
|
45
|
+
raise "Could not find a valid mapping for path #{path.inspect}"
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
def initialize(name, options) #:nodoc:
|
|
44
|
-
@
|
|
45
|
-
@singular = (options[:singular] || @
|
|
49
|
+
@scoped_path = options[:as] ? "#{options[:as]}/#{name}" : name.to_s
|
|
50
|
+
@singular = (options[:singular] || @scoped_path.tr('/', '_').singularize).to_sym
|
|
46
51
|
|
|
47
52
|
@class_name = (options[:class_name] || name.to_s.classify).to_s
|
|
48
|
-
@ref =
|
|
53
|
+
@ref = Devise.ref(@class_name)
|
|
49
54
|
|
|
50
55
|
@path = (options[:path] || name).to_s
|
|
51
56
|
@path_prefix = options[:path_prefix]
|
|
@@ -57,6 +62,8 @@ module Devise
|
|
|
57
62
|
@path_names = Hash.new { |h,k| h[k] = k.to_s }
|
|
58
63
|
@path_names.merge!(:registration => "")
|
|
59
64
|
@path_names.merge!(options[:path_names] || {})
|
|
65
|
+
|
|
66
|
+
@sign_out_via = options[:sign_out_via] || Devise.sign_out_via
|
|
60
67
|
end
|
|
61
68
|
|
|
62
69
|
# Return modules for the mapping.
|
|
@@ -66,7 +73,11 @@ module Devise
|
|
|
66
73
|
|
|
67
74
|
# Gives the class the mapping points to.
|
|
68
75
|
def to
|
|
69
|
-
|
|
76
|
+
if defined?(ActiveSupport::Dependencies::ClassCache)
|
|
77
|
+
@ref.get @class_name
|
|
78
|
+
else
|
|
79
|
+
@ref.get
|
|
80
|
+
end
|
|
70
81
|
end
|
|
71
82
|
|
|
72
83
|
def strategies
|
|
@@ -82,7 +93,7 @@ module Devise
|
|
|
82
93
|
end
|
|
83
94
|
|
|
84
95
|
def fullpath
|
|
85
|
-
"
|
|
96
|
+
"/#{@path_prefix}/#{@path}".squeeze("/")
|
|
86
97
|
end
|
|
87
98
|
|
|
88
99
|
# Create magic predicates for verifying what module is activated by this map.
|
|
@@ -2,34 +2,41 @@ require 'devise/hooks/activatable'
|
|
|
2
2
|
|
|
3
3
|
module Devise
|
|
4
4
|
module Models
|
|
5
|
-
#
|
|
5
|
+
# Authenticatable module. Holds common settings for authentication.
|
|
6
6
|
#
|
|
7
|
-
# ==
|
|
7
|
+
# == Options
|
|
8
8
|
#
|
|
9
|
-
#
|
|
10
|
-
# using devise method or overwriting the respective instance method.
|
|
9
|
+
# Authenticatable adds the following options to devise_for:
|
|
11
10
|
#
|
|
12
|
-
# authentication_keys
|
|
11
|
+
# * +authentication_keys+: parameters used for authentication. By default [:email].
|
|
13
12
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
13
|
+
# * +request_keys+: parameters from the request object used for authentication.
|
|
14
|
+
# By specifying a symbol (which should be a request method), it will automatically be
|
|
15
|
+
# passed to find_for_authentication method and considered in your model lookup.
|
|
16
16
|
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
17
|
+
# For instance, if you set :request_keys to [:subdomain], :subdomain will be considered
|
|
18
|
+
# as key on authentication. This can also be a hash where the value is a boolean expliciting
|
|
19
|
+
# if the value is required or not.
|
|
19
20
|
#
|
|
20
|
-
#
|
|
21
|
+
# * +http_authenticatable+: if this model allows http authentication. By default true.
|
|
22
|
+
# It also accepts an array specifying the strategies that should allow http.
|
|
21
23
|
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
24
|
+
# * +params_authenticatable+: if this model allows authentication through request params. By default true.
|
|
25
|
+
# It also accepts an array specifying the strategies that should allow params authentication.
|
|
26
|
+
#
|
|
27
|
+
# == active_for_authentication?
|
|
28
|
+
#
|
|
29
|
+
# Before authenticating a user and in each request, Devise checks if your model is active by
|
|
30
|
+
# calling model.active_for_authentication?. This method is overwriten by other devise modules. For instance,
|
|
31
|
+
# :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
|
|
25
32
|
#
|
|
26
33
|
# You overwrite this method yourself, but if you do, don't forget to call super:
|
|
27
34
|
#
|
|
28
|
-
# def
|
|
35
|
+
# def active_for_authentication?
|
|
29
36
|
# super && special_condition_is_valid?
|
|
30
37
|
# end
|
|
31
38
|
#
|
|
32
|
-
# Whenever
|
|
39
|
+
# Whenever active_for_authentication? returns false, Devise asks the reason why your model is inactive using
|
|
33
40
|
# the inactive_message method. You can overwrite it as well:
|
|
34
41
|
#
|
|
35
42
|
# def inactive_message
|
|
@@ -48,10 +55,10 @@ module Devise
|
|
|
48
55
|
# find_for_authentication are the methods used in a Warden::Strategy to check
|
|
49
56
|
# if a model should be signed in or not.
|
|
50
57
|
#
|
|
51
|
-
# However, you should not overwrite this method, you should overwrite
|
|
52
|
-
# inactive_message instead.
|
|
58
|
+
# However, you should not overwrite this method, you should overwrite active_for_authentication?
|
|
59
|
+
# and inactive_message instead.
|
|
53
60
|
def valid_for_authentication?
|
|
54
|
-
if
|
|
61
|
+
if active_for_authentication?
|
|
55
62
|
block_given? ? yield : true
|
|
56
63
|
else
|
|
57
64
|
inactive_message
|
|
@@ -59,15 +66,30 @@ module Devise
|
|
|
59
66
|
end
|
|
60
67
|
|
|
61
68
|
def active?
|
|
62
|
-
|
|
69
|
+
ActiveSupport::Deprecation.warn "[DEVISE] active? is deprecated, please use active_for_authentication? instead.", caller
|
|
70
|
+
active_for_authentication?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def active_for_authentication?
|
|
74
|
+
my_methods = self.class.instance_methods(false)
|
|
75
|
+
if my_methods.include?("active?") || my_methods.include?(:active?)
|
|
76
|
+
ActiveSupport::Deprecation.warn "[DEVISE] Overriding active? is deprecated to avoid conflicts. " \
|
|
77
|
+
"Please use active_for_authentication? instead.", caller
|
|
78
|
+
active?
|
|
79
|
+
else
|
|
80
|
+
true
|
|
81
|
+
end
|
|
63
82
|
end
|
|
64
83
|
|
|
65
84
|
def inactive_message
|
|
66
85
|
:inactive
|
|
67
86
|
end
|
|
68
87
|
|
|
88
|
+
def authenticatable_salt
|
|
89
|
+
end
|
|
90
|
+
|
|
69
91
|
module ClassMethods
|
|
70
|
-
Devise::Models.config(self, :authentication_keys, :http_authenticatable, :params_authenticatable)
|
|
92
|
+
Devise::Models.config(self, :authentication_keys, :request_keys, :case_insensitive_keys, :http_authenticatable, :params_authenticatable)
|
|
71
93
|
|
|
72
94
|
def params_authenticatable?(strategy)
|
|
73
95
|
params_authenticatable.is_a?(Array) ?
|
|
@@ -90,34 +112,54 @@ module Devise
|
|
|
90
112
|
# end
|
|
91
113
|
#
|
|
92
114
|
def find_for_authentication(conditions)
|
|
93
|
-
|
|
115
|
+
filter_auth_params(conditions)
|
|
116
|
+
(case_insensitive_keys || []).each { |k| conditions[k].try(:downcase!) }
|
|
117
|
+
to_adapter.find_first(conditions)
|
|
94
118
|
end
|
|
95
119
|
|
|
96
120
|
# Find an initialize a record setting an error if it can't be found.
|
|
97
121
|
def find_or_initialize_with_error_by(attribute, value, error=:invalid) #:nodoc:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
record = find(:first, :conditions => conditions)
|
|
101
|
-
end
|
|
122
|
+
find_or_initialize_with_errors([attribute], { attribute => value }, error)
|
|
123
|
+
end
|
|
102
124
|
|
|
125
|
+
# Find an initialize a group of attributes based on a list of required attributes.
|
|
126
|
+
def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
|
|
127
|
+
(case_insensitive_keys || []).each { |k| attributes[k].try(:downcase!) }
|
|
128
|
+
|
|
129
|
+
attributes = attributes.slice(*required_attributes)
|
|
130
|
+
attributes.delete_if { |key, value| value.blank? }
|
|
131
|
+
|
|
132
|
+
if attributes.size == required_attributes.size
|
|
133
|
+
record = to_adapter.find_first(filter_auth_params(attributes))
|
|
134
|
+
end
|
|
135
|
+
|
|
103
136
|
unless record
|
|
104
137
|
record = new
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
138
|
+
|
|
139
|
+
required_attributes.each do |key|
|
|
140
|
+
value = attributes[key]
|
|
141
|
+
record.send("#{key}=", value)
|
|
142
|
+
record.errors.add(key, value.present? ? error : :blank)
|
|
109
143
|
end
|
|
110
|
-
record.errors.add(attribute, error)
|
|
111
144
|
end
|
|
112
145
|
|
|
113
146
|
record
|
|
114
147
|
end
|
|
115
148
|
|
|
149
|
+
protected
|
|
150
|
+
|
|
151
|
+
# Force keys to be string to avoid injection on mongoid related database.
|
|
152
|
+
def filter_auth_params(conditions)
|
|
153
|
+
conditions.each do |k, v|
|
|
154
|
+
conditions[k] = v.to_s
|
|
155
|
+
end if conditions.is_a?(Hash)
|
|
156
|
+
end
|
|
157
|
+
|
|
116
158
|
# Generate a token by looping and ensuring does not already exist.
|
|
117
159
|
def generate_token(column)
|
|
118
160
|
loop do
|
|
119
161
|
token = Devise.friendly_token
|
|
120
|
-
break token unless
|
|
162
|
+
break token unless to_adapter.find_first({ column => token })
|
|
121
163
|
end
|
|
122
164
|
end
|
|
123
165
|
end
|
|
@@ -3,28 +3,24 @@ module Devise
|
|
|
3
3
|
# Confirmable is responsible to verify if an account is already confirmed to
|
|
4
4
|
# sign in, and to send emails with confirmation instructions.
|
|
5
5
|
# Confirmation instructions are sent to the user email after creating a
|
|
6
|
-
# record
|
|
7
|
-
# a new confirmation instruction request.
|
|
8
|
-
# Whenever the user update it's email, his account is automatically unconfirmed,
|
|
9
|
-
# it means it won't be able to sign in again without confirming the account
|
|
10
|
-
# again through the email that was sent.
|
|
6
|
+
# record and when manually requested by a new confirmation instruction request.
|
|
11
7
|
#
|
|
12
|
-
#
|
|
8
|
+
# == Options
|
|
13
9
|
#
|
|
14
|
-
#
|
|
15
|
-
# without blocking his access. When confirm_within is zero, the
|
|
16
|
-
# user won't be able to sign in without confirming. You can
|
|
17
|
-
# use this to let your user access some features of your
|
|
18
|
-
# application without confirming the account, but blocking it
|
|
19
|
-
# after a certain period (ie 7 days). By default confirm_within is
|
|
20
|
-
# zero, it means users always have to confirm to sign in.
|
|
10
|
+
# Confirmable adds the following options to devise_for:
|
|
21
11
|
#
|
|
22
|
-
#
|
|
12
|
+
# * +confirm_within+: the time you want to allow the user to access his account
|
|
13
|
+
# before confirming it. After this period, the user access is denied. You can
|
|
14
|
+
# use this to let your user access some features of your application without
|
|
15
|
+
# confirming the account, but blocking it after a certain period (ie 7 days).
|
|
16
|
+
# By default confirm_within is zero, it means users always have to confirm to sign in.
|
|
17
|
+
#
|
|
18
|
+
# == Examples
|
|
23
19
|
#
|
|
24
20
|
# User.find(1).confirm! # returns true unless it's already confirmed
|
|
25
21
|
# User.find(1).confirmed? # true/false
|
|
26
22
|
# User.find(1).send_confirmation_instructions # manually send instructions
|
|
27
|
-
#
|
|
23
|
+
#
|
|
28
24
|
module Confirmable
|
|
29
25
|
extend ActiveSupport::Concern
|
|
30
26
|
|
|
@@ -59,11 +55,11 @@ module Devise
|
|
|
59
55
|
unless_confirmed { send_confirmation_instructions }
|
|
60
56
|
end
|
|
61
57
|
|
|
62
|
-
# Overwrites
|
|
63
|
-
# by verifying whether
|
|
58
|
+
# Overwrites active_for_authentication? for confirmation
|
|
59
|
+
# by verifying whether a user is active to sign in or not. If the user
|
|
64
60
|
# is already confirmed, it should never be blocked. Otherwise we need to
|
|
65
61
|
# calculate if the confirm time has not expired for this user.
|
|
66
|
-
def
|
|
62
|
+
def active_for_authentication?
|
|
67
63
|
super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
|
|
68
64
|
end
|
|
69
65
|
|
|
@@ -137,7 +133,7 @@ module Devise
|
|
|
137
133
|
# with an email not found error.
|
|
138
134
|
# Options must contain the user email
|
|
139
135
|
def send_confirmation_instructions(attributes={})
|
|
140
|
-
confirmable =
|
|
136
|
+
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
|
|
141
137
|
confirmable.resend_confirmation_token if confirmable.persisted?
|
|
142
138
|
confirmable
|
|
143
139
|
end
|
|
@@ -157,7 +153,7 @@ module Devise
|
|
|
157
153
|
generate_token(:confirmation_token)
|
|
158
154
|
end
|
|
159
155
|
|
|
160
|
-
Devise::Models.config(self, :confirm_within)
|
|
156
|
+
Devise::Models.config(self, :confirm_within, :confirmation_keys)
|
|
161
157
|
end
|
|
162
158
|
end
|
|
163
159
|
end
|