devise 3.5.2 → 4.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +14 -15
- data/CHANGELOG.md +57 -1125
- data/CODE_OF_CONDUCT.md +22 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +80 -80
- data/MIT-LICENSE +1 -1
- data/README.md +27 -18
- data/app/controllers/devise/confirmations_controller.rb +1 -1
- data/app/controllers/devise/omniauth_callbacks_controller.rb +4 -4
- data/app/controllers/devise/passwords_controller.rb +5 -4
- data/app/controllers/devise/registrations_controller.rb +5 -5
- data/app/controllers/devise/sessions_controller.rb +7 -7
- data/app/controllers/devise/unlocks_controller.rb +2 -2
- data/app/controllers/devise_controller.rb +20 -9
- data/app/mailers/devise/mailer.rb +4 -0
- data/app/views/devise/confirmations/new.html.erb +1 -1
- data/app/views/devise/mailer/password_change.html.erb +3 -0
- data/app/views/devise/shared/_links.html.erb +1 -1
- data/bin/test +13 -0
- data/config/locales/en.yml +2 -0
- data/devise.gemspec +2 -3
- data/gemfiles/Gemfile.rails-4.1-stable +4 -4
- data/gemfiles/Gemfile.rails-4.1-stable.lock +69 -71
- data/gemfiles/Gemfile.rails-4.2-stable +4 -4
- data/gemfiles/Gemfile.rails-4.2-stable.lock +81 -83
- data/gemfiles/{Gemfile.rails-3.2-stable → Gemfile.rails-5.0-beta} +15 -7
- data/gemfiles/Gemfile.rails-5.0-beta.lock +199 -0
- data/lib/devise/controllers/helpers.rb +20 -24
- data/lib/devise/controllers/rememberable.rb +8 -1
- data/lib/devise/encryptor.rb +4 -4
- data/lib/devise/failure_app.rb +33 -12
- data/lib/devise/hooks/timeoutable.rb +5 -3
- data/lib/devise/mailers/helpers.rb +1 -1
- data/lib/devise/models/authenticatable.rb +5 -1
- data/lib/devise/models/confirmable.rb +6 -6
- data/lib/devise/models/database_authenticatable.rb +20 -7
- data/lib/devise/models/lockable.rb +1 -1
- data/lib/devise/models/recoverable.rb +3 -7
- data/lib/devise/models/rememberable.rb +38 -24
- data/lib/devise/models/timeoutable.rb +0 -6
- data/lib/devise/models.rb +1 -1
- data/lib/devise/omniauth/url_helpers.rb +62 -4
- data/lib/devise/parameter_sanitizer.rb +176 -61
- data/lib/devise/rails/routes.rb +54 -31
- data/lib/devise/rails/warden_compat.rb +1 -10
- data/lib/devise/rails.rb +1 -10
- data/lib/devise/strategies/authenticatable.rb +1 -1
- data/lib/devise/strategies/database_authenticatable.rb +3 -3
- data/lib/devise/strategies/rememberable.rb +3 -6
- data/lib/devise/test_helpers.rb +10 -5
- data/lib/devise/token_generator.rb +1 -41
- data/lib/devise/version.rb +1 -1
- data/lib/devise.rb +115 -20
- data/lib/generators/active_record/devise_generator.rb +11 -5
- data/lib/generators/active_record/templates/migration.rb +2 -2
- data/lib/generators/active_record/templates/migration_existing.rb +2 -2
- data/lib/generators/devise/install_generator.rb +15 -0
- data/lib/generators/devise/orm_helpers.rb +1 -18
- data/lib/generators/devise/views_generator.rb +14 -3
- data/lib/generators/templates/controllers/registrations_controller.rb +4 -4
- data/lib/generators/templates/controllers/sessions_controller.rb +2 -2
- data/lib/generators/templates/devise.rb +19 -17
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/password_change.markerb +3 -0
- data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
- data/test/controllers/custom_registrations_controller_test.rb +5 -5
- data/test/controllers/custom_strategy_test.rb +7 -5
- data/test/controllers/helper_methods_test.rb +22 -0
- data/test/controllers/helpers_test.rb +1 -1
- data/test/controllers/inherited_controller_i18n_messages_test.rb +2 -2
- data/test/controllers/internal_helpers_test.rb +8 -10
- data/test/controllers/load_hooks_controller_test.rb +1 -1
- data/test/controllers/passwords_controller_test.rb +4 -3
- data/test/controllers/sessions_controller_test.rb +21 -18
- data/test/controllers/url_helpers_test.rb +1 -1
- data/test/devise_test.rb +27 -0
- data/test/failure_app_test.rb +37 -15
- data/test/generators/active_record_generator_test.rb +0 -26
- data/test/generators/install_generator_test.rb +14 -3
- data/test/generators/views_generator_test.rb +7 -0
- data/test/helpers/devise_helper_test.rb +1 -1
- data/test/integration/authenticatable_test.rb +18 -18
- data/test/integration/confirmable_test.rb +5 -5
- data/test/integration/database_authenticatable_test.rb +1 -1
- data/test/integration/http_authenticatable_test.rb +4 -5
- data/test/integration/lockable_test.rb +4 -3
- data/test/integration/omniauthable_test.rb +12 -10
- data/test/integration/recoverable_test.rb +10 -10
- data/test/integration/registerable_test.rb +9 -11
- data/test/integration/rememberable_test.rb +42 -7
- data/test/integration/timeoutable_test.rb +16 -4
- data/test/integration/trackable_test.rb +1 -1
- data/test/mailers/confirmation_instructions_test.rb +6 -6
- data/test/mailers/reset_password_instructions_test.rb +5 -5
- data/test/mailers/unlock_instructions_test.rb +5 -5
- data/test/models/confirmable_test.rb +25 -1
- data/test/models/database_authenticatable_test.rb +26 -6
- data/test/models/lockable_test.rb +1 -1
- data/test/models/recoverable_test.rb +23 -0
- data/test/models/rememberable_test.rb +48 -95
- data/test/models/validatable_test.rb +2 -10
- data/test/models_test.rb +15 -6
- data/test/omniauth/url_helpers_test.rb +4 -7
- data/test/orm/active_record.rb +6 -1
- data/test/parameter_sanitizer_test.rb +103 -53
- data/test/rails_app/app/active_record/user.rb +1 -0
- data/test/rails_app/app/active_record/user_without_email.rb +8 -0
- data/test/rails_app/app/controllers/admins_controller.rb +1 -1
- data/test/rails_app/app/controllers/application_controller.rb +2 -2
- data/test/rails_app/app/controllers/home_controller.rb +5 -1
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +2 -2
- data/test/rails_app/app/controllers/users_controller.rb +5 -5
- data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
- data/test/rails_app/config/application.rb +1 -1
- data/test/rails_app/config/boot.rb +4 -4
- data/test/rails_app/config/environments/test.rb +6 -1
- data/test/rails_app/config/initializers/devise.rb +1 -1
- data/test/rails_app/config/initializers/secret_token.rb +1 -6
- data/test/rails_app/config/routes.rb +5 -0
- data/test/rails_app/lib/shared_user_without_email.rb +26 -0
- data/test/routes_test.rb +28 -13
- data/test/support/helpers.rb +4 -0
- data/test/support/http_method_compatibility.rb +51 -0
- data/test/support/webrat/integrations/rails.rb +9 -0
- data/test/test_helpers_test.rb +5 -5
- data/test/test_models.rb +1 -1
- metadata +41 -45
- data/gemfiles/Gemfile.rails-3.2-stable.lock +0 -169
- data/gemfiles/Gemfile.rails-4.0-stable +0 -29
- data/gemfiles/Gemfile.rails-4.0-stable.lock +0 -163
- data/script/cached-bundle +0 -49
- data/script/s3-put +0 -71
|
@@ -16,10 +16,6 @@ module Devise
|
|
|
16
16
|
# # resets the user password and save the record, true if valid passwords are given, otherwise false
|
|
17
17
|
# User.find(1).reset_password('password123', 'password123')
|
|
18
18
|
#
|
|
19
|
-
# # only resets the user password, without saving the record
|
|
20
|
-
# user = User.find(1)
|
|
21
|
-
# user.reset_password('password123', 'password123')
|
|
22
|
-
#
|
|
23
19
|
# # creates a new token and send it with instructions about how to reset the password
|
|
24
20
|
# User.find(1).send_reset_password_instructions
|
|
25
21
|
#
|
|
@@ -31,8 +27,8 @@ module Devise
|
|
|
31
27
|
end
|
|
32
28
|
|
|
33
29
|
included do
|
|
34
|
-
|
|
35
|
-
if email_changed? || encrypted_password_changed?
|
|
30
|
+
before_update do
|
|
31
|
+
if (respond_to?(:email_changed?) && email_changed?) || encrypted_password_changed?
|
|
36
32
|
clear_reset_password_token
|
|
37
33
|
end
|
|
38
34
|
end
|
|
@@ -87,7 +83,7 @@ module Devise
|
|
|
87
83
|
# reset_password_period_valid? # will always return false
|
|
88
84
|
#
|
|
89
85
|
def reset_password_period_valid?
|
|
90
|
-
reset_password_sent_at && reset_password_sent_at.utc >= self.class.reset_password_within.ago
|
|
86
|
+
reset_password_sent_at && reset_password_sent_at.utc >= self.class.reset_password_within.ago.utc
|
|
91
87
|
end
|
|
92
88
|
|
|
93
89
|
protected
|
|
@@ -39,17 +39,15 @@ module Devise
|
|
|
39
39
|
module Rememberable
|
|
40
40
|
extend ActiveSupport::Concern
|
|
41
41
|
|
|
42
|
-
attr_accessor :remember_me
|
|
42
|
+
attr_accessor :remember_me
|
|
43
43
|
|
|
44
44
|
def self.required_fields(klass)
|
|
45
45
|
[:remember_created_at]
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self.remember_token = self.class.remember_token if generate_remember_token?
|
|
52
|
-
self.remember_created_at = Time.now.utc if generate_remember_timestamp?(extend_period)
|
|
48
|
+
def remember_me!
|
|
49
|
+
self.remember_token = self.class.remember_token if respond_to?(:remember_token)
|
|
50
|
+
self.remember_created_at ||= Time.now.utc
|
|
53
51
|
save(validate: false) if self.changed?
|
|
54
52
|
end
|
|
55
53
|
|
|
@@ -57,19 +55,17 @@ module Devise
|
|
|
57
55
|
# it exists), and save the record without validations.
|
|
58
56
|
def forget_me!
|
|
59
57
|
return unless persisted?
|
|
60
|
-
self.remember_token = nil if respond_to?(:remember_token
|
|
58
|
+
self.remember_token = nil if respond_to?(:remember_token)
|
|
61
59
|
self.remember_created_at = nil if self.class.expire_all_remember_me_on_sign_out
|
|
62
60
|
save(validate: false)
|
|
63
61
|
end
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
remember_created_at.nil? || (remember_expires_at <= Time.now.utc)
|
|
63
|
+
def remember_expires_at
|
|
64
|
+
self.class.remember_for.from_now
|
|
68
65
|
end
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
remember_created_at + self.class.remember_for
|
|
67
|
+
def extend_remember_period
|
|
68
|
+
self.class.extend_remember_period
|
|
73
69
|
end
|
|
74
70
|
|
|
75
71
|
def rememberable_value
|
|
@@ -102,29 +98,47 @@ module Devise
|
|
|
102
98
|
def after_remembered
|
|
103
99
|
end
|
|
104
100
|
|
|
105
|
-
|
|
101
|
+
def remember_me?(token, generated_at)
|
|
102
|
+
# TODO: Normalize the JSON type coercion along with the Timeoutable hook
|
|
103
|
+
# in a single place https://github.com/plataformatec/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
|
|
104
|
+
if generated_at.is_a?(String)
|
|
105
|
+
generated_at = time_from_json(generated_at)
|
|
106
|
+
end
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
# The token is only valid if:
|
|
109
|
+
# 1. we have a date
|
|
110
|
+
# 2. the current time does not pass the expiry period
|
|
111
|
+
# 3. the record has a remember_created_at date
|
|
112
|
+
# 4. the token date is bigger than the remember_created_at
|
|
113
|
+
# 5. the token matches
|
|
114
|
+
generated_at.is_a?(Time) &&
|
|
115
|
+
(self.class.remember_for.ago < generated_at) &&
|
|
116
|
+
(generated_at > (remember_created_at || Time.now).utc) &&
|
|
117
|
+
Devise.secure_compare(rememberable_value, token)
|
|
109
118
|
end
|
|
110
119
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def
|
|
114
|
-
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
def time_from_json(value)
|
|
123
|
+
if value =~ /\A\d+\.\d+\Z/
|
|
124
|
+
Time.at(value.to_f)
|
|
125
|
+
else
|
|
126
|
+
Time.parse(value) rescue nil
|
|
127
|
+
end
|
|
115
128
|
end
|
|
116
129
|
|
|
117
130
|
module ClassMethods
|
|
118
131
|
# Create the cookie key using the record id and remember_token
|
|
119
132
|
def serialize_into_cookie(record)
|
|
120
|
-
[record.to_key, record.rememberable_value]
|
|
133
|
+
[record.to_key, record.rememberable_value, Time.now.utc.to_f.to_s]
|
|
121
134
|
end
|
|
122
135
|
|
|
123
136
|
# Recreate the user based on the stored cookie
|
|
124
|
-
def serialize_from_cookie(
|
|
137
|
+
def serialize_from_cookie(*args)
|
|
138
|
+
id, token, generated_at = *args
|
|
139
|
+
|
|
125
140
|
record = to_adapter.get(id)
|
|
126
|
-
record if record &&
|
|
127
|
-
Devise.secure_compare(record.rememberable_value, remember_token)
|
|
141
|
+
record if record && record.remember_me?(token, generated_at)
|
|
128
142
|
end
|
|
129
143
|
|
|
130
144
|
# Generate a token checking if one does not already exist in the database.
|
|
@@ -26,7 +26,6 @@ module Devise
|
|
|
26
26
|
|
|
27
27
|
# Checks whether the user session has expired based on configured time.
|
|
28
28
|
def timedout?(last_access)
|
|
29
|
-
return false if remember_exists_and_not_expired?
|
|
30
29
|
!timeout_in.nil? && last_access && last_access <= timeout_in.ago
|
|
31
30
|
end
|
|
32
31
|
|
|
@@ -36,11 +35,6 @@ module Devise
|
|
|
36
35
|
|
|
37
36
|
private
|
|
38
37
|
|
|
39
|
-
def remember_exists_and_not_expired?
|
|
40
|
-
return false unless respond_to?(:remember_created_at) && respond_to?(:remember_expired?)
|
|
41
|
-
remember_created_at && !remember_expired?
|
|
42
|
-
end
|
|
43
|
-
|
|
44
38
|
module ClassMethods
|
|
45
39
|
Devise::Models.config(self, :timeout_in)
|
|
46
40
|
end
|
data/lib/devise/models.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Devise
|
|
|
12
12
|
|
|
13
13
|
# Creates configuration values for Devise and for the given module.
|
|
14
14
|
#
|
|
15
|
-
# Devise::Models.config(Devise::
|
|
15
|
+
# Devise::Models.config(Devise::DatabaseAuthenticatable, :stretches)
|
|
16
16
|
#
|
|
17
17
|
# The line above creates:
|
|
18
18
|
#
|
|
@@ -2,16 +2,74 @@ module Devise
|
|
|
2
2
|
module OmniAuth
|
|
3
3
|
module UrlHelpers
|
|
4
4
|
def self.define_helpers(mapping)
|
|
5
|
+
return unless mapping.omniauthable?
|
|
6
|
+
|
|
7
|
+
mapping = mapping.name
|
|
8
|
+
|
|
9
|
+
class_eval do
|
|
10
|
+
define_method("#{mapping}_omniauth_authorize_path") do |provider, *args|
|
|
11
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
|
|
12
|
+
[Devise] #{mapping}_omniauth_authorize_path(#{provider.inspect}) is deprecated and it will be removed from Devise 4.1.
|
|
13
|
+
|
|
14
|
+
Please use #{mapping}_#{provider}_omniauth_authorize_path instead.
|
|
15
|
+
DEPRECATION
|
|
16
|
+
send("#{mapping}_#{provider}_omniauth_authorize_path", *args)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
define_method("#{mapping}_omniauth_authorize_url") do |provider, *args|
|
|
20
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
|
|
21
|
+
[Devise] #{mapping}_omniauth_authorize_url(#{provider.inspect}) is deprecated and it will be removed from Devise 4.1.
|
|
22
|
+
|
|
23
|
+
Please use #{mapping}_#{provider}_omniauth_authorize_url instead.
|
|
24
|
+
DEPRECATION
|
|
25
|
+
send("#{mapping}_#{provider}_omniauth_authorize_url", *args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
define_method("#{mapping}_omniauth_callback_path") do |provider, *args|
|
|
29
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
|
|
30
|
+
[Devise] #{mapping}_omniauth_callback_path(#{provider.inspect}) is deprecated and it will be removed from Devise 4.1.
|
|
31
|
+
|
|
32
|
+
Please use #{mapping}_#{provider}_omniauth_callback_path instead.
|
|
33
|
+
DEPRECATION
|
|
34
|
+
send("#{mapping}_#{provider}_omniauth_callback_path", *args)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
define_method("#{mapping}_omniauth_callback_url") do |provider, *args|
|
|
38
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
|
|
39
|
+
[Devise] #{mapping}_omniauth_callback_url(#{provider.inspect}) is deprecated and it will be removed from Devise 4.1.
|
|
40
|
+
|
|
41
|
+
Please use #{mapping}_#{provider}_omniauth_callback_url instead.
|
|
42
|
+
DEPRECATION
|
|
43
|
+
send("#{mapping}_#{provider}_omniauth_callback_url", *args)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
ActiveSupport.on_load(:action_controller) do
|
|
48
|
+
if respond_to?(:helper_method)
|
|
49
|
+
helper_method "#{mapping}_omniauth_authorize_path", "#{mapping}_omniauth_authorize_url"
|
|
50
|
+
helper_method "#{mapping}_omniauth_callback_path", "#{mapping}_omniauth_callback_url"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def omniauth_authorize_path(resource_or_scope, provider, *args)
|
|
56
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
57
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_path", *args)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def omniauth_authorize_url(resource_or_scope, provider, *args)
|
|
61
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
62
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_url", *args)
|
|
5
63
|
end
|
|
6
64
|
|
|
7
|
-
def
|
|
65
|
+
def omniauth_callback_path(resource_or_scope, provider, *args)
|
|
8
66
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
9
|
-
_devise_route_context.send("#{scope}
|
|
67
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_callback_path", *args)
|
|
10
68
|
end
|
|
11
69
|
|
|
12
|
-
def
|
|
70
|
+
def omniauth_callback_url(resource_or_scope, provider, *args)
|
|
13
71
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
14
|
-
_devise_route_context.send("#{scope}
|
|
72
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_callback_url", *args)
|
|
15
73
|
end
|
|
16
74
|
end
|
|
17
75
|
end
|
|
@@ -1,99 +1,214 @@
|
|
|
1
1
|
module Devise
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
# The +ParameterSanitizer+ deals with permitting specific parameters values
|
|
3
|
+
# for each +Devise+ scope in the application.
|
|
4
|
+
#
|
|
5
|
+
# The sanitizer knows about Devise default parameters (like +password+ and
|
|
6
|
+
# +password_confirmation+ for the `RegistrationsController`), and you can
|
|
7
|
+
# extend or change the permitted parameters list on your controllers.
|
|
8
|
+
#
|
|
9
|
+
# === Permitting new parameters
|
|
10
|
+
#
|
|
11
|
+
# You can add new parameters to the permitted list using the +permit+ method
|
|
12
|
+
# in a +before_action+ method, for instance.
|
|
13
|
+
#
|
|
14
|
+
# class ApplicationController < ActionController::Base
|
|
15
|
+
# before_action :configure_permitted_parameters, if: :devise_controller?
|
|
16
|
+
#
|
|
17
|
+
# protected
|
|
18
|
+
#
|
|
19
|
+
# def configure_permitted_parameters
|
|
20
|
+
# # Permit the `subscribe_newsletter` parameter along with the other
|
|
21
|
+
# # sign up parameters.
|
|
22
|
+
# devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# Using a block yields an +ActionController::Parameters+ object so you can
|
|
27
|
+
# permit nested parameters and have more control over how the parameters are
|
|
28
|
+
# permitted in your controller.
|
|
29
|
+
#
|
|
30
|
+
# def configure_permitted_parameters
|
|
31
|
+
# devise_parameter_sanitizer.permit(:sign_up) do |user|
|
|
32
|
+
# user.permit(newsletter_preferences: [])
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
class ParameterSanitizer
|
|
36
|
+
DEFAULT_PERMITTED_ATTRIBUTES = {
|
|
37
|
+
sign_in: [:password, :remember_me],
|
|
38
|
+
sign_up: [:password, :password_confirmation],
|
|
39
|
+
account_update: [:password, :password_confirmation, :current_password]
|
|
40
|
+
}
|
|
4
41
|
|
|
5
42
|
def initialize(resource_class, resource_name, params)
|
|
6
|
-
@
|
|
7
|
-
@resource_name = resource_name
|
|
43
|
+
@auth_keys = extract_auth_keys(resource_class)
|
|
8
44
|
@params = params
|
|
9
|
-
@
|
|
45
|
+
@resource_name = resource_name
|
|
46
|
+
@permitted = {}
|
|
47
|
+
|
|
48
|
+
DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
|
|
49
|
+
permit(action, keys: keys)
|
|
50
|
+
end
|
|
10
51
|
end
|
|
11
52
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
53
|
+
# Sanitize the parameters for a specific +action+.
|
|
54
|
+
#
|
|
55
|
+
# === Arguments
|
|
56
|
+
#
|
|
57
|
+
# * +action+ - A +Symbol+ with the action that the controller is
|
|
58
|
+
# performing, like +sign_up+, +sign_in+, etc.
|
|
59
|
+
#
|
|
60
|
+
# === Examples
|
|
61
|
+
#
|
|
62
|
+
# # Inside the `RegistrationsController#create` action.
|
|
63
|
+
# resource = build_resource(devise_parameter_sanitizer.sanitize(:sign_up))
|
|
64
|
+
# resource.save
|
|
65
|
+
#
|
|
66
|
+
# Returns an +ActiveSupport::HashWithIndifferentAccess+ with the permitted
|
|
67
|
+
# attributes.
|
|
68
|
+
def sanitize(action)
|
|
69
|
+
permissions = @permitted[action]
|
|
70
|
+
|
|
71
|
+
# DEPRECATED: Remove this branch on Devise 4.1.
|
|
72
|
+
if respond_to?(action, true)
|
|
73
|
+
deprecate_instance_method_sanitization(action)
|
|
74
|
+
return cast_to_hash send(action)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if permissions.respond_to?(:call)
|
|
78
|
+
cast_to_hash permissions.call(default_params)
|
|
79
|
+
elsif permissions.present?
|
|
80
|
+
cast_to_hash permit_keys(default_params, permissions)
|
|
15
81
|
else
|
|
16
|
-
|
|
82
|
+
unknown_action!(action)
|
|
17
83
|
end
|
|
18
84
|
end
|
|
19
85
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
86
|
+
# Add or remove new parameters to the permitted list of an +action+.
|
|
87
|
+
#
|
|
88
|
+
# === Arguments
|
|
89
|
+
#
|
|
90
|
+
# * +action+ - A +Symbol+ with the action that the controller is
|
|
91
|
+
# performing, like +sign_up+, +sign_in+, etc.
|
|
92
|
+
# * +keys:+ - An +Array+ of keys that also should be permitted.
|
|
93
|
+
# * +except:+ - An +Array+ of keys that shouldn't be permitted.
|
|
94
|
+
# * +block+ - A block that should be used to permit the action
|
|
95
|
+
# parameters instead of the +Array+ based approach. The block will be
|
|
96
|
+
# called with an +ActionController::Parameters+ instance.
|
|
97
|
+
#
|
|
98
|
+
# === Examples
|
|
99
|
+
#
|
|
100
|
+
# # Adding new parameters to be permitted in the `sign_up` action.
|
|
101
|
+
# devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
|
|
102
|
+
#
|
|
103
|
+
# # Removing the `password` parameter from the `account_update` action.
|
|
104
|
+
# devise_parameter_sanitizer.permit(:account_update, except: [:password])
|
|
105
|
+
#
|
|
106
|
+
# # Using the block form to completely override how we permit the
|
|
107
|
+
# # parameters for the `sign_up` action.
|
|
108
|
+
# devise_parameter_sanitizer.permit(:sign_up) do |user|
|
|
109
|
+
# user.permit(:email, :password, :password_confirmation)
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
#
|
|
113
|
+
# Returns nothing.
|
|
114
|
+
def permit(action, keys: nil, except: nil, &block)
|
|
115
|
+
if block_given?
|
|
116
|
+
@permitted[action] = block
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
if keys.present?
|
|
120
|
+
@permitted[action] ||= @auth_keys.dup
|
|
121
|
+
@permitted[action].concat(keys)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if except.present?
|
|
125
|
+
@permitted[action] ||= @auth_keys.dup
|
|
126
|
+
@permitted[action] = @permitted[action] - except
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# DEPRECATED: Remove this method on Devise 4.1.
|
|
131
|
+
def for(action, &block) # :nodoc:
|
|
132
|
+
if block_given?
|
|
133
|
+
deprecate_for_with_block(action)
|
|
134
|
+
permit(action, &block)
|
|
23
135
|
else
|
|
24
|
-
|
|
136
|
+
deprecate_for_without_block(action)
|
|
137
|
+
@permitted[action] or unknown_action!(action)
|
|
25
138
|
end
|
|
26
139
|
end
|
|
27
140
|
|
|
28
141
|
private
|
|
29
142
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def
|
|
35
|
-
|
|
143
|
+
# Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
|
|
144
|
+
# that can be used elsewhere.
|
|
145
|
+
#
|
|
146
|
+
# Returns an +ActiveSupport::HashWithIndifferentAccess+.
|
|
147
|
+
def cast_to_hash(params)
|
|
148
|
+
# TODO: Remove the `with_indifferent_access` method call when we only support Rails 5+.
|
|
149
|
+
params && params.to_h.with_indifferent_access
|
|
36
150
|
end
|
|
37
151
|
|
|
38
152
|
def default_params
|
|
39
|
-
params.fetch(resource_name, {})
|
|
153
|
+
@params.fetch(@resource_name, {})
|
|
40
154
|
end
|
|
41
|
-
end
|
|
42
155
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
super
|
|
46
|
-
@permitted = Hash.new { |h,k| h[k] = attributes_for(k) }
|
|
156
|
+
def permit_keys(parameters, keys)
|
|
157
|
+
parameters.permit(*keys)
|
|
47
158
|
end
|
|
48
159
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
end
|
|
160
|
+
def extract_auth_keys(klass)
|
|
161
|
+
auth_keys = klass.authentication_keys
|
|
52
162
|
|
|
53
|
-
|
|
54
|
-
permit self.for(:sign_up)
|
|
163
|
+
auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
|
|
55
164
|
end
|
|
56
165
|
|
|
57
|
-
def
|
|
58
|
-
|
|
166
|
+
def unknown_action!(action)
|
|
167
|
+
raise NotImplementedError, <<-MESSAGE.strip_heredoc
|
|
168
|
+
"Devise doesn't know how to sanitize parameters for '#{action}'".
|
|
169
|
+
If you want to define a new set of parameters to be sanitized use the
|
|
170
|
+
`permit` method first:
|
|
171
|
+
|
|
172
|
+
devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
|
|
173
|
+
MESSAGE
|
|
59
174
|
end
|
|
60
175
|
|
|
61
|
-
|
|
176
|
+
def deprecate_for_with_block(action)
|
|
177
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
|
178
|
+
[Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.1.
|
|
179
|
+
Please use the `permit` method:
|
|
62
180
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
181
|
+
devise_parameter_sanitizer.permit(:#{action}) do |user|
|
|
182
|
+
# Your block here.
|
|
183
|
+
end
|
|
184
|
+
MESSAGE
|
|
67
185
|
end
|
|
68
186
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end
|
|
187
|
+
def deprecate_for_without_block(action)
|
|
188
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
|
189
|
+
[Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.1.
|
|
190
|
+
Please use the `permit` method to add or remove any key:
|
|
74
191
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
send(kind)
|
|
78
|
-
else
|
|
79
|
-
raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
|
|
80
|
-
end
|
|
81
|
-
end
|
|
192
|
+
To add any new key, use the `keys` keyword argument:
|
|
193
|
+
devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
|
|
82
194
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
auth_keys + [:password, :remember_me]
|
|
87
|
-
when :sign_up
|
|
88
|
-
auth_keys + [:password, :password_confirmation]
|
|
89
|
-
when :account_update
|
|
90
|
-
auth_keys + [:password, :password_confirmation, :current_password]
|
|
91
|
-
end
|
|
195
|
+
To remove any existing key, use the `except` keyword argument:
|
|
196
|
+
devise_parameter_sanitizer.permit(:#{action}, except: [:email])
|
|
197
|
+
MESSAGE
|
|
92
198
|
end
|
|
93
199
|
|
|
94
|
-
def
|
|
95
|
-
|
|
96
|
-
|
|
200
|
+
def deprecate_instance_method_sanitization(action)
|
|
201
|
+
ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
|
|
202
|
+
[Devise] Parameter sanitization through a "#{self.class.name}##{action}" method is deprecated and it will be removed from Devise 4.1.
|
|
203
|
+
Please use the `permit` method on your sanitizer `initialize` method.
|
|
204
|
+
|
|
205
|
+
class #{self.class.name} < Devise::ParameterSanitizer
|
|
206
|
+
def initialize(*)
|
|
207
|
+
super
|
|
208
|
+
permit(:#{action}, keys: [:param1, :param2, :param3])
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
MESSAGE
|
|
97
212
|
end
|
|
98
213
|
end
|
|
99
214
|
end
|
data/lib/devise/rails/routes.rb
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
require "active_support/core_ext/object/try"
|
|
2
2
|
require "active_support/core_ext/hash/slice"
|
|
3
3
|
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def finalize_with_devise!
|
|
9
|
-
result = finalize_without_devise!
|
|
10
|
-
|
|
4
|
+
module Devise
|
|
5
|
+
module RouteSet
|
|
6
|
+
def finalize!
|
|
7
|
+
result = super
|
|
11
8
|
@devise_finalized ||= begin
|
|
12
9
|
if Devise.router_name.nil? && defined?(@devise_finalized) && self != Rails.application.try(:routes)
|
|
13
10
|
warn "[DEVISE] We have detected that you are using devise_for inside engine routes. " \
|
|
@@ -21,10 +18,16 @@ module ActionDispatch::Routing
|
|
|
21
18
|
Devise.regenerate_helpers!
|
|
22
19
|
true
|
|
23
20
|
end
|
|
24
|
-
|
|
25
21
|
result
|
|
26
22
|
end
|
|
27
|
-
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
module ActionDispatch::Routing
|
|
27
|
+
class RouteSet #:nodoc:
|
|
28
|
+
# Ensure Devise modules are included only after loading routes, because we
|
|
29
|
+
# need devise_for mappings already declared to create filters and helpers.
|
|
30
|
+
prepend Devise::RouteSet
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
class Mapper
|
|
@@ -84,20 +87,34 @@ module ActionDispatch::Routing
|
|
|
84
87
|
#
|
|
85
88
|
# You can configure your routes with some options:
|
|
86
89
|
#
|
|
87
|
-
# * class_name:
|
|
90
|
+
# * class_name: set up a different class to be looked up by devise, if it cannot be
|
|
88
91
|
# properly found by the route name.
|
|
89
92
|
#
|
|
90
93
|
# devise_for :users, class_name: 'Account'
|
|
91
94
|
#
|
|
92
|
-
# * path: allows you to
|
|
93
|
-
# The following route configuration would
|
|
95
|
+
# * path: allows you to set up path name that will be used, as rails routes does.
|
|
96
|
+
# The following route configuration would set up your route as /accounts instead of /users:
|
|
94
97
|
#
|
|
95
98
|
# devise_for :users, path: 'accounts'
|
|
96
99
|
#
|
|
97
|
-
# * singular:
|
|
98
|
-
#
|
|
100
|
+
# * singular: set up the singular name for the given resource. This is used as the helper methods
|
|
101
|
+
# names in controller ("authenticate_#{singular}!", "#{singular}_signed_in?", "current_#{singular}"
|
|
102
|
+
# and "#{singular}_session"), as the scope name in routes and as the scope given to warden.
|
|
99
103
|
#
|
|
100
|
-
# devise_for :
|
|
104
|
+
# devise_for :admins, singular: :manager
|
|
105
|
+
#
|
|
106
|
+
# devise_scope :manager do
|
|
107
|
+
# ...
|
|
108
|
+
# end
|
|
109
|
+
#
|
|
110
|
+
# class ManagerController < ApplicationController
|
|
111
|
+
# before_action authenticate_manager!
|
|
112
|
+
#
|
|
113
|
+
# def show
|
|
114
|
+
# @manager = current_manager
|
|
115
|
+
# ...
|
|
116
|
+
# end
|
|
117
|
+
# end
|
|
101
118
|
#
|
|
102
119
|
# * path_names: configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
|
|
103
120
|
# :password, :confirmation, :unlock.
|
|
@@ -414,27 +431,29 @@ options to another `devise_for` call outside the scope. Here is an example:
|
|
|
414
431
|
end
|
|
415
432
|
ERROR
|
|
416
433
|
end
|
|
417
|
-
|
|
418
|
-
|
|
434
|
+
current_scope = @scope.dup
|
|
435
|
+
if @scope.respond_to? :new
|
|
436
|
+
@scope = @scope.new path: nil
|
|
437
|
+
else
|
|
438
|
+
@scope[:path] = nil
|
|
439
|
+
end
|
|
419
440
|
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.fullpath}/auth".squeeze("/")
|
|
420
441
|
|
|
421
442
|
set_omniauth_path_prefix!(path_prefix)
|
|
422
443
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
as: :omniauth_authorize,
|
|
429
|
-
via: [:get, :post]
|
|
444
|
+
mapping.to.omniauth_providers.each do |provider|
|
|
445
|
+
match "#{path_prefix}/#{provider}",
|
|
446
|
+
to: "#{controllers[:omniauth_callbacks]}#passthru",
|
|
447
|
+
as: "#{provider}_omniauth_authorize",
|
|
448
|
+
via: [:get, :post]
|
|
430
449
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
450
|
+
match "#{path_prefix}/#{provider}/callback",
|
|
451
|
+
to: "#{controllers[:omniauth_callbacks]}##{provider}",
|
|
452
|
+
as: "#{provider}_omniauth_callback",
|
|
453
|
+
via: [:get, :post]
|
|
454
|
+
end
|
|
436
455
|
ensure
|
|
437
|
-
@scope
|
|
456
|
+
@scope = current_scope
|
|
438
457
|
end
|
|
439
458
|
|
|
440
459
|
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
|
|
@@ -443,7 +462,11 @@ ERROR
|
|
|
443
462
|
exclusive = { as: new_as, path: new_path, module: nil }
|
|
444
463
|
exclusive.merge!(options.slice(:constraints, :defaults, :options))
|
|
445
464
|
|
|
446
|
-
|
|
465
|
+
if @scope.respond_to? :new
|
|
466
|
+
@scope = @scope.new exclusive
|
|
467
|
+
else
|
|
468
|
+
exclusive.each_pair { |key, value| @scope[key] = value }
|
|
469
|
+
end
|
|
447
470
|
yield
|
|
448
471
|
ensure
|
|
449
472
|
@scope = current_scope
|