devise 3.2.4 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +33 -17
- data/CHANGELOG.md +57 -1033
- data/CODE_OF_CONDUCT.md +22 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -5
- data/Gemfile.lock +138 -115
- data/MIT-LICENSE +1 -1
- data/README.md +124 -65
- data/Rakefile +2 -1
- data/app/controllers/devise/confirmations_controller.rb +7 -3
- data/app/controllers/devise/omniauth_callbacks_controller.rb +8 -4
- data/app/controllers/devise/passwords_controller.rb +16 -6
- data/app/controllers/devise/registrations_controller.rb +22 -10
- data/app/controllers/devise/sessions_controller.rb +42 -14
- data/app/controllers/devise/unlocks_controller.rb +5 -2
- data/app/controllers/devise_controller.rb +63 -29
- data/app/mailers/devise/mailer.rb +4 -0
- data/app/views/devise/confirmations/new.html.erb +7 -3
- data/app/views/devise/mailer/password_change.html.erb +3 -0
- data/app/views/devise/passwords/edit.html.erb +14 -5
- data/app/views/devise/passwords/new.html.erb +7 -3
- data/app/views/devise/registrations/edit.html.erb +19 -9
- data/app/views/devise/registrations/new.html.erb +18 -7
- data/app/views/devise/sessions/new.html.erb +16 -7
- data/app/views/devise/shared/{_links.erb → _links.html.erb} +2 -2
- data/app/views/devise/unlocks/new.html.erb +7 -3
- data/bin/test +13 -0
- data/config/locales/en.yml +19 -16
- data/devise.gemspec +3 -4
- data/gemfiles/{Gemfile.rails-3.2-stable → Gemfile.rails-4.1-stable} +6 -6
- data/gemfiles/Gemfile.rails-4.1-stable.lock +167 -0
- data/gemfiles/{Gemfile.rails-head → Gemfile.rails-4.2-stable} +6 -6
- data/gemfiles/Gemfile.rails-4.2-stable.lock +189 -0
- data/gemfiles/Gemfile.rails-5.0-beta +37 -0
- data/gemfiles/Gemfile.rails-5.0-beta.lock +199 -0
- data/lib/devise/controllers/helpers.rb +94 -27
- data/lib/devise/controllers/rememberable.rb +9 -2
- data/lib/devise/controllers/sign_in_out.rb +2 -9
- data/lib/devise/controllers/store_location.rb +11 -3
- data/lib/devise/controllers/url_helpers.rb +7 -7
- data/lib/devise/encryptor.rb +22 -0
- data/lib/devise/failure_app.rb +72 -23
- data/lib/devise/hooks/activatable.rb +3 -4
- data/lib/devise/hooks/csrf_cleaner.rb +3 -1
- data/lib/devise/hooks/timeoutable.rb +13 -8
- data/lib/devise/mailers/helpers.rb +1 -1
- data/lib/devise/mapping.rb +6 -2
- data/lib/devise/models/authenticatable.rb +32 -28
- data/lib/devise/models/confirmable.rb +55 -22
- data/lib/devise/models/database_authenticatable.rb +32 -19
- data/lib/devise/models/lockable.rb +5 -5
- data/lib/devise/models/recoverable.rb +44 -20
- data/lib/devise/models/rememberable.rb +54 -27
- data/lib/devise/models/timeoutable.rb +0 -6
- data/lib/devise/models/trackable.rb +5 -3
- data/lib/devise/models/validatable.rb +3 -3
- 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 +76 -59
- data/lib/devise/rails/warden_compat.rb +1 -10
- data/lib/devise/rails.rb +2 -11
- data/lib/devise/strategies/authenticatable.rb +15 -6
- data/lib/devise/strategies/database_authenticatable.rb +5 -4
- data/lib/devise/strategies/rememberable.rb +13 -3
- data/lib/devise/test_helpers.rb +12 -7
- data/lib/devise/token_generator.rb +1 -41
- data/lib/devise/version.rb +1 -1
- data/lib/devise.rb +150 -58
- data/lib/generators/active_record/devise_generator.rb +28 -4
- data/lib/generators/active_record/templates/migration.rb +3 -3
- data/lib/generators/active_record/templates/migration_existing.rb +3 -3
- data/lib/generators/devise/controllers_generator.rb +44 -0
- 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/README +1 -1
- data/lib/generators/templates/controllers/README +14 -0
- data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
- data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
- data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
- data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
- data/lib/generators/templates/devise.rb +36 -28
- 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/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +2 -2
- data/test/controllers/custom_registrations_controller_test.rb +40 -0
- data/test/controllers/custom_strategy_test.rb +7 -5
- data/test/controllers/helper_methods_test.rb +22 -0
- data/test/controllers/helpers_test.rb +41 -1
- data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
- data/test/controllers/internal_helpers_test.rb +19 -15
- data/test/controllers/load_hooks_controller_test.rb +19 -0
- data/test/controllers/passwords_controller_test.rb +5 -4
- data/test/controllers/sessions_controller_test.rb +24 -21
- data/test/controllers/url_helpers_test.rb +7 -1
- data/test/devise_test.rb +48 -8
- data/test/failure_app_test.rb +107 -19
- data/test/generators/active_record_generator_test.rb +6 -26
- data/test/generators/controllers_generator_test.rb +48 -0
- data/test/generators/install_generator_test.rb +14 -3
- data/test/generators/views_generator_test.rb +8 -1
- data/test/helpers/devise_helper_test.rb +10 -12
- data/test/integration/authenticatable_test.rb +37 -21
- data/test/integration/confirmable_test.rb +54 -14
- data/test/integration/database_authenticatable_test.rb +12 -1
- data/test/integration/http_authenticatable_test.rb +4 -5
- data/test/integration/lockable_test.rb +10 -9
- data/test/integration/omniauthable_test.rb +13 -11
- data/test/integration/recoverable_test.rb +28 -15
- data/test/integration/registerable_test.rb +41 -33
- data/test/integration/rememberable_test.rb +51 -7
- data/test/integration/timeoutable_test.rb +23 -22
- data/test/integration/trackable_test.rb +3 -3
- data/test/mailers/confirmation_instructions_test.rb +10 -10
- data/test/mailers/reset_password_instructions_test.rb +8 -8
- data/test/mailers/unlock_instructions_test.rb +8 -8
- data/test/mapping_test.rb +7 -0
- data/test/models/authenticatable_test.rb +11 -1
- data/test/models/confirmable_test.rb +91 -42
- data/test/models/database_authenticatable_test.rb +26 -6
- data/test/models/lockable_test.rb +29 -17
- data/test/models/recoverable_test.rb +74 -7
- data/test/models/rememberable_test.rb +68 -94
- data/test/models/trackable_test.rb +28 -0
- data/test/models/validatable_test.rb +9 -17
- 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_on_engine.rb +7 -0
- data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
- data/test/rails_app/app/active_record/user_without_email.rb +8 -0
- data/test/rails_app/app/controllers/admins_controller.rb +1 -6
- data/test/rails_app/app/controllers/application_controller.rb +5 -2
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +31 -0
- data/test/rails_app/app/controllers/home_controller.rb +5 -1
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +3 -3
- data/test/rails_app/app/controllers/users_controller.rb +6 -6
- data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
- data/test/rails_app/app/mailers/users/mailer.rb +0 -9
- data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
- data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
- data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
- data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
- data/test/rails_app/config/application.rb +3 -3
- data/test/rails_app/config/boot.rb +4 -4
- data/test/rails_app/config/environments/production.rb +6 -2
- data/test/rails_app/config/environments/test.rb +13 -3
- data/test/rails_app/config/initializers/devise.rb +15 -16
- data/test/rails_app/config/initializers/secret_token.rb +1 -6
- data/test/rails_app/config/routes.rb +23 -3
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +2 -2
- data/test/rails_app/lib/shared_user.rb +1 -1
- data/test/rails_app/lib/shared_user_without_email.rb +26 -0
- data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
- data/test/rails_test.rb +9 -0
- data/test/routes_test.rb +33 -16
- data/test/support/assertions.rb +2 -3
- data/test/support/helpers.rb +13 -6
- data/test/support/http_method_compatibility.rb +51 -0
- data/test/support/integration.rb +4 -4
- data/test/support/webrat/integrations/rails.rb +9 -0
- data/test/test_helper.rb +7 -0
- data/test/test_helpers_test.rb +43 -38
- data/test/test_models.rb +3 -3
- metadata +77 -23
- data/gemfiles/Gemfile.rails-4.0-stable +0 -29
@@ -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.
|
103
|
+
#
|
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!
|
99
112
|
#
|
100
|
-
#
|
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.
|
@@ -119,7 +136,7 @@ module ActionDispatch::Routing
|
|
119
136
|
# * sign_out_via: the HTTP method(s) accepted for the :sign_out action (default: :get),
|
120
137
|
# if you wish to restrict this to accept only :post or :delete requests you should do:
|
121
138
|
#
|
122
|
-
# devise_for :users, sign_out_via: [
|
139
|
+
# devise_for :users, sign_out_via: [:post, :delete]
|
123
140
|
#
|
124
141
|
# You need to make sure that your sign_out controls trigger a request with a matching HTTP method.
|
125
142
|
#
|
@@ -129,7 +146,8 @@ module ActionDispatch::Routing
|
|
129
146
|
#
|
130
147
|
# devise_for :users, module: "users"
|
131
148
|
#
|
132
|
-
# * skip: tell which controller you want to skip routes from being created
|
149
|
+
# * skip: tell which controller you want to skip routes from being created.
|
150
|
+
# It accepts :all as an option, meaning it will not generate any route at all:
|
133
151
|
#
|
134
152
|
# devise_for :users, skip: :sessions
|
135
153
|
#
|
@@ -153,6 +171,8 @@ module ActionDispatch::Routing
|
|
153
171
|
#
|
154
172
|
# * defaults: works the same as Rails' defaults
|
155
173
|
#
|
174
|
+
# * router_name: allows application level router name to be overwritten for the current scope
|
175
|
+
#
|
156
176
|
# ==== Scoping
|
157
177
|
#
|
158
178
|
# Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:
|
@@ -224,7 +244,7 @@ module ActionDispatch::Routing
|
|
224
244
|
raise_no_devise_method_error!(mapping.class_name) unless mapping.to.respond_to?(:devise)
|
225
245
|
rescue NameError => e
|
226
246
|
raise unless mapping.class_name == resource.to_s.classify
|
227
|
-
warn "[WARNING] You provided devise_for #{resource.inspect} but there is "
|
247
|
+
warn "[WARNING] You provided devise_for #{resource.inspect} but there is " \
|
228
248
|
"no model #{mapping.class_name} defined in your application"
|
229
249
|
next
|
230
250
|
rescue NoMethodError => e
|
@@ -234,13 +254,12 @@ module ActionDispatch::Routing
|
|
234
254
|
|
235
255
|
if options[:controllers] && options[:controllers][:omniauth_callbacks]
|
236
256
|
unless mapping.omniauthable?
|
237
|
-
|
238
|
-
|
239
|
-
raise msg
|
257
|
+
raise ArgumentError, "Mapping omniauth_callbacks on a resource that is not omniauthable\n" \
|
258
|
+
"Please add `devise :omniauthable` to the `#{mapping.class_name}` model"
|
240
259
|
end
|
241
260
|
end
|
242
261
|
|
243
|
-
routes
|
262
|
+
routes = mapping.used_routes
|
244
263
|
|
245
264
|
devise_scope mapping.name do
|
246
265
|
with_devise_exclusive_scope mapping.fullpath, mapping.name, options do
|
@@ -400,59 +419,57 @@ module ActionDispatch::Routing
|
|
400
419
|
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
401
420
|
if mapping.fullpath =~ /:[a-zA-Z_]/
|
402
421
|
raise <<-ERROR
|
403
|
-
Devise does not support scoping
|
422
|
+
Devise does not support scoping OmniAuth callbacks under a dynamic segment
|
404
423
|
and you have set #{mapping.fullpath.inspect}. You can work around by passing
|
405
|
-
`skip: :omniauth_callbacks`
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
match "/users/auth/:action/callback",
|
414
|
-
constraints: { action: /google|facebook/ },
|
415
|
-
to: "devise/omniauth_callbacks",
|
416
|
-
as: :omniauth_callback,
|
417
|
-
via: [:get, :post]
|
424
|
+
`skip: :omniauth_callbacks` to the `devise_for` call and extract omniauth
|
425
|
+
options to another `devise_for` call outside the scope. Here is an example:
|
426
|
+
|
427
|
+
devise_for :users, only: :omniauth_callbacks, controllers: {omniauth_callbacks: 'users/omniauth_callbacks'}
|
428
|
+
|
429
|
+
scope '/(:locale)', locale: /ru|en/ do
|
430
|
+
devise_for :users, skip: :omniauth_callbacks
|
431
|
+
end
|
418
432
|
ERROR
|
419
433
|
end
|
420
|
-
|
421
|
-
|
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
|
422
440
|
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.fullpath}/auth".squeeze("/")
|
423
441
|
|
424
442
|
set_omniauth_path_prefix!(path_prefix)
|
425
443
|
|
426
|
-
|
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]
|
427
449
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
match "#{path_prefix}/:action/callback",
|
435
|
-
constraints: { action: providers },
|
436
|
-
to: controllers[:omniauth_callbacks],
|
437
|
-
as: :omniauth_callback,
|
438
|
-
via: [:get, :post]
|
450
|
+
match "#{path_prefix}/#{provider}/callback",
|
451
|
+
to: "#{controllers[:omniauth_callbacks]}##{provider}",
|
452
|
+
as: "#{provider}_omniauth_callback",
|
453
|
+
via: [:get, :post]
|
454
|
+
end
|
439
455
|
ensure
|
440
|
-
@scope
|
456
|
+
@scope = current_scope
|
441
457
|
end
|
442
458
|
|
443
|
-
DEVISE_SCOPE_KEYS = [:as, :path, :module, :constraints, :defaults, :options]
|
444
|
-
|
445
459
|
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
|
446
|
-
|
447
|
-
DEVISE_SCOPE_KEYS.each { |k| old[k] = @scope[k] }
|
460
|
+
current_scope = @scope.dup
|
448
461
|
|
449
|
-
|
450
|
-
|
462
|
+
exclusive = { as: new_as, path: new_path, module: nil }
|
463
|
+
exclusive.merge!(options.slice(:constraints, :defaults, :options))
|
451
464
|
|
452
|
-
@scope.
|
465
|
+
if @scope.respond_to? :new
|
466
|
+
@scope = @scope.new exclusive
|
467
|
+
else
|
468
|
+
exclusive.each_pair { |key, value| @scope[key] = value }
|
469
|
+
end
|
453
470
|
yield
|
454
471
|
ensure
|
455
|
-
@scope
|
472
|
+
@scope = current_scope
|
456
473
|
end
|
457
474
|
|
458
475
|
def constraints_for(method_to_apply, scope=nil, block=nil)
|
@@ -3,17 +3,8 @@ module Warden::Mixins::Common
|
|
3
3
|
@request ||= ActionDispatch::Request.new(env)
|
4
4
|
end
|
5
5
|
|
6
|
-
# Deprecate: Remove this check once we move to Rails 4 only.
|
7
|
-
NULL_STORE =
|
8
|
-
defined?(ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash) ?
|
9
|
-
ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash : nil
|
10
|
-
|
11
6
|
def reset_session!
|
12
|
-
|
13
|
-
# This is a bug that needs to be fixed in Rails.
|
14
|
-
unless NULL_STORE && request.session.is_a?(NULL_STORE)
|
15
|
-
request.reset_session
|
16
|
-
end
|
7
|
+
request.reset_session
|
17
8
|
end
|
18
9
|
|
19
10
|
def cookies
|
data/lib/devise/rails.rb
CHANGED
@@ -17,7 +17,7 @@ module Devise
|
|
17
17
|
Devise.include_helpers(Devise::Controllers)
|
18
18
|
end
|
19
19
|
|
20
|
-
initializer "devise.omniauth" do |app|
|
20
|
+
initializer "devise.omniauth", after: :load_config_initializers, before: :build_middleware_stack do |app|
|
21
21
|
Devise.omniauth_configs.each do |provider, config|
|
22
22
|
app.middleware.use config.strategy_class, *config.args do |strategy|
|
23
23
|
config.strategy = strategy
|
@@ -39,18 +39,9 @@ module Devise
|
|
39
39
|
Devise.token_generator ||=
|
40
40
|
if secret_key = Devise.secret_key
|
41
41
|
Devise::TokenGenerator.new(
|
42
|
-
|
42
|
+
ActiveSupport::CachingKeyGenerator.new(ActiveSupport::KeyGenerator.new(secret_key))
|
43
43
|
)
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
|
48
|
-
# Deprecate: Remove once we move to Rails 4 only.
|
49
|
-
ActionDispatch::Routing::RoutesProxy.class_eval do
|
50
|
-
def respond_to?(method, include_private = false)
|
51
|
-
super || routes.url_helpers.respond_to?(method)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
46
|
end
|
56
47
|
end
|
@@ -16,11 +16,18 @@ module Devise
|
|
16
16
|
valid_for_params_auth? || valid_for_http_auth?
|
17
17
|
end
|
18
18
|
|
19
|
+
# Override and set to false for things like OmniAuth that technically
|
20
|
+
# run through Authentication (user_set) very often, which would normally
|
21
|
+
# reset CSRF data in the session
|
22
|
+
def clean_up_csrf?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
19
26
|
private
|
20
27
|
|
21
28
|
# Receives a resource and check if it is valid by calling valid_for_authentication?
|
22
29
|
# An optional block that will be triggered while validating can be optionally
|
23
|
-
# given as parameter. Check Devise::Models::
|
30
|
+
# given as parameter. Check Devise::Models::Authenticatable.valid_for_authentication?
|
24
31
|
# for more information.
|
25
32
|
#
|
26
33
|
# In case the resource can't be validated, it will fail with the given
|
@@ -29,7 +36,6 @@ module Devise
|
|
29
36
|
result = resource && resource.valid_for_authentication?(&block)
|
30
37
|
|
31
38
|
if result
|
32
|
-
decorate(resource)
|
33
39
|
true
|
34
40
|
else
|
35
41
|
if resource
|
@@ -40,7 +46,7 @@ module Devise
|
|
40
46
|
end
|
41
47
|
|
42
48
|
# Get values from params and set in the resource.
|
43
|
-
def
|
49
|
+
def remember_me(resource)
|
44
50
|
resource.remember_me = remember_me? if resource.respond_to?(:remember_me=)
|
45
51
|
end
|
46
52
|
|
@@ -51,7 +57,7 @@ module Devise
|
|
51
57
|
|
52
58
|
# Check if this is a valid strategy for http authentication by:
|
53
59
|
#
|
54
|
-
# * Validating if the model allows
|
60
|
+
# * Validating if the model allows http authentication;
|
55
61
|
# * If any of the authorization headers were sent;
|
56
62
|
# * If all authentication keys are present;
|
57
63
|
#
|
@@ -102,14 +108,17 @@ module Devise
|
|
102
108
|
params_auth_hash.is_a?(Hash)
|
103
109
|
end
|
104
110
|
|
105
|
-
#
|
111
|
+
# Note: unlike `Model.valid_password?`, this method does not actually
|
112
|
+
# ensure that the password in the params matches the password stored in
|
113
|
+
# the database. It only checks if the password is *present*. Do not rely
|
114
|
+
# on this method for validating that a given password is correct.
|
106
115
|
def valid_password?
|
107
116
|
password.present?
|
108
117
|
end
|
109
118
|
|
110
119
|
# Helper to decode credentials from HTTP.
|
111
120
|
def decode_credentials
|
112
|
-
return [] unless request.authorization && request.authorization =~ /^Basic (.*)/
|
121
|
+
return [] unless request.authorization && request.authorization =~ /^Basic (.*)/mi
|
113
122
|
Base64.decode64($1).split(/:/, 2)
|
114
123
|
end
|
115
124
|
|
@@ -5,15 +5,16 @@ module Devise
|
|
5
5
|
# Default strategy for signing in a user, based on their email and password in the database.
|
6
6
|
class DatabaseAuthenticatable < Authenticatable
|
7
7
|
def authenticate!
|
8
|
-
resource =
|
9
|
-
|
8
|
+
resource = password.present? && mapping.to.find_for_database_authentication(authentication_hash)
|
9
|
+
hashed = false
|
10
10
|
|
11
|
-
if validate(resource){
|
11
|
+
if validate(resource){ hashed = true; resource.valid_password?(password) }
|
12
|
+
remember_me(resource)
|
12
13
|
resource.after_database_authentication
|
13
14
|
success!(resource)
|
14
15
|
end
|
15
16
|
|
16
|
-
mapping.to.new.password = password if !
|
17
|
+
mapping.to.new.password = password if !hashed && Devise.paranoid
|
17
18
|
fail(:not_found_in_database) unless resource
|
18
19
|
end
|
19
20
|
end
|
@@ -25,15 +25,25 @@ module Devise
|
|
25
25
|
end
|
26
26
|
|
27
27
|
if validate(resource)
|
28
|
+
remember_me(resource) if extend_remember_me?(resource)
|
29
|
+
resource.after_remembered
|
28
30
|
success!(resource)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
34
|
+
# No need to clean up the CSRF when using rememberable.
|
35
|
+
# In fact, cleaning it up here would be a bug because
|
36
|
+
# rememberable is triggered on GET requests which means
|
37
|
+
# we would render a page on first access with all csrf
|
38
|
+
# tokens expired.
|
39
|
+
def clean_up_csrf?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
32
43
|
private
|
33
44
|
|
34
|
-
def
|
35
|
-
|
36
|
-
resource.extend_remember_period = mapping.to.extend_remember_period if resource.respond_to?(:extend_remember_period=)
|
45
|
+
def extend_remember_me?(resource)
|
46
|
+
resource.respond_to?(:extend_remember_period) && resource.extend_remember_period
|
37
47
|
end
|
38
48
|
|
39
49
|
def remember_me?
|