devise 3.2.4 → 4.7.1
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 +5 -5
- data/CHANGELOG.md +259 -994
- data/MIT-LICENSE +1 -1
- data/README.md +336 -99
- data/app/controllers/devise/confirmations_controller.rb +9 -3
- data/app/controllers/devise/omniauth_callbacks_controller.rb +12 -6
- data/app/controllers/devise/passwords_controller.rb +19 -6
- data/app/controllers/devise/registrations_controller.rb +55 -22
- data/app/controllers/devise/sessions_controller.rb +44 -14
- data/app/controllers/devise/unlocks_controller.rb +7 -2
- data/app/controllers/devise_controller.rb +65 -29
- data/app/helpers/devise_helper.rb +12 -19
- data/app/mailers/devise/mailer.rb +10 -0
- data/app/views/devise/confirmations/new.html.erb +8 -4
- data/app/views/devise/mailer/email_changed.html.erb +7 -0
- data/app/views/devise/mailer/password_change.html.erb +3 -0
- data/app/views/devise/passwords/edit.html.erb +15 -6
- data/app/views/devise/passwords/new.html.erb +8 -4
- data/app/views/devise/registrations/edit.html.erb +27 -13
- data/app/views/devise/registrations/new.html.erb +19 -8
- data/app/views/devise/sessions/new.html.erb +18 -9
- data/app/views/devise/shared/_error_messages.html.erb +15 -0
- data/app/views/devise/shared/{_links.erb → _links.html.erb} +9 -9
- data/app/views/devise/unlocks/new.html.erb +8 -4
- data/config/locales/en.yml +22 -16
- data/lib/devise/controllers/helpers.rb +109 -29
- data/lib/devise/controllers/rememberable.rb +12 -3
- data/lib/devise/controllers/scoped_views.rb +2 -0
- data/lib/devise/controllers/sign_in_out.rb +36 -20
- data/lib/devise/controllers/store_location.rb +31 -5
- data/lib/devise/controllers/url_helpers.rb +9 -7
- data/lib/devise/delegator.rb +2 -0
- data/lib/devise/encryptor.rb +24 -0
- data/lib/devise/failure_app.rb +116 -36
- data/lib/devise/hooks/activatable.rb +5 -4
- data/lib/devise/hooks/csrf_cleaner.rb +5 -1
- data/lib/devise/hooks/forgetable.rb +2 -0
- data/lib/devise/hooks/lockable.rb +6 -1
- data/lib/devise/hooks/proxy.rb +3 -1
- data/lib/devise/hooks/rememberable.rb +2 -0
- data/lib/devise/hooks/timeoutable.rb +15 -8
- data/lib/devise/hooks/trackable.rb +2 -0
- data/lib/devise/mailers/helpers.rb +7 -4
- data/lib/devise/mapping.rb +8 -2
- data/lib/devise/models/authenticatable.rb +76 -51
- data/lib/devise/models/confirmable.rb +129 -34
- data/lib/devise/models/database_authenticatable.rb +107 -30
- data/lib/devise/models/lockable.rb +19 -9
- data/lib/devise/models/omniauthable.rb +2 -0
- data/lib/devise/models/recoverable.rb +62 -26
- data/lib/devise/models/registerable.rb +4 -0
- data/lib/devise/models/rememberable.rb +58 -29
- data/lib/devise/models/timeoutable.rb +2 -6
- data/lib/devise/models/trackable.rb +20 -4
- data/lib/devise/models/validatable.rb +12 -5
- data/lib/devise/models.rb +3 -1
- data/lib/devise/modules.rb +2 -0
- data/lib/devise/omniauth/config.rb +2 -0
- data/lib/devise/omniauth/url_helpers.rb +14 -5
- data/lib/devise/omniauth.rb +2 -0
- data/lib/devise/orm/active_record.rb +5 -1
- data/lib/devise/orm/mongoid.rb +6 -2
- data/lib/devise/parameter_filter.rb +4 -0
- data/lib/devise/parameter_sanitizer.rb +139 -65
- data/lib/devise/rails/routes.rb +80 -61
- data/lib/devise/rails/warden_compat.rb +3 -10
- data/lib/devise/rails.rb +8 -17
- data/lib/devise/secret_key_finder.rb +27 -0
- data/lib/devise/strategies/authenticatable.rb +18 -7
- data/lib/devise/strategies/base.rb +2 -0
- data/lib/devise/strategies/database_authenticatable.rb +13 -5
- data/lib/devise/strategies/rememberable.rb +15 -3
- data/lib/devise/test/controller_helpers.rb +165 -0
- data/lib/devise/test/integration_helpers.rb +63 -0
- data/lib/devise/test_helpers.rb +7 -124
- data/lib/devise/time_inflector.rb +2 -0
- data/lib/devise/token_generator.rb +3 -41
- data/lib/devise/version.rb +3 -1
- data/lib/devise.rb +106 -79
- data/lib/generators/active_record/devise_generator.rb +44 -7
- data/lib/generators/active_record/templates/migration.rb +5 -3
- data/lib/generators/active_record/templates/migration_existing.rb +5 -3
- data/lib/generators/devise/controllers_generator.rb +46 -0
- data/lib/generators/devise/devise_generator.rb +4 -2
- data/lib/generators/devise/install_generator.rb +17 -0
- data/lib/generators/devise/orm_helpers.rb +10 -21
- data/lib/generators/devise/views_generator.rb +21 -11
- data/lib/generators/mongoid/devise_generator.rb +7 -5
- data/lib/generators/templates/README +2 -9
- data/lib/generators/templates/controllers/README +14 -0
- data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
- data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
- data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
- data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
- data/lib/generators/templates/devise.rb +69 -30
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/email_changed.markerb +7 -0
- 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/confirmations/new.html.erb +5 -1
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +4 -1
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +9 -4
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
- metadata +31 -259
- data/.gitignore +0 -11
- data/.travis.yml +0 -28
- data/.yardopts +0 -9
- data/CONTRIBUTING.md +0 -14
- data/Gemfile +0 -29
- data/Gemfile.lock +0 -160
- data/Rakefile +0 -35
- data/devise.gemspec +0 -27
- data/devise.png +0 -0
- data/gemfiles/Gemfile.rails-3.2-stable +0 -29
- data/gemfiles/Gemfile.rails-4.0-stable +0 -29
- data/gemfiles/Gemfile.rails-head +0 -29
- data/test/controllers/custom_strategy_test.rb +0 -62
- data/test/controllers/helpers_test.rb +0 -276
- data/test/controllers/internal_helpers_test.rb +0 -123
- data/test/controllers/passwords_controller_test.rb +0 -31
- data/test/controllers/sessions_controller_test.rb +0 -103
- data/test/controllers/url_helpers_test.rb +0 -59
- data/test/delegator_test.rb +0 -19
- data/test/devise_test.rb +0 -94
- data/test/failure_app_test.rb +0 -232
- data/test/generators/active_record_generator_test.rb +0 -103
- data/test/generators/devise_generator_test.rb +0 -39
- data/test/generators/install_generator_test.rb +0 -13
- data/test/generators/mongoid_generator_test.rb +0 -23
- data/test/generators/views_generator_test.rb +0 -96
- data/test/helpers/devise_helper_test.rb +0 -51
- data/test/integration/authenticatable_test.rb +0 -713
- data/test/integration/confirmable_test.rb +0 -284
- data/test/integration/database_authenticatable_test.rb +0 -84
- data/test/integration/http_authenticatable_test.rb +0 -105
- data/test/integration/lockable_test.rb +0 -239
- data/test/integration/omniauthable_test.rb +0 -133
- data/test/integration/recoverable_test.rb +0 -334
- data/test/integration/registerable_test.rb +0 -349
- data/test/integration/rememberable_test.rb +0 -167
- data/test/integration/timeoutable_test.rb +0 -183
- data/test/integration/trackable_test.rb +0 -92
- data/test/mailers/confirmation_instructions_test.rb +0 -115
- data/test/mailers/reset_password_instructions_test.rb +0 -96
- data/test/mailers/unlock_instructions_test.rb +0 -91
- data/test/mapping_test.rb +0 -127
- data/test/models/authenticatable_test.rb +0 -13
- data/test/models/confirmable_test.rb +0 -454
- data/test/models/database_authenticatable_test.rb +0 -249
- data/test/models/lockable_test.rb +0 -316
- data/test/models/omniauthable_test.rb +0 -7
- data/test/models/recoverable_test.rb +0 -184
- data/test/models/registerable_test.rb +0 -7
- data/test/models/rememberable_test.rb +0 -183
- data/test/models/serializable_test.rb +0 -49
- data/test/models/timeoutable_test.rb +0 -51
- data/test/models/trackable_test.rb +0 -13
- data/test/models/validatable_test.rb +0 -127
- data/test/models_test.rb +0 -144
- data/test/omniauth/config_test.rb +0 -57
- data/test/omniauth/url_helpers_test.rb +0 -54
- data/test/orm/active_record.rb +0 -10
- data/test/orm/mongoid.rb +0 -13
- data/test/parameter_sanitizer_test.rb +0 -81
- data/test/rails_app/Rakefile +0 -6
- data/test/rails_app/app/active_record/admin.rb +0 -6
- data/test/rails_app/app/active_record/shim.rb +0 -2
- data/test/rails_app/app/active_record/user.rb +0 -6
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
- data/test/rails_app/app/controllers/admins_controller.rb +0 -11
- data/test/rails_app/app/controllers/application_controller.rb +0 -9
- data/test/rails_app/app/controllers/home_controller.rb +0 -25
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
- data/test/rails_app/app/controllers/users_controller.rb +0 -31
- data/test/rails_app/app/helpers/application_helper.rb +0 -3
- data/test/rails_app/app/mailers/users/mailer.rb +0 -12
- data/test/rails_app/app/mongoid/admin.rb +0 -29
- data/test/rails_app/app/mongoid/shim.rb +0 -23
- data/test/rails_app/app/mongoid/user.rb +0 -39
- data/test/rails_app/app/views/admins/index.html.erb +0 -1
- data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
- data/test/rails_app/app/views/home/index.html.erb +0 -1
- data/test/rails_app/app/views/home/join.html.erb +0 -1
- data/test/rails_app/app/views/home/private.html.erb +0 -1
- data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
- data/test/rails_app/app/views/layouts/application.html.erb +0 -24
- data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
- data/test/rails_app/app/views/users/index.html.erb +0 -1
- data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
- data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
- data/test/rails_app/bin/bundle +0 -3
- data/test/rails_app/bin/rails +0 -4
- data/test/rails_app/bin/rake +0 -4
- data/test/rails_app/config/application.rb +0 -40
- data/test/rails_app/config/boot.rb +0 -14
- data/test/rails_app/config/database.yml +0 -18
- data/test/rails_app/config/environment.rb +0 -5
- data/test/rails_app/config/environments/development.rb +0 -30
- data/test/rails_app/config/environments/production.rb +0 -80
- data/test/rails_app/config/environments/test.rb +0 -36
- data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/test/rails_app/config/initializers/devise.rb +0 -181
- data/test/rails_app/config/initializers/inflections.rb +0 -2
- data/test/rails_app/config/initializers/secret_token.rb +0 -8
- data/test/rails_app/config/initializers/session_store.rb +0 -1
- data/test/rails_app/config/routes.rb +0 -105
- data/test/rails_app/config.ru +0 -4
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
- data/test/rails_app/db/schema.rb +0 -55
- data/test/rails_app/lib/shared_admin.rb +0 -17
- data/test/rails_app/lib/shared_user.rb +0 -29
- data/test/rails_app/public/404.html +0 -26
- data/test/rails_app/public/422.html +0 -26
- data/test/rails_app/public/500.html +0 -26
- data/test/rails_app/public/favicon.ico +0 -0
- data/test/routes_test.rb +0 -262
- data/test/support/action_controller/record_identifier.rb +0 -10
- data/test/support/assertions.rb +0 -40
- data/test/support/helpers.rb +0 -70
- data/test/support/integration.rb +0 -92
- data/test/support/locale/en.yml +0 -8
- data/test/support/mongoid.yml +0 -6
- data/test/support/webrat/integrations/rails.rb +0 -24
- data/test/test_helper.rb +0 -27
- data/test/test_helpers_test.rb +0 -173
- data/test/test_models.rb +0 -33
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'devise/hooks/trackable'
|
|
2
4
|
|
|
3
5
|
module Devise
|
|
@@ -15,21 +17,35 @@ module Devise
|
|
|
15
17
|
[:current_sign_in_at, :current_sign_in_ip, :last_sign_in_at, :last_sign_in_ip, :sign_in_count]
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
def update_tracked_fields
|
|
20
|
+
def update_tracked_fields(request)
|
|
19
21
|
old_current, new_current = self.current_sign_in_at, Time.now.utc
|
|
20
22
|
self.last_sign_in_at = old_current || new_current
|
|
21
23
|
self.current_sign_in_at = new_current
|
|
22
24
|
|
|
23
|
-
old_current, new_current = self.current_sign_in_ip, request
|
|
25
|
+
old_current, new_current = self.current_sign_in_ip, extract_ip_from(request)
|
|
24
26
|
self.last_sign_in_ip = old_current || new_current
|
|
25
27
|
self.current_sign_in_ip = new_current
|
|
26
28
|
|
|
27
29
|
self.sign_in_count ||= 0
|
|
28
30
|
self.sign_in_count += 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update_tracked_fields!(request)
|
|
34
|
+
# We have to check if the user is already persisted before running
|
|
35
|
+
# `save` here because invalid users can be saved if we don't.
|
|
36
|
+
# See https://github.com/plataformatec/devise/issues/4673 for more details.
|
|
37
|
+
return if new_record?
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
update_tracked_fields(request)
|
|
40
|
+
save(validate: false)
|
|
32
41
|
end
|
|
42
|
+
|
|
43
|
+
protected
|
|
44
|
+
|
|
45
|
+
def extract_ip_from(request)
|
|
46
|
+
request.remote_ip
|
|
47
|
+
end
|
|
48
|
+
|
|
33
49
|
end
|
|
34
50
|
end
|
|
35
51
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
4
|
module Models
|
|
3
5
|
# Validatable creates all needed validations for a user email and password.
|
|
@@ -10,12 +12,12 @@ module Devise
|
|
|
10
12
|
# Validatable adds the following options to devise_for:
|
|
11
13
|
#
|
|
12
14
|
# * +email_regexp+: the regular expression used to validate e-mails;
|
|
13
|
-
# * +password_length+: a range expressing password length. Defaults to
|
|
15
|
+
# * +password_length+: a range expressing password length. Defaults to 6..128.
|
|
14
16
|
#
|
|
15
17
|
module Validatable
|
|
16
18
|
# All validations used by this module.
|
|
17
|
-
VALIDATIONS = [
|
|
18
|
-
|
|
19
|
+
VALIDATIONS = [:validates_presence_of, :validates_uniqueness_of, :validates_format_of,
|
|
20
|
+
:validates_confirmation_of, :validates_length_of].freeze
|
|
19
21
|
|
|
20
22
|
def self.required_fields(klass)
|
|
21
23
|
[]
|
|
@@ -27,8 +29,13 @@ module Devise
|
|
|
27
29
|
|
|
28
30
|
base.class_eval do
|
|
29
31
|
validates_presence_of :email, if: :email_required?
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
if Devise.activerecord51?
|
|
33
|
+
validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :will_save_change_to_email?
|
|
34
|
+
validates_format_of :email, with: email_regexp, allow_blank: true, if: :will_save_change_to_email?
|
|
35
|
+
else
|
|
36
|
+
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
|
|
37
|
+
validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
|
|
38
|
+
end
|
|
32
39
|
|
|
33
40
|
validates_presence_of :password, if: :password_required?
|
|
34
41
|
validates_confirmation_of :password, if: :password_required?
|
data/lib/devise/models.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
4
|
module Models
|
|
3
5
|
class MissingAttribute < StandardError
|
|
@@ -12,7 +14,7 @@ module Devise
|
|
|
12
14
|
|
|
13
15
|
# Creates configuration values for Devise and for the given module.
|
|
14
16
|
#
|
|
15
|
-
# Devise::Models.config(Devise::
|
|
17
|
+
# Devise::Models.config(Devise::Models::DatabaseAuthenticatable, :stretches)
|
|
16
18
|
#
|
|
17
19
|
# The line above creates:
|
|
18
20
|
#
|
data/lib/devise/modules.rb
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
4
|
module OmniAuth
|
|
3
5
|
module UrlHelpers
|
|
4
|
-
def
|
|
6
|
+
def omniauth_authorize_path(resource_or_scope, provider, *args)
|
|
7
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
8
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_path", *args)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def omniauth_authorize_url(resource_or_scope, provider, *args)
|
|
12
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
13
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_url", *args)
|
|
5
14
|
end
|
|
6
15
|
|
|
7
|
-
def
|
|
16
|
+
def omniauth_callback_path(resource_or_scope, provider, *args)
|
|
8
17
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
9
|
-
_devise_route_context.send("#{scope}
|
|
18
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_callback_path", *args)
|
|
10
19
|
end
|
|
11
20
|
|
|
12
|
-
def
|
|
21
|
+
def omniauth_callback_url(resource_or_scope, provider, *args)
|
|
13
22
|
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
|
14
|
-
_devise_route_context.send("#{scope}
|
|
23
|
+
_devise_route_context.send("#{scope}_#{provider}_omniauth_callback_url", *args)
|
|
15
24
|
end
|
|
16
25
|
end
|
|
17
26
|
end
|
data/lib/devise/omniauth.rb
CHANGED
data/lib/devise/orm/mongoid.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ActiveSupport.on_load(:mongoid) do
|
|
4
|
+
require 'orm_adapter/adapters/mongoid'
|
|
5
|
+
|
|
6
|
+
Mongoid::Document::ClassMethods.send :include, Devise::Models
|
|
7
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
4
|
class ParameterFilter
|
|
3
5
|
def initialize(case_insensitive_keys, strip_whitespace_keys)
|
|
@@ -16,6 +18,8 @@ module Devise
|
|
|
16
18
|
|
|
17
19
|
def filtered_hash_by_method_for_given_keys(conditions, method, condition_keys)
|
|
18
20
|
condition_keys.each do |k|
|
|
21
|
+
next unless conditions.key?(k)
|
|
22
|
+
|
|
19
23
|
value = conditions[k]
|
|
20
24
|
conditions[k] = value.send(method) if value.respond_to?(method)
|
|
21
25
|
end
|
|
@@ -1,99 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Devise
|
|
2
|
-
|
|
3
|
-
|
|
4
|
+
# The +ParameterSanitizer+ deals with permitting specific parameters values
|
|
5
|
+
# for each +Devise+ scope in the application.
|
|
6
|
+
#
|
|
7
|
+
# The sanitizer knows about Devise default parameters (like +password+ and
|
|
8
|
+
# +password_confirmation+ for the `RegistrationsController`), and you can
|
|
9
|
+
# extend or change the permitted parameters list on your controllers.
|
|
10
|
+
#
|
|
11
|
+
# === Permitting new parameters
|
|
12
|
+
#
|
|
13
|
+
# You can add new parameters to the permitted list using the +permit+ method
|
|
14
|
+
# in a +before_action+ method, for instance.
|
|
15
|
+
#
|
|
16
|
+
# class ApplicationController < ActionController::Base
|
|
17
|
+
# before_action :configure_permitted_parameters, if: :devise_controller?
|
|
18
|
+
#
|
|
19
|
+
# protected
|
|
20
|
+
#
|
|
21
|
+
# def configure_permitted_parameters
|
|
22
|
+
# # Permit the `subscribe_newsletter` parameter along with the other
|
|
23
|
+
# # sign up parameters.
|
|
24
|
+
# devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# Using a block yields an +ActionController::Parameters+ object so you can
|
|
29
|
+
# permit nested parameters and have more control over how the parameters are
|
|
30
|
+
# permitted in your controller.
|
|
31
|
+
#
|
|
32
|
+
# def configure_permitted_parameters
|
|
33
|
+
# devise_parameter_sanitizer.permit(:sign_up) do |user|
|
|
34
|
+
# user.permit(newsletter_preferences: [])
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
37
|
+
class ParameterSanitizer
|
|
38
|
+
DEFAULT_PERMITTED_ATTRIBUTES = {
|
|
39
|
+
sign_in: [:password, :remember_me],
|
|
40
|
+
sign_up: [:password, :password_confirmation],
|
|
41
|
+
account_update: [:password, :password_confirmation, :current_password]
|
|
42
|
+
}
|
|
4
43
|
|
|
5
44
|
def initialize(resource_class, resource_name, params)
|
|
6
|
-
@
|
|
7
|
-
@resource_name = resource_name
|
|
45
|
+
@auth_keys = extract_auth_keys(resource_class)
|
|
8
46
|
@params = params
|
|
9
|
-
@
|
|
10
|
-
|
|
47
|
+
@resource_name = resource_name
|
|
48
|
+
@permitted = {}
|
|
11
49
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@blocks[kind] = block
|
|
15
|
-
else
|
|
16
|
-
default_for(kind)
|
|
50
|
+
DEFAULT_PERMITTED_ATTRIBUTES.each_pair do |action, keys|
|
|
51
|
+
permit(action, keys: keys)
|
|
17
52
|
end
|
|
18
53
|
end
|
|
19
54
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
55
|
+
# Sanitize the parameters for a specific +action+.
|
|
56
|
+
#
|
|
57
|
+
# === Arguments
|
|
58
|
+
#
|
|
59
|
+
# * +action+ - A +Symbol+ with the action that the controller is
|
|
60
|
+
# performing, like +sign_up+, +sign_in+, etc.
|
|
61
|
+
#
|
|
62
|
+
# === Examples
|
|
63
|
+
#
|
|
64
|
+
# # Inside the `RegistrationsController#create` action.
|
|
65
|
+
# resource = build_resource(devise_parameter_sanitizer.sanitize(:sign_up))
|
|
66
|
+
# resource.save
|
|
67
|
+
#
|
|
68
|
+
# Returns an +ActiveSupport::HashWithIndifferentAccess+ with the permitted
|
|
69
|
+
# attributes.
|
|
70
|
+
def sanitize(action)
|
|
71
|
+
permissions = @permitted[action]
|
|
72
|
+
|
|
73
|
+
if permissions.respond_to?(:call)
|
|
74
|
+
cast_to_hash permissions.call(default_params)
|
|
75
|
+
elsif permissions.present?
|
|
76
|
+
cast_to_hash permit_keys(default_params, permissions)
|
|
23
77
|
else
|
|
24
|
-
|
|
78
|
+
unknown_action!(action)
|
|
25
79
|
end
|
|
26
80
|
end
|
|
27
81
|
|
|
28
|
-
|
|
82
|
+
# Add or remove new parameters to the permitted list of an +action+.
|
|
83
|
+
#
|
|
84
|
+
# === Arguments
|
|
85
|
+
#
|
|
86
|
+
# * +action+ - A +Symbol+ with the action that the controller is
|
|
87
|
+
# performing, like +sign_up+, +sign_in+, etc.
|
|
88
|
+
# * +keys:+ - An +Array+ of keys that also should be permitted.
|
|
89
|
+
# * +except:+ - An +Array+ of keys that shouldn't be permitted.
|
|
90
|
+
# * +block+ - A block that should be used to permit the action
|
|
91
|
+
# parameters instead of the +Array+ based approach. The block will be
|
|
92
|
+
# called with an +ActionController::Parameters+ instance.
|
|
93
|
+
#
|
|
94
|
+
# === Examples
|
|
95
|
+
#
|
|
96
|
+
# # Adding new parameters to be permitted in the `sign_up` action.
|
|
97
|
+
# devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
|
|
98
|
+
#
|
|
99
|
+
# # Removing the `password` parameter from the `account_update` action.
|
|
100
|
+
# devise_parameter_sanitizer.permit(:account_update, except: [:password])
|
|
101
|
+
#
|
|
102
|
+
# # Using the block form to completely override how we permit the
|
|
103
|
+
# # parameters for the `sign_up` action.
|
|
104
|
+
# devise_parameter_sanitizer.permit(:sign_up) do |user|
|
|
105
|
+
# user.permit(:email, :password, :password_confirmation)
|
|
106
|
+
# end
|
|
107
|
+
#
|
|
108
|
+
#
|
|
109
|
+
# Returns nothing.
|
|
110
|
+
def permit(action, keys: nil, except: nil, &block)
|
|
111
|
+
if block_given?
|
|
112
|
+
@permitted[action] = block
|
|
113
|
+
end
|
|
29
114
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
115
|
+
if keys.present?
|
|
116
|
+
@permitted[action] ||= @auth_keys.dup
|
|
117
|
+
@permitted[action].concat(keys)
|
|
118
|
+
end
|
|
33
119
|
|
|
34
|
-
|
|
35
|
-
|
|
120
|
+
if except.present?
|
|
121
|
+
@permitted[action] ||= @auth_keys.dup
|
|
122
|
+
@permitted[action] = @permitted[action] - except
|
|
123
|
+
end
|
|
36
124
|
end
|
|
37
125
|
|
|
38
|
-
|
|
39
|
-
params.fetch(resource_name, {})
|
|
40
|
-
end
|
|
41
|
-
end
|
|
126
|
+
private
|
|
42
127
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
128
|
+
# Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
|
|
129
|
+
# that can be used elsewhere.
|
|
130
|
+
#
|
|
131
|
+
# Returns an +ActiveSupport::HashWithIndifferentAccess+.
|
|
132
|
+
def cast_to_hash(params)
|
|
133
|
+
# TODO: Remove the `with_indifferent_access` method call when we only support Rails 5+.
|
|
134
|
+
params && params.to_h.with_indifferent_access
|
|
47
135
|
end
|
|
48
136
|
|
|
49
|
-
def
|
|
50
|
-
|
|
137
|
+
def default_params
|
|
138
|
+
if hashable_resource_params?
|
|
139
|
+
@params.fetch(@resource_name)
|
|
140
|
+
else
|
|
141
|
+
empty_params
|
|
142
|
+
end
|
|
51
143
|
end
|
|
52
144
|
|
|
53
|
-
def
|
|
54
|
-
|
|
145
|
+
def hashable_resource_params?
|
|
146
|
+
@params[@resource_name].respond_to?(:permit)
|
|
55
147
|
end
|
|
56
148
|
|
|
57
|
-
def
|
|
58
|
-
|
|
149
|
+
def empty_params
|
|
150
|
+
ActionController::Parameters.new({})
|
|
59
151
|
end
|
|
60
152
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# TODO: We do need to flatten so it works with strong_parameters
|
|
64
|
-
# gem. We should drop it once we move to Rails 4 only support.
|
|
65
|
-
def permit(keys)
|
|
66
|
-
default_params.permit(*Array(keys))
|
|
153
|
+
def permit_keys(parameters, keys)
|
|
154
|
+
parameters.permit(*keys)
|
|
67
155
|
end
|
|
68
156
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def default_for(kind)
|
|
72
|
-
@permitted[kind] || raise("No sanitizer provided for #{kind}")
|
|
73
|
-
end
|
|
157
|
+
def extract_auth_keys(klass)
|
|
158
|
+
auth_keys = klass.authentication_keys
|
|
74
159
|
|
|
75
|
-
|
|
76
|
-
if respond_to?(kind, true)
|
|
77
|
-
send(kind)
|
|
78
|
-
else
|
|
79
|
-
raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
|
|
80
|
-
end
|
|
160
|
+
auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
|
|
81
161
|
end
|
|
82
162
|
|
|
83
|
-
def
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
auth_keys + [:password, :password_confirmation]
|
|
89
|
-
when :account_update
|
|
90
|
-
auth_keys + [:password, :password_confirmation, :current_password]
|
|
91
|
-
end
|
|
92
|
-
end
|
|
163
|
+
def unknown_action!(action)
|
|
164
|
+
raise NotImplementedError, <<-MESSAGE.strip_heredoc
|
|
165
|
+
"Devise doesn't know how to sanitize parameters for '#{action}'".
|
|
166
|
+
If you want to define a new set of parameters to be sanitized use the
|
|
167
|
+
`permit` method first:
|
|
93
168
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
@resource_class.authentication_keys.keys : @resource_class.authentication_keys
|
|
169
|
+
devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
|
|
170
|
+
MESSAGE
|
|
97
171
|
end
|
|
98
172
|
end
|
|
99
173
|
end
|
data/lib/devise/rails/routes.rb
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "active_support/core_ext/object/try"
|
|
2
4
|
require "active_support/core_ext/hash/slice"
|
|
3
5
|
|
|
4
|
-
module
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def finalize_with_devise!
|
|
9
|
-
result = finalize_without_devise!
|
|
10
|
-
|
|
6
|
+
module Devise
|
|
7
|
+
module RouteSet
|
|
8
|
+
def finalize!
|
|
9
|
+
result = super
|
|
11
10
|
@devise_finalized ||= begin
|
|
12
11
|
if Devise.router_name.nil? && defined?(@devise_finalized) && self != Rails.application.try(:routes)
|
|
13
12
|
warn "[DEVISE] We have detected that you are using devise_for inside engine routes. " \
|
|
@@ -21,10 +20,16 @@ module ActionDispatch::Routing
|
|
|
21
20
|
Devise.regenerate_helpers!
|
|
22
21
|
true
|
|
23
22
|
end
|
|
24
|
-
|
|
25
23
|
result
|
|
26
24
|
end
|
|
27
|
-
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module ActionDispatch::Routing
|
|
29
|
+
class RouteSet #:nodoc:
|
|
30
|
+
# Ensure Devise modules are included only after loading routes, because we
|
|
31
|
+
# need devise_for mappings already declared to create filters and helpers.
|
|
32
|
+
prepend Devise::RouteSet
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
class Mapper
|
|
@@ -84,20 +89,34 @@ module ActionDispatch::Routing
|
|
|
84
89
|
#
|
|
85
90
|
# You can configure your routes with some options:
|
|
86
91
|
#
|
|
87
|
-
# * class_name:
|
|
92
|
+
# * class_name: set up a different class to be looked up by devise, if it cannot be
|
|
88
93
|
# properly found by the route name.
|
|
89
94
|
#
|
|
90
95
|
# devise_for :users, class_name: 'Account'
|
|
91
96
|
#
|
|
92
|
-
# * path: allows you to
|
|
93
|
-
# The following route configuration would
|
|
97
|
+
# * path: allows you to set up path name that will be used, as rails routes does.
|
|
98
|
+
# The following route configuration would set up your route as /accounts instead of /users:
|
|
94
99
|
#
|
|
95
100
|
# devise_for :users, path: 'accounts'
|
|
96
101
|
#
|
|
97
|
-
# * singular:
|
|
98
|
-
#
|
|
102
|
+
# * singular: set up the singular name for the given resource. This is used as the helper methods
|
|
103
|
+
# names in controller ("authenticate_#{singular}!", "#{singular}_signed_in?", "current_#{singular}"
|
|
104
|
+
# and "#{singular}_session"), as the scope name in routes and as the scope given to warden.
|
|
99
105
|
#
|
|
100
|
-
# devise_for :
|
|
106
|
+
# devise_for :admins, singular: :manager
|
|
107
|
+
#
|
|
108
|
+
# devise_scope :manager do
|
|
109
|
+
# ...
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# class ManagerController < ApplicationController
|
|
113
|
+
# before_action authenticate_manager!
|
|
114
|
+
#
|
|
115
|
+
# def show
|
|
116
|
+
# @manager = current_manager
|
|
117
|
+
# ...
|
|
118
|
+
# end
|
|
119
|
+
# end
|
|
101
120
|
#
|
|
102
121
|
# * path_names: configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
|
|
103
122
|
# :password, :confirmation, :unlock.
|
|
@@ -116,10 +135,10 @@ module ActionDispatch::Routing
|
|
|
116
135
|
# * failure_app: a rack app which is invoked whenever there is a failure. Strings representing a given
|
|
117
136
|
# are also allowed as parameter.
|
|
118
137
|
#
|
|
119
|
-
# * sign_out_via: the HTTP method(s) accepted for the :sign_out action (default: :
|
|
138
|
+
# * sign_out_via: the HTTP method(s) accepted for the :sign_out action (default: :delete),
|
|
120
139
|
# if you wish to restrict this to accept only :post or :delete requests you should do:
|
|
121
140
|
#
|
|
122
|
-
# devise_for :users, sign_out_via: [
|
|
141
|
+
# devise_for :users, sign_out_via: [:get, :post]
|
|
123
142
|
#
|
|
124
143
|
# You need to make sure that your sign_out controls trigger a request with a matching HTTP method.
|
|
125
144
|
#
|
|
@@ -129,7 +148,8 @@ module ActionDispatch::Routing
|
|
|
129
148
|
#
|
|
130
149
|
# devise_for :users, module: "users"
|
|
131
150
|
#
|
|
132
|
-
# * skip: tell which controller you want to skip routes from being created
|
|
151
|
+
# * skip: tell which controller you want to skip routes from being created.
|
|
152
|
+
# It accepts :all as an option, meaning it will not generate any route at all:
|
|
133
153
|
#
|
|
134
154
|
# devise_for :users, skip: :sessions
|
|
135
155
|
#
|
|
@@ -153,6 +173,8 @@ module ActionDispatch::Routing
|
|
|
153
173
|
#
|
|
154
174
|
# * defaults: works the same as Rails' defaults
|
|
155
175
|
#
|
|
176
|
+
# * router_name: allows application level router name to be overwritten for the current scope
|
|
177
|
+
#
|
|
156
178
|
# ==== Scoping
|
|
157
179
|
#
|
|
158
180
|
# Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:
|
|
@@ -224,7 +246,7 @@ module ActionDispatch::Routing
|
|
|
224
246
|
raise_no_devise_method_error!(mapping.class_name) unless mapping.to.respond_to?(:devise)
|
|
225
247
|
rescue NameError => e
|
|
226
248
|
raise unless mapping.class_name == resource.to_s.classify
|
|
227
|
-
warn "[WARNING] You provided devise_for #{resource.inspect} but there is "
|
|
249
|
+
warn "[WARNING] You provided devise_for #{resource.inspect} but there is " \
|
|
228
250
|
"no model #{mapping.class_name} defined in your application"
|
|
229
251
|
next
|
|
230
252
|
rescue NoMethodError => e
|
|
@@ -234,13 +256,12 @@ module ActionDispatch::Routing
|
|
|
234
256
|
|
|
235
257
|
if options[:controllers] && options[:controllers][:omniauth_callbacks]
|
|
236
258
|
unless mapping.omniauthable?
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
raise msg
|
|
259
|
+
raise ArgumentError, "Mapping omniauth_callbacks on a resource that is not omniauthable\n" \
|
|
260
|
+
"Please add `devise :omniauthable` to the `#{mapping.class_name}` model"
|
|
240
261
|
end
|
|
241
262
|
end
|
|
242
263
|
|
|
243
|
-
routes
|
|
264
|
+
routes = mapping.used_routes
|
|
244
265
|
|
|
245
266
|
devise_scope mapping.name do
|
|
246
267
|
with_devise_exclusive_scope mapping.fullpath, mapping.name, options do
|
|
@@ -319,7 +340,7 @@ module ActionDispatch::Routing
|
|
|
319
340
|
|
|
320
341
|
# Sets the devise scope to be used in the controller. If you have custom routes,
|
|
321
342
|
# you are required to call this method (also aliased as :as) in order to specify
|
|
322
|
-
# to which controller it is
|
|
343
|
+
# to which controller it is targeted.
|
|
323
344
|
#
|
|
324
345
|
# as :user do
|
|
325
346
|
# get "sign_in", to: "devise/sessions#new"
|
|
@@ -400,59 +421,57 @@ module ActionDispatch::Routing
|
|
|
400
421
|
def devise_omniauth_callback(mapping, controllers) #:nodoc:
|
|
401
422
|
if mapping.fullpath =~ /:[a-zA-Z_]/
|
|
402
423
|
raise <<-ERROR
|
|
403
|
-
Devise does not support scoping
|
|
424
|
+
Devise does not support scoping OmniAuth callbacks under a dynamic segment
|
|
404
425
|
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]
|
|
426
|
+
`skip: :omniauth_callbacks` to the `devise_for` call and extract omniauth
|
|
427
|
+
options to another `devise_for` call outside the scope. Here is an example:
|
|
428
|
+
|
|
429
|
+
devise_for :users, only: :omniauth_callbacks, controllers: {omniauth_callbacks: 'users/omniauth_callbacks'}
|
|
430
|
+
|
|
431
|
+
scope '/(:locale)', locale: /ru|en/ do
|
|
432
|
+
devise_for :users, skip: :omniauth_callbacks
|
|
433
|
+
end
|
|
418
434
|
ERROR
|
|
419
435
|
end
|
|
420
|
-
|
|
421
|
-
|
|
436
|
+
current_scope = @scope.dup
|
|
437
|
+
if @scope.respond_to? :new
|
|
438
|
+
@scope = @scope.new path: nil
|
|
439
|
+
else
|
|
440
|
+
@scope[:path] = nil
|
|
441
|
+
end
|
|
422
442
|
path_prefix = Devise.omniauth_path_prefix || "/#{mapping.fullpath}/auth".squeeze("/")
|
|
423
443
|
|
|
424
444
|
set_omniauth_path_prefix!(path_prefix)
|
|
425
445
|
|
|
426
|
-
|
|
446
|
+
mapping.to.omniauth_providers.each do |provider|
|
|
447
|
+
match "#{path_prefix}/#{provider}",
|
|
448
|
+
to: "#{controllers[:omniauth_callbacks]}#passthru",
|
|
449
|
+
as: "#{provider}_omniauth_authorize",
|
|
450
|
+
via: [:get, :post]
|
|
427
451
|
|
|
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]
|
|
452
|
+
match "#{path_prefix}/#{provider}/callback",
|
|
453
|
+
to: "#{controllers[:omniauth_callbacks]}##{provider}",
|
|
454
|
+
as: "#{provider}_omniauth_callback",
|
|
455
|
+
via: [:get, :post]
|
|
456
|
+
end
|
|
439
457
|
ensure
|
|
440
|
-
@scope
|
|
458
|
+
@scope = current_scope
|
|
441
459
|
end
|
|
442
460
|
|
|
443
|
-
DEVISE_SCOPE_KEYS = [:as, :path, :module, :constraints, :defaults, :options]
|
|
444
|
-
|
|
445
461
|
def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
|
|
446
|
-
|
|
447
|
-
DEVISE_SCOPE_KEYS.each { |k| old[k] = @scope[k] }
|
|
462
|
+
current_scope = @scope.dup
|
|
448
463
|
|
|
449
|
-
|
|
450
|
-
|
|
464
|
+
exclusive = { as: new_as, path: new_path, module: nil }
|
|
465
|
+
exclusive.merge!(options.slice(:constraints, :defaults, :options))
|
|
451
466
|
|
|
452
|
-
@scope.
|
|
467
|
+
if @scope.respond_to? :new
|
|
468
|
+
@scope = @scope.new exclusive
|
|
469
|
+
else
|
|
470
|
+
exclusive.each_pair { |key, value| @scope[key] = value }
|
|
471
|
+
end
|
|
453
472
|
yield
|
|
454
473
|
ensure
|
|
455
|
-
@scope
|
|
474
|
+
@scope = current_scope
|
|
456
475
|
end
|
|
457
476
|
|
|
458
477
|
def constraints_for(method_to_apply, scope=nil, block=nil)
|