devise 4.3.0 → 4.9.2
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 +205 -2
- data/MIT-LICENSE +2 -1
- data/README.md +214 -57
- data/app/controllers/devise/confirmations_controller.rb +3 -0
- data/app/controllers/devise/omniauth_callbacks_controller.rb +3 -1
- data/app/controllers/devise/passwords_controller.rb +5 -2
- data/app/controllers/devise/registrations_controller.rb +32 -12
- data/app/controllers/devise/sessions_controller.rb +4 -2
- data/app/controllers/devise/unlocks_controller.rb +3 -0
- data/app/controllers/devise_controller.rb +6 -3
- data/app/helpers/devise_helper.rb +23 -18
- data/app/mailers/devise/mailer.rb +7 -5
- data/app/views/devise/confirmations/new.html.erb +2 -2
- data/app/views/devise/passwords/edit.html.erb +3 -3
- data/app/views/devise/passwords/new.html.erb +2 -2
- data/app/views/devise/registrations/edit.html.erb +6 -6
- data/app/views/devise/registrations/new.html.erb +4 -4
- data/app/views/devise/sessions/new.html.erb +4 -4
- data/app/views/devise/shared/_error_messages.html.erb +15 -0
- data/app/views/devise/shared/_links.html.erb +8 -8
- data/app/views/devise/unlocks/new.html.erb +2 -2
- data/config/locales/en.yml +3 -2
- data/lib/devise/controllers/helpers.rb +10 -8
- data/lib/devise/controllers/rememberable.rb +2 -0
- data/lib/devise/controllers/responder.rb +35 -0
- data/lib/devise/controllers/scoped_views.rb +2 -0
- data/lib/devise/controllers/sign_in_out.rb +14 -4
- data/lib/devise/controllers/store_location.rb +24 -6
- data/lib/devise/controllers/url_helpers.rb +3 -1
- data/lib/devise/delegator.rb +2 -0
- data/lib/devise/encryptor.rb +2 -0
- data/lib/devise/failure_app.rb +33 -7
- data/lib/devise/hooks/activatable.rb +2 -0
- data/lib/devise/hooks/csrf_cleaner.rb +8 -1
- data/lib/devise/hooks/forgetable.rb +2 -0
- data/lib/devise/hooks/lockable.rb +4 -5
- data/lib/devise/hooks/proxy.rb +2 -0
- data/lib/devise/hooks/rememberable.rb +2 -0
- data/lib/devise/hooks/timeoutable.rb +4 -2
- data/lib/devise/hooks/trackable.rb +2 -0
- data/lib/devise/mailers/helpers.rb +2 -0
- data/lib/devise/mapping.rb +3 -1
- data/lib/devise/models/authenticatable.rb +55 -50
- data/lib/devise/models/confirmable.rb +36 -40
- data/lib/devise/models/database_authenticatable.rb +57 -36
- data/lib/devise/models/lockable.rb +18 -4
- data/lib/devise/models/omniauthable.rb +4 -2
- data/lib/devise/models/recoverable.rb +10 -19
- data/lib/devise/models/registerable.rb +4 -0
- data/lib/devise/models/rememberable.rb +5 -3
- data/lib/devise/models/timeoutable.rb +3 -1
- data/lib/devise/models/trackable.rb +15 -1
- data/lib/devise/models/validatable.rb +7 -10
- data/lib/devise/models.rb +3 -0
- data/lib/devise/modules.rb +2 -0
- data/lib/devise/omniauth/config.rb +2 -0
- data/lib/devise/omniauth/url_helpers.rb +2 -0
- data/lib/devise/omniauth.rb +4 -5
- data/lib/devise/orm/active_record.rb +2 -0
- data/lib/devise/orm/mongoid.rb +2 -0
- data/lib/devise/orm.rb +71 -0
- data/lib/devise/parameter_filter.rb +4 -0
- data/lib/devise/parameter_sanitizer.rb +15 -1
- data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
- data/lib/devise/rails/routes.rb +8 -6
- data/lib/devise/rails/warden_compat.rb +2 -0
- data/lib/devise/rails.rb +3 -5
- data/lib/devise/secret_key_finder.rb +27 -0
- data/lib/devise/strategies/authenticatable.rb +3 -1
- data/lib/devise/strategies/base.rb +2 -0
- data/lib/devise/strategies/database_authenticatable.rb +8 -1
- data/lib/devise/strategies/rememberable.rb +2 -0
- data/lib/devise/test/controller_helpers.rb +6 -1
- data/lib/devise/test/integration_helpers.rb +3 -1
- data/lib/devise/test_helpers.rb +2 -0
- data/lib/devise/time_inflector.rb +2 -0
- data/lib/devise/token_generator.rb +2 -0
- data/lib/devise/version.rb +3 -1
- data/lib/devise.rb +38 -12
- data/lib/generators/active_record/devise_generator.rb +40 -12
- data/lib/generators/active_record/templates/migration.rb +3 -1
- data/lib/generators/active_record/templates/migration_existing.rb +2 -0
- data/lib/generators/devise/controllers_generator.rb +3 -1
- data/lib/generators/devise/devise_generator.rb +5 -3
- data/lib/generators/devise/install_generator.rb +3 -5
- data/lib/generators/devise/orm_helpers.rb +9 -3
- data/lib/generators/devise/views_generator.rb +8 -9
- data/lib/generators/mongoid/devise_generator.rb +7 -5
- data/lib/generators/templates/README +9 -1
- data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
- data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +3 -1
- data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
- data/lib/generators/templates/controllers/registrations_controller.rb +2 -0
- data/lib/generators/templates/controllers/sessions_controller.rb +2 -0
- data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
- data/lib/generators/templates/devise.rb +43 -7
- 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 +12 -4
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
- metadata +24 -307
- data/.gitignore +0 -10
- data/.travis.yml +0 -58
- data/.yardopts +0 -9
- data/CODE_OF_CONDUCT.md +0 -22
- data/CONTRIBUTING.md +0 -79
- data/Gemfile +0 -40
- data/Gemfile.lock +0 -194
- data/Rakefile +0 -36
- data/bin/test +0 -13
- data/devise.gemspec +0 -26
- data/devise.png +0 -0
- data/gemfiles/Gemfile.rails-4.1-stable +0 -30
- data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -171
- data/gemfiles/Gemfile.rails-4.2-stable +0 -30
- data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
- data/gemfiles/Gemfile.rails-5.0-stable +0 -34
- data/gemfiles/Gemfile.rails-5.0-stable.lock +0 -193
- data/guides/bug_report_templates/integration_test.rb +0 -104
- data/test/controllers/custom_registrations_controller_test.rb +0 -40
- data/test/controllers/custom_strategy_test.rb +0 -64
- data/test/controllers/helper_methods_test.rb +0 -22
- data/test/controllers/helpers_test.rb +0 -316
- data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -51
- data/test/controllers/internal_helpers_test.rb +0 -127
- data/test/controllers/load_hooks_controller_test.rb +0 -19
- data/test/controllers/passwords_controller_test.rb +0 -32
- data/test/controllers/sessions_controller_test.rb +0 -106
- data/test/controllers/url_helpers_test.rb +0 -65
- data/test/delegator_test.rb +0 -19
- data/test/devise_test.rb +0 -107
- data/test/failure_app_test.rb +0 -338
- data/test/generators/active_record_generator_test.rb +0 -83
- data/test/generators/controllers_generator_test.rb +0 -48
- data/test/generators/devise_generator_test.rb +0 -39
- data/test/generators/install_generator_test.rb +0 -24
- data/test/generators/mongoid_generator_test.rb +0 -23
- data/test/generators/views_generator_test.rb +0 -103
- data/test/helpers/devise_helper_test.rb +0 -49
- data/test/integration/authenticatable_test.rb +0 -698
- data/test/integration/confirmable_test.rb +0 -324
- data/test/integration/database_authenticatable_test.rb +0 -95
- data/test/integration/http_authenticatable_test.rb +0 -106
- data/test/integration/lockable_test.rb +0 -240
- data/test/integration/mounted_engine_test.rb +0 -36
- data/test/integration/omniauthable_test.rb +0 -135
- data/test/integration/recoverable_test.rb +0 -347
- data/test/integration/registerable_test.rb +0 -363
- data/test/integration/rememberable_test.rb +0 -217
- data/test/integration/timeoutable_test.rb +0 -184
- data/test/integration/trackable_test.rb +0 -92
- data/test/mailers/confirmation_instructions_test.rb +0 -115
- data/test/mailers/email_changed_test.rb +0 -130
- data/test/mailers/mailer_test.rb +0 -18
- 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 -134
- data/test/models/authenticatable_test.rb +0 -23
- data/test/models/confirmable_test.rb +0 -536
- data/test/models/database_authenticatable_test.rb +0 -281
- data/test/models/lockable_test.rb +0 -350
- data/test/models/omniauthable_test.rb +0 -7
- data/test/models/recoverable_test.rb +0 -261
- data/test/models/registerable_test.rb +0 -7
- data/test/models/rememberable_test.rb +0 -182
- data/test/models/serializable_test.rb +0 -54
- data/test/models/timeoutable_test.rb +0 -51
- data/test/models/trackable_test.rb +0 -41
- data/test/models/validatable_test.rb +0 -119
- data/test/models_test.rb +0 -153
- data/test/omniauth/config_test.rb +0 -59
- data/test/omniauth/url_helpers_test.rb +0 -51
- data/test/orm/active_record.rb +0 -17
- data/test/orm/mongoid.rb +0 -13
- data/test/parameter_sanitizer_test.rb +0 -75
- 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 -7
- data/test/rails_app/app/active_record/user_on_engine.rb +0 -7
- data/test/rails_app/app/active_record/user_on_main_app.rb +0 -7
- data/test/rails_app/app/active_record/user_without_email.rb +0 -8
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
- data/test/rails_app/app/controllers/admins_controller.rb +0 -6
- data/test/rails_app/app/controllers/application_controller.rb +0 -11
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -30
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -31
- data/test/rails_app/app/controllers/home_controller.rb +0 -29
- 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/from_proc_mailer.rb +0 -3
- data/test/rails_app/app/mailers/users/mailer.rb +0 -3
- data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -4
- 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/mongoid/user_on_engine.rb +0 -39
- data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -39
- data/test/rails_app/app/mongoid/user_without_email.rb +0 -33
- 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 -44
- data/test/rails_app/config/boot.rb +0 -20
- 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 -86
- data/test/rails_app/config/environments/test.rb +0 -45
- data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/test/rails_app/config/initializers/devise.rb +0 -180
- data/test/rails_app/config/initializers/inflections.rb +0 -2
- data/test/rails_app/config/initializers/secret_token.rb +0 -3
- data/test/rails_app/config/initializers/session_store.rb +0 -1
- data/test/rails_app/config/routes.rb +0 -126
- data/test/rails_app/config.ru +0 -4
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -75
- data/test/rails_app/db/schema.rb +0 -55
- data/test/rails_app/lib/shared_admin.rb +0 -21
- data/test/rails_app/lib/shared_user.rb +0 -30
- data/test/rails_app/lib/shared_user_without_email.rb +0 -26
- data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -13
- 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/rails_test.rb +0 -9
- data/test/routes_test.rb +0 -279
- data/test/support/action_controller/record_identifier.rb +0 -10
- data/test/support/assertions.rb +0 -28
- data/test/support/helpers.rb +0 -77
- data/test/support/http_method_compatibility.rb +0 -51
- 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 -33
- data/test/test/controller_helpers_test.rb +0 -186
- data/test/test/integration_helpers_test.rb +0 -32
- data/test/test_helper.rb +0 -34
- data/test/test_models.rb +0 -33
data/lib/devise/failure_app.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_controller/metal"
|
2
4
|
|
3
5
|
module Devise
|
@@ -69,8 +71,11 @@ module Devise
|
|
69
71
|
end
|
70
72
|
|
71
73
|
flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
|
72
|
-
|
73
|
-
|
74
|
+
self.response = recall_app(warden_options[:recall]).call(request.env).tap { |response|
|
75
|
+
response[0] = Rack::Utils.status_code(
|
76
|
+
response[0].in?(300..399) ? Devise.responder.redirect_status : Devise.responder.error_status
|
77
|
+
)
|
78
|
+
}
|
74
79
|
end
|
75
80
|
|
76
81
|
def redirect
|
@@ -105,7 +110,7 @@ module Devise
|
|
105
110
|
options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
|
106
111
|
options = i18n_options(options)
|
107
112
|
|
108
|
-
I18n.t(:"#{scope}.#{message}", options)
|
113
|
+
I18n.t(:"#{scope}.#{message}", **options)
|
109
114
|
else
|
110
115
|
message.to_s
|
111
116
|
end
|
@@ -142,11 +147,20 @@ module Devise
|
|
142
147
|
|
143
148
|
opts[:format] = request_format unless skip_format?
|
144
149
|
|
145
|
-
opts[:script_name] = relative_url_root if relative_url_root?
|
146
|
-
|
147
150
|
router_name = Devise.mappings[scope].router_name || Devise.available_router_name
|
148
151
|
context = send(router_name)
|
149
152
|
|
153
|
+
if relative_url_root?
|
154
|
+
opts[:script_name] = relative_url_root
|
155
|
+
|
156
|
+
# We need to add the rootpath to `script_name` manually for applications that use a Rails
|
157
|
+
# version lower than 5.1. Otherwise, it is going to generate a wrong path for Engines
|
158
|
+
# that use Devise. Remove it when the support of Rails 5.0 is dropped.
|
159
|
+
elsif root_path_defined?(context) && !rails_51_and_up?
|
160
|
+
rootpath = context.routes.url_helpers.root_path
|
161
|
+
opts[:script_name] = rootpath.chomp('/') if rootpath.length > 1
|
162
|
+
end
|
163
|
+
|
150
164
|
if context.respond_to?(route)
|
151
165
|
context.send(route, opts)
|
152
166
|
elsif respond_to?(:root_url)
|
@@ -157,7 +171,7 @@ module Devise
|
|
157
171
|
end
|
158
172
|
|
159
173
|
def skip_format?
|
160
|
-
%w(html */*).include? request_format.to_s
|
174
|
+
%w(html */* turbo_stream).include? request_format.to_s
|
161
175
|
end
|
162
176
|
|
163
177
|
# Choose whether we should respond in an HTTP authentication fashion,
|
@@ -240,7 +254,7 @@ module Devise
|
|
240
254
|
# Check if flash messages should be emitted. Default is to do it on
|
241
255
|
# navigational formats
|
242
256
|
def is_flashing_format?
|
243
|
-
is_navigational_format?
|
257
|
+
request.respond_to?(:flash) && is_navigational_format?
|
244
258
|
end
|
245
259
|
|
246
260
|
def request_format
|
@@ -258,5 +272,17 @@ module Devise
|
|
258
272
|
def relative_url_root?
|
259
273
|
relative_url_root.present?
|
260
274
|
end
|
275
|
+
|
276
|
+
ActiveSupport.run_load_hooks(:devise_failure_app, self)
|
277
|
+
|
278
|
+
private
|
279
|
+
|
280
|
+
def root_path_defined?(context)
|
281
|
+
defined?(context.routes) && context.routes.url_helpers.respond_to?(:root_path)
|
282
|
+
end
|
283
|
+
|
284
|
+
def rails_51_and_up?
|
285
|
+
Rails.gem_version >= Gem::Version.new("5.1")
|
286
|
+
end
|
261
287
|
end
|
262
288
|
end
|
@@ -1,7 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Warden::Manager.after_authentication do |record, warden, options|
|
2
4
|
clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
|
3
5
|
warden.winning_strategy.clean_up_csrf?
|
4
6
|
if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
|
5
|
-
warden.request.
|
7
|
+
if warden.request.respond_to?(:reset_csrf_token)
|
8
|
+
# Rails 7.1+
|
9
|
+
warden.request.reset_csrf_token
|
10
|
+
else
|
11
|
+
warden.request.session.try(:delete, :_csrf_token)
|
12
|
+
end
|
6
13
|
end
|
7
14
|
end
|
@@ -1,10 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# After each sign in, if resource responds to failed_attempts, sets it to 0
|
2
4
|
# This is only triggered when the user is explicitly set (with set_user)
|
3
5
|
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
|
4
|
-
if record.respond_to?(:
|
5
|
-
|
6
|
-
record.failed_attempts = 0
|
7
|
-
record.save(validate: false)
|
8
|
-
end
|
6
|
+
if record.respond_to?(:reset_failed_attempts!) && warden.authenticated?(options[:scope])
|
7
|
+
record.reset_failed_attempts!
|
9
8
|
end
|
10
9
|
end
|
data/lib/devise/hooks/proxy.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Each time a record is set we check whether its session has already timed out
|
2
4
|
# or not, based on last request time. If so, the record is logged out and
|
3
5
|
# redirected to the sign in page. Also, each time the request comes and the
|
@@ -19,8 +21,8 @@ Warden::Manager.after_set_user do |record, warden, options|
|
|
19
21
|
|
20
22
|
proxy = Devise::Hooks::Proxy.new(warden)
|
21
23
|
|
22
|
-
if
|
23
|
-
|
24
|
+
if !env['devise.skip_timeout'] &&
|
25
|
+
record.timedout?(last_request_at) &&
|
24
26
|
!proxy.remember_me_is_active?(record)
|
25
27
|
Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
|
26
28
|
throw :warden, scope: scope, message: :timeout
|
data/lib/devise/mapping.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
# Responsible for handling devise mappings and routes configuration. Each
|
3
5
|
# resource configured by devise_for in routes is actually creating a mapping
|
@@ -44,7 +46,7 @@ module Devise
|
|
44
46
|
raise "Could not find a valid mapping for #{obj.inspect}"
|
45
47
|
end
|
46
48
|
|
47
|
-
def self.find_by_path!(path, path_type
|
49
|
+
def self.find_by_path!(path, path_type = :fullpath)
|
48
50
|
Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
|
49
51
|
raise "Could not find a valid mapping for path #{path.inspect}"
|
50
52
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'devise/hooks/activatable'
|
3
4
|
require 'devise/hooks/csrf_cleaner'
|
5
|
+
require 'devise/rails/deprecated_constant_accessor'
|
4
6
|
|
5
7
|
module Devise
|
6
8
|
module Models
|
@@ -8,7 +10,7 @@ module Devise
|
|
8
10
|
#
|
9
11
|
# == Options
|
10
12
|
#
|
11
|
-
# Authenticatable adds the following options to
|
13
|
+
# Authenticatable adds the following options to +devise+:
|
12
14
|
#
|
13
15
|
# * +authentication_keys+: parameters used for authentication. By default [:email].
|
14
16
|
#
|
@@ -54,11 +56,14 @@ module Devise
|
|
54
56
|
module Authenticatable
|
55
57
|
extend ActiveSupport::Concern
|
56
58
|
|
57
|
-
|
59
|
+
UNSAFE_ATTRIBUTES_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
|
58
60
|
:remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
|
59
61
|
:last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
|
60
62
|
:remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at]
|
61
63
|
|
64
|
+
include Devise::DeprecatedConstantAccessor
|
65
|
+
deprecate_constant "BLACKLIST_FOR_SERIALIZATION", "Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION"
|
66
|
+
|
62
67
|
included do
|
63
68
|
class_attribute :devise_modules, instance_writer: false
|
64
69
|
self.devise_modules ||= []
|
@@ -102,13 +107,13 @@ module Devise
|
|
102
107
|
# and passing a new list of attributes you want to exempt. All attributes
|
103
108
|
# given to :except will simply add names to exempt to Devise internal list.
|
104
109
|
def serializable_hash(options = nil)
|
105
|
-
options
|
106
|
-
options[:except] = Array(options[:except])
|
110
|
+
options = options.try(:dup) || {}
|
111
|
+
options[:except] = Array(options[:except]).dup
|
107
112
|
|
108
113
|
if options[:force_except]
|
109
114
|
options[:except].concat Array(options[:force_except])
|
110
115
|
else
|
111
|
-
options[:except].concat
|
116
|
+
options[:except].concat UNSAFE_ATTRIBUTES_FOR_SERIALIZATION
|
112
117
|
end
|
113
118
|
|
114
119
|
super(options)
|
@@ -132,16 +137,18 @@ module Devise
|
|
132
137
|
# This is an internal method called every time Devise needs
|
133
138
|
# to send a notification/mail. This can be overridden if you
|
134
139
|
# need to customize the e-mail delivery logic. For instance,
|
135
|
-
# if you are using a queue to deliver e-mails (
|
136
|
-
# sidekiq, resque, etc), you must add the delivery to the queue
|
140
|
+
# if you are using a queue to deliver e-mails (active job, delayed
|
141
|
+
# job, sidekiq, resque, etc), you must add the delivery to the queue
|
137
142
|
# just after the transaction was committed. To achieve this,
|
138
143
|
# you can override send_devise_notification to store the
|
139
|
-
# deliveries until the after_commit callback is triggered
|
144
|
+
# deliveries until the after_commit callback is triggered.
|
145
|
+
#
|
146
|
+
# The following example uses Active Job's `deliver_later` :
|
140
147
|
#
|
141
148
|
# class User
|
142
149
|
# devise :database_authenticatable, :confirmable
|
143
150
|
#
|
144
|
-
# after_commit :
|
151
|
+
# after_commit :send_pending_devise_notifications
|
145
152
|
#
|
146
153
|
# protected
|
147
154
|
#
|
@@ -149,39 +156,45 @@ module Devise
|
|
149
156
|
# # If the record is new or changed then delay the
|
150
157
|
# # delivery until the after_commit callback otherwise
|
151
158
|
# # send now because after_commit will not be called.
|
152
|
-
#
|
153
|
-
#
|
159
|
+
# # For Rails < 6 use `changed?` instead of `saved_changes?`.
|
160
|
+
# if new_record? || saved_changes?
|
161
|
+
# pending_devise_notifications << [notification, args]
|
154
162
|
# else
|
155
|
-
#
|
156
|
-
# Remove once we move to Rails 4.2+ only.
|
157
|
-
# if message.respond_to?(:deliver_now)
|
158
|
-
# message.deliver_now
|
159
|
-
# else
|
160
|
-
# message.deliver
|
161
|
-
# end
|
163
|
+
# render_and_send_devise_message(notification, *args)
|
162
164
|
# end
|
163
165
|
# end
|
164
166
|
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
# message.deliver_now
|
171
|
-
# else
|
172
|
-
# message.deliver
|
173
|
-
# end
|
167
|
+
# private
|
168
|
+
#
|
169
|
+
# def send_pending_devise_notifications
|
170
|
+
# pending_devise_notifications.each do |notification, args|
|
171
|
+
# render_and_send_devise_message(notification, *args)
|
174
172
|
# end
|
175
173
|
#
|
176
174
|
# # Empty the pending notifications array because the
|
177
175
|
# # after_commit hook can be called multiple times which
|
178
176
|
# # could cause multiple emails to be sent.
|
179
|
-
#
|
177
|
+
# pending_devise_notifications.clear
|
180
178
|
# end
|
181
179
|
#
|
182
|
-
# def
|
183
|
-
# @
|
180
|
+
# def pending_devise_notifications
|
181
|
+
# @pending_devise_notifications ||= []
|
184
182
|
# end
|
183
|
+
#
|
184
|
+
# def render_and_send_devise_message(notification, *args)
|
185
|
+
# message = devise_mailer.send(notification, self, *args)
|
186
|
+
#
|
187
|
+
# # Deliver later with Active Job's `deliver_later`
|
188
|
+
# if message.respond_to?(:deliver_later)
|
189
|
+
# message.deliver_later
|
190
|
+
# # Remove once we move to Rails 4.2+ only, as `deliver` is deprecated.
|
191
|
+
# elsif message.respond_to?(:deliver_now)
|
192
|
+
# message.deliver_now
|
193
|
+
# else
|
194
|
+
# message.deliver
|
195
|
+
# end
|
196
|
+
# end
|
197
|
+
#
|
185
198
|
# end
|
186
199
|
#
|
187
200
|
def send_devise_notification(notification, *args)
|
@@ -256,46 +269,38 @@ module Devise
|
|
256
269
|
# end
|
257
270
|
#
|
258
271
|
# Finally, notice that Devise also queries for users in other scenarios
|
259
|
-
# besides authentication, for example when retrieving
|
272
|
+
# besides authentication, for example when retrieving a user to send
|
260
273
|
# an e-mail for password reset. In such cases, find_for_authentication
|
261
274
|
# is not called.
|
262
275
|
def find_for_authentication(tainted_conditions)
|
263
276
|
find_first_by_auth_conditions(tainted_conditions)
|
264
277
|
end
|
265
278
|
|
266
|
-
def find_first_by_auth_conditions(tainted_conditions, opts={})
|
279
|
+
def find_first_by_auth_conditions(tainted_conditions, opts = {})
|
267
280
|
to_adapter.find_first(devise_parameter_filter.filter(tainted_conditions).merge(opts))
|
268
281
|
end
|
269
282
|
|
270
283
|
# Find or initialize a record setting an error if it can't be found.
|
271
|
-
def find_or_initialize_with_error_by(attribute, value, error
|
284
|
+
def find_or_initialize_with_error_by(attribute, value, error = :invalid) #:nodoc:
|
272
285
|
find_or_initialize_with_errors([attribute], { attribute => value }, error)
|
273
286
|
end
|
274
287
|
|
275
288
|
# Find or initialize a record with group of attributes based on a list of required attributes.
|
276
|
-
def find_or_initialize_with_errors(required_attributes, attributes, error
|
277
|
-
attributes
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
end
|
282
|
-
attributes.delete_if { |key, value| value.blank? }
|
289
|
+
def find_or_initialize_with_errors(required_attributes, attributes, error = :invalid) #:nodoc:
|
290
|
+
attributes.try(:permit!)
|
291
|
+
attributes = attributes.to_h.with_indifferent_access
|
292
|
+
.slice(*required_attributes)
|
293
|
+
.delete_if { |key, value| value.blank? }
|
283
294
|
|
284
295
|
if attributes.size == required_attributes.size
|
285
|
-
record = find_first_by_auth_conditions(attributes)
|
296
|
+
record = find_first_by_auth_conditions(attributes) and return record
|
286
297
|
end
|
287
298
|
|
288
|
-
|
289
|
-
record = new
|
290
|
-
|
299
|
+
new(devise_parameter_filter.filter(attributes)).tap do |record|
|
291
300
|
required_attributes.each do |key|
|
292
|
-
|
293
|
-
record.send("#{key}=", value)
|
294
|
-
record.errors.add(key, value.present? ? error : :blank)
|
301
|
+
record.errors.add(key, attributes[key].blank? ? :blank : error)
|
295
302
|
end
|
296
303
|
end
|
297
|
-
|
298
|
-
record
|
299
304
|
end
|
300
305
|
|
301
306
|
protected
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
module Models
|
3
5
|
# Confirmable is responsible to verify if an account is already confirmed to
|
@@ -46,7 +48,7 @@ module Devise
|
|
46
48
|
included do
|
47
49
|
before_create :generate_confirmation_token, if: :confirmation_required?
|
48
50
|
after_create :skip_reconfirmation_in_callback!, if: :send_confirmation_notification?
|
49
|
-
if
|
51
|
+
if Devise::Orm.active_record?(self) # ActiveRecord
|
50
52
|
after_commit :send_on_create_confirmation_instructions, on: :create, if: :send_confirmation_notification?
|
51
53
|
after_commit :send_reconfirmation_instructions, on: :update, if: :reconfirmation_required?
|
52
54
|
else # Mongoid
|
@@ -74,7 +76,7 @@ module Devise
|
|
74
76
|
# Confirm a user by setting it's confirmed_at to actual time. If the user
|
75
77
|
# is already confirmed, add an error to email field. If the user is invalid
|
76
78
|
# add errors
|
77
|
-
def confirm(args={})
|
79
|
+
def confirm(args = {})
|
78
80
|
pending_any_confirmation do
|
79
81
|
if confirmation_period_expired?
|
80
82
|
self.errors.add(:email, :confirmation_period_expired,
|
@@ -209,7 +211,10 @@ module Devise
|
|
209
211
|
# confirmation_period_valid? # will always return true
|
210
212
|
#
|
211
213
|
def confirmation_period_valid?
|
212
|
-
|
214
|
+
return true if self.class.allow_unconfirmed_access_for.nil?
|
215
|
+
return false if self.class.allow_unconfirmed_access_for == 0.days
|
216
|
+
|
217
|
+
confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
|
213
218
|
end
|
214
219
|
|
215
220
|
# Checks if the user confirmation happens before the token becomes invalid
|
@@ -253,44 +258,23 @@ module Devise
|
|
253
258
|
generate_confirmation_token && save(validate: false)
|
254
259
|
end
|
255
260
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
end
|
264
|
-
else
|
265
|
-
def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
|
266
|
-
@reconfirmation_required = true
|
267
|
-
self.unconfirmed_email = self.email
|
268
|
-
self.email = self.email_was
|
269
|
-
self.confirmation_token = nil
|
270
|
-
generate_confirmation_token
|
271
|
-
end
|
261
|
+
|
262
|
+
def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
|
263
|
+
@reconfirmation_required = true
|
264
|
+
self.unconfirmed_email = self.email
|
265
|
+
self.email = self.devise_email_in_database
|
266
|
+
self.confirmation_token = nil
|
267
|
+
generate_confirmation_token
|
272
268
|
end
|
273
269
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
postpone
|
283
|
-
end
|
284
|
-
else
|
285
|
-
def postpone_email_change?
|
286
|
-
postpone = self.class.reconfirmable &&
|
287
|
-
email_changed? &&
|
288
|
-
!@bypass_confirmation_postpone &&
|
289
|
-
self.email.present? &&
|
290
|
-
(!@skip_reconfirmation_in_callback || !self.email_was.nil?)
|
291
|
-
@bypass_confirmation_postpone = false
|
292
|
-
postpone
|
293
|
-
end
|
270
|
+
def postpone_email_change?
|
271
|
+
postpone = self.class.reconfirmable &&
|
272
|
+
devise_will_save_change_to_email? &&
|
273
|
+
!@bypass_confirmation_postpone &&
|
274
|
+
self.email.present? &&
|
275
|
+
(!@skip_reconfirmation_in_callback || !self.devise_email_in_database.nil?)
|
276
|
+
@bypass_confirmation_postpone = false
|
277
|
+
postpone
|
294
278
|
end
|
295
279
|
|
296
280
|
def reconfirmation_required?
|
@@ -329,7 +313,7 @@ module Devise
|
|
329
313
|
# confirmation instructions to it. If not, try searching for a user by unconfirmed_email
|
330
314
|
# field. If no user is found, returns a new user with an email not found error.
|
331
315
|
# Options must contain the user email
|
332
|
-
def send_confirmation_instructions(attributes={})
|
316
|
+
def send_confirmation_instructions(attributes = {})
|
333
317
|
confirmable = find_by_unconfirmed_email_with_errors(attributes) if reconfirmable
|
334
318
|
unless confirmable.try(:persisted?)
|
335
319
|
confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
|
@@ -343,7 +327,19 @@ module Devise
|
|
343
327
|
# If the user is already confirmed, create an error for the user
|
344
328
|
# Options must have the confirmation_token
|
345
329
|
def confirm_by_token(confirmation_token)
|
330
|
+
# When the `confirmation_token` parameter is blank, if there are any users with a blank
|
331
|
+
# `confirmation_token` in the database, the first one would be confirmed here.
|
332
|
+
# The error is being manually added here to ensure no users are confirmed by mistake.
|
333
|
+
# This was done in the model for convenience, since validation errors are automatically
|
334
|
+
# displayed in the view.
|
335
|
+
if confirmation_token.blank?
|
336
|
+
confirmable = new
|
337
|
+
confirmable.errors.add(:confirmation_token, :blank)
|
338
|
+
return confirmable
|
339
|
+
end
|
340
|
+
|
346
341
|
confirmable = find_first_by_auth_conditions(confirmation_token: confirmation_token)
|
342
|
+
|
347
343
|
unless confirmable
|
348
344
|
confirmation_digest = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
|
349
345
|
confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_digest)
|