devise 4.5.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.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +137 -3
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +125 -60
  5. data/app/controllers/devise/confirmations_controller.rb +1 -0
  6. data/app/controllers/devise/passwords_controller.rb +3 -2
  7. data/app/controllers/devise/registrations_controller.rb +26 -8
  8. data/app/controllers/devise/sessions_controller.rb +1 -1
  9. data/app/controllers/devise/unlocks_controller.rb +1 -0
  10. data/app/controllers/devise_controller.rb +3 -2
  11. data/app/helpers/devise_helper.rb +21 -18
  12. data/app/mailers/devise/mailer.rb +5 -5
  13. data/app/views/devise/confirmations/new.html.erb +1 -1
  14. data/app/views/devise/passwords/edit.html.erb +2 -2
  15. data/app/views/devise/passwords/new.html.erb +1 -1
  16. data/app/views/devise/registrations/edit.html.erb +2 -2
  17. data/app/views/devise/registrations/new.html.erb +1 -1
  18. data/app/views/devise/sessions/new.html.erb +2 -2
  19. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  20. data/app/views/devise/shared/_links.html.erb +8 -8
  21. data/app/views/devise/unlocks/new.html.erb +1 -1
  22. data/config/locales/en.yml +3 -2
  23. data/lib/devise/controllers/helpers.rb +8 -8
  24. data/lib/devise/controllers/responder.rb +35 -0
  25. data/lib/devise/controllers/sign_in_out.rb +6 -4
  26. data/lib/devise/controllers/url_helpers.rb +1 -1
  27. data/lib/devise/failure_app.rb +29 -7
  28. data/lib/devise/hooks/csrf_cleaner.rb +6 -1
  29. data/lib/devise/hooks/lockable.rb +2 -5
  30. data/lib/devise/hooks/timeoutable.rb +2 -2
  31. data/lib/devise/mapping.rb +1 -1
  32. data/lib/devise/models/authenticatable.rb +20 -24
  33. data/lib/devise/models/confirmable.rb +34 -40
  34. data/lib/devise/models/database_authenticatable.rb +47 -28
  35. data/lib/devise/models/lockable.rb +13 -5
  36. data/lib/devise/models/omniauthable.rb +2 -2
  37. data/lib/devise/models/recoverable.rb +8 -19
  38. data/lib/devise/models/registerable.rb +2 -0
  39. data/lib/devise/models/rememberable.rb +2 -2
  40. data/lib/devise/models/timeoutable.rb +1 -1
  41. data/lib/devise/models/trackable.rb +1 -1
  42. data/lib/devise/models/validatable.rb +4 -9
  43. data/lib/devise/models.rb +1 -0
  44. data/lib/devise/omniauth.rb +2 -5
  45. data/lib/devise/orm.rb +71 -0
  46. data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
  47. data/lib/devise/rails/routes.rb +6 -6
  48. data/lib/devise/strategies/authenticatable.rb +1 -1
  49. data/lib/devise/strategies/database_authenticatable.rb +3 -0
  50. data/lib/devise/test/controller_helpers.rb +4 -2
  51. data/lib/devise/test/integration_helpers.rb +1 -1
  52. data/lib/devise/version.rb +1 -1
  53. data/lib/devise.rb +34 -11
  54. data/lib/generators/active_record/devise_generator.rb +21 -6
  55. data/lib/generators/devise/controllers_generator.rb +1 -1
  56. data/lib/generators/devise/devise_generator.rb +1 -1
  57. data/lib/generators/devise/install_generator.rb +1 -5
  58. data/lib/generators/devise/views_generator.rb +1 -1
  59. data/lib/generators/templates/README +9 -1
  60. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +1 -1
  61. data/lib/generators/templates/devise.rb +37 -14
  62. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -1
  63. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +2 -2
  64. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
  65. metadata +23 -318
  66. data/.gitignore +0 -10
  67. data/.travis.yml +0 -69
  68. data/.yardopts +0 -9
  69. data/CODE_OF_CONDUCT.md +0 -22
  70. data/CONTRIBUTING.md +0 -79
  71. data/Gemfile +0 -39
  72. data/Gemfile.lock +0 -202
  73. data/ISSUE_TEMPLATE.md +0 -19
  74. data/Rakefile +0 -37
  75. data/bin/test +0 -13
  76. data/devise.gemspec +0 -28
  77. data/devise.png +0 -0
  78. data/gemfiles/Gemfile.rails-4.1-stable +0 -32
  79. data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -171
  80. data/gemfiles/Gemfile.rails-4.2-stable +0 -32
  81. data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
  82. data/gemfiles/Gemfile.rails-5.0-stable +0 -33
  83. data/gemfiles/Gemfile.rails-5.0-stable.lock +0 -192
  84. data/gemfiles/Gemfile.rails-5.2-rc1 +0 -26
  85. data/gemfiles/Gemfile.rails-5.2-rc1.lock +0 -201
  86. data/guides/bug_report_templates/integration_test.rb +0 -106
  87. data/test/controllers/custom_registrations_controller_test.rb +0 -42
  88. data/test/controllers/custom_strategy_test.rb +0 -66
  89. data/test/controllers/helper_methods_test.rb +0 -24
  90. data/test/controllers/helpers_test.rb +0 -318
  91. data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -53
  92. data/test/controllers/internal_helpers_test.rb +0 -129
  93. data/test/controllers/load_hooks_controller_test.rb +0 -21
  94. data/test/controllers/passwords_controller_test.rb +0 -34
  95. data/test/controllers/sessions_controller_test.rb +0 -108
  96. data/test/controllers/url_helpers_test.rb +0 -67
  97. data/test/delegator_test.rb +0 -21
  98. data/test/devise_test.rb +0 -109
  99. data/test/failure_app_test.rb +0 -346
  100. data/test/generators/active_record_generator_test.rb +0 -130
  101. data/test/generators/controllers_generator_test.rb +0 -50
  102. data/test/generators/devise_generator_test.rb +0 -41
  103. data/test/generators/install_generator_test.rb +0 -26
  104. data/test/generators/mongoid_generator_test.rb +0 -25
  105. data/test/generators/views_generator_test.rb +0 -105
  106. data/test/helpers/devise_helper_test.rb +0 -51
  107. data/test/integration/authenticatable_test.rb +0 -706
  108. data/test/integration/confirmable_test.rb +0 -326
  109. data/test/integration/database_authenticatable_test.rb +0 -110
  110. data/test/integration/http_authenticatable_test.rb +0 -114
  111. data/test/integration/lockable_test.rb +0 -242
  112. data/test/integration/mounted_engine_test.rb +0 -38
  113. data/test/integration/omniauthable_test.rb +0 -148
  114. data/test/integration/recoverable_test.rb +0 -349
  115. data/test/integration/registerable_test.rb +0 -365
  116. data/test/integration/rememberable_test.rb +0 -219
  117. data/test/integration/timeoutable_test.rb +0 -186
  118. data/test/integration/trackable_test.rb +0 -99
  119. data/test/mailers/confirmation_instructions_test.rb +0 -117
  120. data/test/mailers/email_changed_test.rb +0 -132
  121. data/test/mailers/mailer_test.rb +0 -20
  122. data/test/mailers/reset_password_instructions_test.rb +0 -98
  123. data/test/mailers/unlock_instructions_test.rb +0 -93
  124. data/test/mapping_test.rb +0 -136
  125. data/test/models/authenticatable_test.rb +0 -25
  126. data/test/models/confirmable_test.rb +0 -549
  127. data/test/models/database_authenticatable_test.rb +0 -290
  128. data/test/models/lockable_test.rb +0 -352
  129. data/test/models/omniauthable_test.rb +0 -9
  130. data/test/models/recoverable_test.rb +0 -263
  131. data/test/models/registerable_test.rb +0 -9
  132. data/test/models/rememberable_test.rb +0 -184
  133. data/test/models/serializable_test.rb +0 -60
  134. data/test/models/timeoutable_test.rb +0 -53
  135. data/test/models/trackable_test.rb +0 -80
  136. data/test/models/validatable_test.rb +0 -121
  137. data/test/models_test.rb +0 -155
  138. data/test/omniauth/config_test.rb +0 -61
  139. data/test/omniauth/url_helpers_test.rb +0 -53
  140. data/test/orm/active_record.rb +0 -24
  141. data/test/orm/mongoid.rb +0 -15
  142. data/test/parameter_sanitizer_test.rb +0 -105
  143. data/test/rails_app/Rakefile +0 -6
  144. data/test/rails_app/app/active_record/admin.rb +0 -8
  145. data/test/rails_app/app/active_record/shim.rb +0 -4
  146. data/test/rails_app/app/active_record/user.rb +0 -20
  147. data/test/rails_app/app/active_record/user_on_engine.rb +0 -9
  148. data/test/rails_app/app/active_record/user_on_main_app.rb +0 -9
  149. data/test/rails_app/app/active_record/user_with_validations.rb +0 -12
  150. data/test/rails_app/app/active_record/user_without_email.rb +0 -10
  151. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -8
  152. data/test/rails_app/app/controllers/admins_controller.rb +0 -8
  153. data/test/rails_app/app/controllers/application_controller.rb +0 -13
  154. data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -32
  155. data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -33
  156. data/test/rails_app/app/controllers/home_controller.rb +0 -31
  157. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -4
  158. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -4
  159. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -16
  160. data/test/rails_app/app/controllers/users_controller.rb +0 -33
  161. data/test/rails_app/app/helpers/application_helper.rb +0 -5
  162. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -5
  163. data/test/rails_app/app/mailers/users/mailer.rb +0 -5
  164. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -6
  165. data/test/rails_app/app/mongoid/admin.rb +0 -31
  166. data/test/rails_app/app/mongoid/shim.rb +0 -25
  167. data/test/rails_app/app/mongoid/user.rb +0 -50
  168. data/test/rails_app/app/mongoid/user_on_engine.rb +0 -41
  169. data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -41
  170. data/test/rails_app/app/mongoid/user_with_validations.rb +0 -37
  171. data/test/rails_app/app/mongoid/user_without_email.rb +0 -35
  172. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  173. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  174. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  175. data/test/rails_app/app/views/home/index.html.erb +0 -1
  176. data/test/rails_app/app/views/home/join.html.erb +0 -1
  177. data/test/rails_app/app/views/home/private.html.erb +0 -1
  178. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  179. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  180. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  181. data/test/rails_app/app/views/users/index.html.erb +0 -1
  182. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  183. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  184. data/test/rails_app/bin/bundle +0 -3
  185. data/test/rails_app/bin/rails +0 -4
  186. data/test/rails_app/bin/rake +0 -4
  187. data/test/rails_app/config/application.rb +0 -48
  188. data/test/rails_app/config/boot.rb +0 -27
  189. data/test/rails_app/config/database.yml +0 -18
  190. data/test/rails_app/config/environment.rb +0 -7
  191. data/test/rails_app/config/environments/development.rb +0 -32
  192. data/test/rails_app/config/environments/production.rb +0 -88
  193. data/test/rails_app/config/environments/test.rb +0 -47
  194. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -9
  195. data/test/rails_app/config/initializers/devise.rb +0 -187
  196. data/test/rails_app/config/initializers/inflections.rb +0 -4
  197. data/test/rails_app/config/initializers/secret_token.rb +0 -5
  198. data/test/rails_app/config/initializers/session_store.rb +0 -3
  199. data/test/rails_app/config/routes.rb +0 -128
  200. data/test/rails_app/config.ru +0 -4
  201. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -77
  202. data/test/rails_app/db/schema.rb +0 -57
  203. data/test/rails_app/lib/lazy_load_test_module.rb +0 -5
  204. data/test/rails_app/lib/shared_admin.rb +0 -23
  205. data/test/rails_app/lib/shared_user.rb +0 -32
  206. data/test/rails_app/lib/shared_user_without_email.rb +0 -28
  207. data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -15
  208. data/test/rails_app/public/404.html +0 -26
  209. data/test/rails_app/public/422.html +0 -26
  210. data/test/rails_app/public/500.html +0 -26
  211. data/test/rails_app/public/favicon.ico +0 -0
  212. data/test/rails_test.rb +0 -11
  213. data/test/routes_test.rb +0 -281
  214. data/test/secret_key_finder_test.rb +0 -121
  215. data/test/support/action_controller/record_identifier.rb +0 -12
  216. data/test/support/assertions.rb +0 -30
  217. data/test/support/helpers.rb +0 -83
  218. data/test/support/http_method_compatibility.rb +0 -53
  219. data/test/support/integration.rb +0 -95
  220. data/test/support/locale/en.yml +0 -8
  221. data/test/support/mongoid.yml +0 -6
  222. data/test/support/webrat/integrations/rails.rb +0 -35
  223. data/test/test/controller_helpers_test.rb +0 -193
  224. data/test/test/integration_helpers_test.rb +0 -34
  225. data/test/test_helper.rb +0 -36
  226. data/test/test_models.rb +0 -35
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_model/version'
4
3
  require 'devise/hooks/activatable'
5
4
  require 'devise/hooks/csrf_cleaner'
5
+ require 'devise/rails/deprecated_constant_accessor'
6
6
 
7
7
  module Devise
8
8
  module Models
@@ -10,7 +10,7 @@ module Devise
10
10
  #
11
11
  # == Options
12
12
  #
13
- # Authenticatable adds the following options to devise_for:
13
+ # Authenticatable adds the following options to +devise+:
14
14
  #
15
15
  # * +authentication_keys+: parameters used for authentication. By default [:email].
16
16
  #
@@ -56,11 +56,14 @@ module Devise
56
56
  module Authenticatable
57
57
  extend ActiveSupport::Concern
58
58
 
59
- BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
59
+ UNSAFE_ATTRIBUTES_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
60
60
  :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
61
61
  :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
62
62
  :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at]
63
63
 
64
+ include Devise::DeprecatedConstantAccessor
65
+ deprecate_constant "BLACKLIST_FOR_SERIALIZATION", "Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION"
66
+
64
67
  included do
65
68
  class_attribute :devise_modules, instance_writer: false
66
69
  self.devise_modules ||= []
@@ -105,12 +108,12 @@ module Devise
105
108
  # given to :except will simply add names to exempt to Devise internal list.
106
109
  def serializable_hash(options = nil)
107
110
  options = options.try(:dup) || {}
108
- options[:except] = Array(options[:except])
111
+ options[:except] = Array(options[:except]).dup
109
112
 
110
113
  if options[:force_except]
111
114
  options[:except].concat Array(options[:force_except])
112
115
  else
113
- options[:except].concat BLACKLIST_FOR_SERIALIZATION
116
+ options[:except].concat UNSAFE_ATTRIBUTES_FOR_SERIALIZATION
114
117
  end
115
118
 
116
119
  super(options)
@@ -153,7 +156,8 @@ module Devise
153
156
  # # If the record is new or changed then delay the
154
157
  # # delivery until the after_commit callback otherwise
155
158
  # # send now because after_commit will not be called.
156
- # if new_record? || changed?
159
+ # # For Rails < 6 use `changed?` instead of `saved_changes?`.
160
+ # if new_record? || saved_changes?
157
161
  # pending_devise_notifications << [notification, args]
158
162
  # else
159
163
  # render_and_send_devise_message(notification, *args)
@@ -272,39 +276,31 @@ module Devise
272
276
  find_first_by_auth_conditions(tainted_conditions)
273
277
  end
274
278
 
275
- def find_first_by_auth_conditions(tainted_conditions, opts={})
279
+ def find_first_by_auth_conditions(tainted_conditions, opts = {})
276
280
  to_adapter.find_first(devise_parameter_filter.filter(tainted_conditions).merge(opts))
277
281
  end
278
282
 
279
283
  # Find or initialize a record setting an error if it can't be found.
280
- def find_or_initialize_with_error_by(attribute, value, error=:invalid) #:nodoc:
284
+ def find_or_initialize_with_error_by(attribute, value, error = :invalid) #:nodoc:
281
285
  find_or_initialize_with_errors([attribute], { attribute => value }, error)
282
286
  end
283
287
 
284
288
  # Find or initialize a record with group of attributes based on a list of required attributes.
285
- def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
286
- attributes = if attributes.respond_to? :permit!
287
- attributes.slice(*required_attributes).permit!.to_h.with_indifferent_access
288
- else
289
- attributes.with_indifferent_access.slice(*required_attributes)
290
- end
291
- 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? }
292
294
 
293
295
  if attributes.size == required_attributes.size
294
- record = find_first_by_auth_conditions(attributes)
296
+ record = find_first_by_auth_conditions(attributes) and return record
295
297
  end
296
298
 
297
- unless record
298
- record = new
299
-
299
+ new(devise_parameter_filter.filter(attributes)).tap do |record|
300
300
  required_attributes.each do |key|
301
- value = attributes[key]
302
- record.send("#{key}=", value)
303
- record.errors.add(key, value.present? ? error : :blank)
301
+ record.errors.add(key, attributes[key].blank? ? :blank : error)
304
302
  end
305
303
  end
306
-
307
- record
308
304
  end
309
305
 
310
306
  protected
@@ -48,7 +48,7 @@ module Devise
48
48
  included do
49
49
  before_create :generate_confirmation_token, if: :confirmation_required?
50
50
  after_create :skip_reconfirmation_in_callback!, if: :send_confirmation_notification?
51
- if defined?(ActiveRecord) && self < ActiveRecord::Base # ActiveRecord
51
+ if Devise::Orm.active_record?(self) # ActiveRecord
52
52
  after_commit :send_on_create_confirmation_instructions, on: :create, if: :send_confirmation_notification?
53
53
  after_commit :send_reconfirmation_instructions, on: :update, if: :reconfirmation_required?
54
54
  else # Mongoid
@@ -76,7 +76,7 @@ module Devise
76
76
  # Confirm a user by setting it's confirmed_at to actual time. If the user
77
77
  # is already confirmed, add an error to email field. If the user is invalid
78
78
  # add errors
79
- def confirm(args={})
79
+ def confirm(args = {})
80
80
  pending_any_confirmation do
81
81
  if confirmation_period_expired?
82
82
  self.errors.add(:email, :confirmation_period_expired,
@@ -211,7 +211,10 @@ module Devise
211
211
  # confirmation_period_valid? # will always return true
212
212
  #
213
213
  def confirmation_period_valid?
214
- self.class.allow_unconfirmed_access_for.nil? || (confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago)
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
215
218
  end
216
219
 
217
220
  # Checks if the user confirmation happens before the token becomes invalid
@@ -255,44 +258,23 @@ module Devise
255
258
  generate_confirmation_token && save(validate: false)
256
259
  end
257
260
 
258
- if Devise.activerecord51?
259
- def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
260
- @reconfirmation_required = true
261
- self.unconfirmed_email = self.email
262
- self.email = self.email_in_database
263
- self.confirmation_token = nil
264
- generate_confirmation_token
265
- end
266
- else
267
- def postpone_email_change_until_confirmation_and_regenerate_confirmation_token
268
- @reconfirmation_required = true
269
- self.unconfirmed_email = self.email
270
- self.email = self.email_was
271
- self.confirmation_token = nil
272
- generate_confirmation_token
273
- 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
274
268
  end
275
269
 
276
- if Devise.activerecord51?
277
- def postpone_email_change?
278
- postpone = self.class.reconfirmable &&
279
- will_save_change_to_email? &&
280
- !@bypass_confirmation_postpone &&
281
- self.email.present? &&
282
- (!@skip_reconfirmation_in_callback || !self.email_in_database.nil?)
283
- @bypass_confirmation_postpone = false
284
- postpone
285
- end
286
- else
287
- def postpone_email_change?
288
- postpone = self.class.reconfirmable &&
289
- email_changed? &&
290
- !@bypass_confirmation_postpone &&
291
- self.email.present? &&
292
- (!@skip_reconfirmation_in_callback || !self.email_was.nil?)
293
- @bypass_confirmation_postpone = false
294
- postpone
295
- 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
296
278
  end
297
279
 
298
280
  def reconfirmation_required?
@@ -331,7 +313,7 @@ module Devise
331
313
  # confirmation instructions to it. If not, try searching for a user by unconfirmed_email
332
314
  # field. If no user is found, returns a new user with an email not found error.
333
315
  # Options must contain the user email
334
- def send_confirmation_instructions(attributes={})
316
+ def send_confirmation_instructions(attributes = {})
335
317
  confirmable = find_by_unconfirmed_email_with_errors(attributes) if reconfirmable
336
318
  unless confirmable.try(:persisted?)
337
319
  confirmable = find_or_initialize_with_errors(confirmation_keys, attributes, :not_found)
@@ -345,7 +327,19 @@ module Devise
345
327
  # If the user is already confirmed, create an error for the user
346
328
  # Options must have the confirmation_token
347
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
+
348
341
  confirmable = find_first_by_auth_conditions(confirmation_token: confirmation_token)
342
+
349
343
  unless confirmable
350
344
  confirmation_digest = Devise.token_generator.digest(self, :confirmation_token, confirmation_token)
351
345
  confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_digest)
@@ -7,9 +7,13 @@ module Devise
7
7
  # Authenticatable Module, responsible for hashing the password and
8
8
  # validating the authenticity of a user while signing in.
9
9
  #
10
+ # This module defines a `password=` method. This method will hash the argument
11
+ # and store it in the `encrypted_password` column, bypassing any pre-existing
12
+ # `password` column if it exists.
13
+ #
10
14
  # == Options
11
15
  #
12
- # DatabaseAuthenticatable adds the following options to devise_for:
16
+ # DatabaseAuthenticatable adds the following options to +devise+:
13
17
  #
14
18
  # * +pepper+: a random string used to provide a more secure hash. Use
15
19
  # `rails secret` to generate new keys.
@@ -35,6 +39,22 @@ module Devise
35
39
  attr_accessor :password_confirmation
36
40
  end
37
41
 
42
+ def initialize(*args, &block)
43
+ @skip_email_changed_notification = false
44
+ @skip_password_change_notification = false
45
+ super
46
+ end
47
+
48
+ # Skips sending the email changed notification after_update
49
+ def skip_email_changed_notification!
50
+ @skip_email_changed_notification = true
51
+ end
52
+
53
+ # Skips sending the password change notification after_update
54
+ def skip_password_change_notification!
55
+ @skip_password_change_notification = true
56
+ end
57
+
38
58
  def self.required_fields(klass)
39
59
  [:encrypted_password] + klass.authentication_keys
40
60
  end
@@ -65,6 +85,15 @@ module Devise
65
85
  # their password). In case the password field is rejected, the confirmation
66
86
  # is also rejected as long as it is also blank.
67
87
  def update_with_password(params, *options)
88
+ if options.present?
89
+ ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
90
+ [Devise] The second argument of `DatabaseAuthenticatable#update_with_password`
91
+ (`options`) is deprecated and it will be removed in the next major version.
92
+ It was added to support a feature deprecated in Rails 4, so you can safely remove it
93
+ from your code.
94
+ DEPRECATION
95
+ end
96
+
68
97
  current_password = params.delete(:current_password)
69
98
 
70
99
  if params[:password].blank?
@@ -98,6 +127,15 @@ module Devise
98
127
  # end
99
128
  #
100
129
  def update_without_password(params, *options)
130
+ if options.present?
131
+ ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
132
+ [Devise] The second argument of `DatabaseAuthenticatable#update_without_password`
133
+ (`options`) is deprecated and it will be removed in the next major version.
134
+ It was added to support a feature deprecated in Rails 4, so you can safely remove it
135
+ from your code.
136
+ DEPRECATION
137
+ end
138
+
101
139
  params.delete(:password)
102
140
  params.delete(:password_confirmation)
103
141
 
@@ -139,16 +177,9 @@ module Devise
139
177
  encrypted_password[0,29] if encrypted_password
140
178
  end
141
179
 
142
- if Devise.activerecord51?
143
- # Send notification to user when email changes.
144
- def send_email_changed_notification
145
- send_devise_notification(:email_changed, to: email_before_last_save)
146
- end
147
- else
148
- # Send notification to user when email changes.
149
- def send_email_changed_notification
150
- send_devise_notification(:email_changed, to: email_was)
151
- end
180
+ # Send notification to user when email changes.
181
+ def send_email_changed_notification
182
+ send_devise_notification(:email_changed, to: devise_email_before_last_save)
152
183
  end
153
184
 
154
185
  # Send notification to user when password changes.
@@ -161,30 +192,18 @@ module Devise
161
192
  # Hashes the password using bcrypt. Custom hash functions should override
162
193
  # this method to apply their own algorithm.
163
194
  #
164
- # See https://github.com/plataformatec/devise-encryptable for examples
195
+ # See https://github.com/heartcombo/devise-encryptable for examples
165
196
  # of other hashing engines.
166
197
  def password_digest(password)
167
198
  Devise::Encryptor.digest(self.class, password)
168
199
  end
169
200
 
170
- if Devise.activerecord51?
171
- def send_email_changed_notification?
172
- self.class.send_email_changed_notification && saved_change_to_email?
173
- end
174
- else
175
- def send_email_changed_notification?
176
- self.class.send_email_changed_notification && email_changed?
177
- end
201
+ def send_email_changed_notification?
202
+ self.class.send_email_changed_notification && devise_saved_change_to_email? && !@skip_email_changed_notification
178
203
  end
179
204
 
180
- if Devise.activerecord51?
181
- def send_password_change_notification?
182
- self.class.send_password_change_notification && saved_change_to_encrypted_password?
183
- end
184
- else
185
- def send_password_change_notification?
186
- self.class.send_password_change_notification && encrypted_password_changed?
187
- end
205
+ def send_password_change_notification?
206
+ self.class.send_password_change_notification && devise_saved_change_to_encrypted_password? && !@skip_password_change_notification
188
207
  end
189
208
 
190
209
  module ClassMethods
@@ -18,7 +18,7 @@ module Devise
18
18
  # * +maximum_attempts+: how many attempts should be accepted before blocking the user.
19
19
  # * +lock_strategy+: lock the user account by :failed_attempts or :none.
20
20
  # * +unlock_strategy+: unlock the user account by :time, :email, :both or :none.
21
- # * +unlock_in+: the time you want to lock the user after to lock happens. Only available when unlock_strategy is :time or :both.
21
+ # * +unlock_in+: the time you want to unlock the user after lock happens. Only available when unlock_strategy is :time or :both.
22
22
  # * +unlock_keys+: the keys you want to use when locking and unlocking an account
23
23
  #
24
24
  module Lockable
@@ -57,6 +57,14 @@ module Devise
57
57
  save(validate: false)
58
58
  end
59
59
 
60
+ # Resets failed attempts counter to 0.
61
+ def reset_failed_attempts!
62
+ if respond_to?(:failed_attempts) && !failed_attempts.to_i.zero?
63
+ self.failed_attempts = 0
64
+ save(validate: false)
65
+ end
66
+ end
67
+
60
68
  # Verifies whether a user is locked or not.
61
69
  def access_locked?
62
70
  !!locked_at && !lock_expired?
@@ -110,10 +118,10 @@ module Devise
110
118
  false
111
119
  end
112
120
  end
113
-
121
+
114
122
  def increment_failed_attempts
115
- self.failed_attempts ||= 0
116
- self.failed_attempts += 1
123
+ self.class.increment_counter(:failed_attempts, id)
124
+ reload
117
125
  end
118
126
 
119
127
  def unauthenticated_message
@@ -168,7 +176,7 @@ module Devise
168
176
  # unlock instructions to it. If not user is found, returns a new user
169
177
  # with an email not found error.
170
178
  # Options must contain the user's unlock keys
171
- def send_unlock_instructions(attributes={})
179
+ def send_unlock_instructions(attributes = {})
172
180
  lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
173
181
  lockable.resend_unlock_instructions if lockable.persisted?
174
182
  lockable
@@ -8,11 +8,11 @@ module Devise
8
8
  #
9
9
  # == Options
10
10
  #
11
- # Oauthable adds the following options to devise_for:
11
+ # Oauthable adds the following options to +devise+:
12
12
  #
13
13
  # * +omniauth_providers+: Which providers are available to this model. It expects an array:
14
14
  #
15
- # devise_for :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
15
+ # devise :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
16
16
  #
17
17
  module Omniauthable
18
18
  extend ActiveSupport::Concern
@@ -7,7 +7,7 @@ module Devise
7
7
  #
8
8
  # ==Options
9
9
  #
10
- # Recoverable adds the following options to devise_for:
10
+ # Recoverable adds the following options to +devise+:
11
11
  #
12
12
  # * +reset_password_keys+: the keys you want to use when recovering the password for an account
13
13
  # * +reset_password_within+: the time period within which the password must be reset or the token expires.
@@ -99,24 +99,13 @@ module Devise
99
99
  send_devise_notification(:reset_password_instructions, token, {})
100
100
  end
101
101
 
102
- if Devise.activerecord51?
103
- def clear_reset_password_token?
104
- encrypted_password_changed = respond_to?(:will_save_change_to_encrypted_password?) && will_save_change_to_encrypted_password?
105
- authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
106
- respond_to?("will_save_change_to_#{attribute}?") && send("will_save_change_to_#{attribute}?")
107
- end
108
-
109
- authentication_keys_changed || encrypted_password_changed
102
+ def clear_reset_password_token?
103
+ encrypted_password_changed = devise_respond_to_and_will_save_change_to_attribute?(:encrypted_password)
104
+ authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
105
+ devise_respond_to_and_will_save_change_to_attribute?(attribute)
110
106
  end
111
- else
112
- def clear_reset_password_token?
113
- encrypted_password_changed = respond_to?(:encrypted_password_changed?) && encrypted_password_changed?
114
- authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
115
- respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
116
- end
117
107
 
118
- authentication_keys_changed || encrypted_password_changed
119
- end
108
+ authentication_keys_changed || encrypted_password_changed
120
109
  end
121
110
 
122
111
  module ClassMethods
@@ -131,7 +120,7 @@ module Devise
131
120
  # password instructions to it. If user is not found, returns a new user
132
121
  # with an email not found error.
133
122
  # Attributes must contain the user's email
134
- def send_reset_password_instructions(attributes={})
123
+ def send_reset_password_instructions(attributes = {})
135
124
  recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
136
125
  recoverable.send_reset_password_instructions if recoverable.persisted?
137
126
  recoverable
@@ -142,7 +131,7 @@ module Devise
142
131
  # try saving the record. If not user is found, returns a new user
143
132
  # containing an error in reset_password_token attribute.
144
133
  # Attributes must contain reset_password_token, password and confirmation
145
- def reset_password_by_token(attributes={})
134
+ def reset_password_by_token(attributes = {})
146
135
  original_token = attributes[:reset_password_token]
147
136
  reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
148
137
 
@@ -21,6 +21,8 @@ module Devise
21
21
  def new_with_session(params, session)
22
22
  new(params)
23
23
  end
24
+
25
+ Devise::Models.config(self, :sign_in_after_change_password)
24
26
  end
25
27
  end
26
28
  end
@@ -15,7 +15,7 @@ module Devise
15
15
  #
16
16
  # == Options
17
17
  #
18
- # Rememberable adds the following options in devise_for:
18
+ # Rememberable adds the following options to +devise+:
19
19
  #
20
20
  # * +remember_for+: the time you want the user will be remembered without
21
21
  # asking for credentials. After this time the user will be blocked and
@@ -102,7 +102,7 @@ module Devise
102
102
 
103
103
  def remember_me?(token, generated_at)
104
104
  # TODO: Normalize the JSON type coercion along with the Timeoutable hook
105
- # in a single place https://github.com/plataformatec/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
105
+ # in a single place https://github.com/heartcombo/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
106
106
  if generated_at.is_a?(String)
107
107
  generated_at = time_from_json(generated_at)
108
108
  end
@@ -11,7 +11,7 @@ module Devise
11
11
  #
12
12
  # == Options
13
13
  #
14
- # Timeoutable adds the following options to devise_for:
14
+ # Timeoutable adds the following options to +devise+:
15
15
  #
16
16
  # * +timeout_in+: the interval to timeout the user session without activity.
17
17
  #
@@ -33,7 +33,7 @@ module Devise
33
33
  def update_tracked_fields!(request)
34
34
  # We have to check if the user is already persisted before running
35
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.
36
+ # See https://github.com/heartcombo/devise/issues/4673 for more details.
37
37
  return if new_record?
38
38
 
39
39
  update_tracked_fields(request)
@@ -9,7 +9,7 @@ module Devise
9
9
  #
10
10
  # == Options
11
11
  #
12
- # Validatable adds the following options to devise_for:
12
+ # Validatable adds the following options to +devise+:
13
13
  #
14
14
  # * +email_regexp+: the regular expression used to validate e-mails;
15
15
  # * +password_length+: a range expressing password length. Defaults to 6..128.
@@ -29,13 +29,8 @@ module Devise
29
29
 
30
30
  base.class_eval do
31
31
  validates_presence_of :email, if: :email_required?
32
- if Devise.activerecord51?
33
- validates_uniqueness_of :email, allow_blank: 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
+ validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :devise_will_save_change_to_email?
33
+ validates_format_of :email, with: email_regexp, allow_blank: true, if: :devise_will_save_change_to_email?
39
34
 
40
35
  validates_presence_of :password, if: :password_required?
41
36
  validates_confirmation_of :password, if: :password_required?
@@ -47,7 +42,7 @@ module Devise
47
42
  unavailable_validations = VALIDATIONS.select { |v| !base.respond_to?(v) }
48
43
 
49
44
  unless unavailable_validations.empty?
50
- raise "Could not use :validatable module since #{base} does not respond " <<
45
+ raise "Could not use :validatable module since #{base} does not respond " \
51
46
  "to the following methods: #{unavailable_validations.to_sentence}."
52
47
  end
53
48
  end
data/lib/devise/models.rb CHANGED
@@ -84,6 +84,7 @@ module Devise
84
84
  end
85
85
 
86
86
  devise_modules_hook! do
87
+ include Devise::Orm
87
88
  include Devise::Models::Authenticatable
88
89
 
89
90
  selected_modules.each do |m|
@@ -1,17 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  begin
4
+ gem "omniauth", ">= 1.0.0"
5
+
4
6
  require "omniauth"
5
- require "omniauth/version"
6
7
  rescue LoadError
7
8
  warn "Could not load 'omniauth'. Please ensure you have the omniauth gem >= 1.0.0 installed and listed in your Gemfile."
8
9
  raise
9
10
  end
10
11
 
11
- unless OmniAuth::VERSION =~ /^1\./
12
- raise "You are using an old OmniAuth version, please ensure you have 1.0.0.pr2 version or later installed."
13
- end
14
-
15
12
  # Clean up the default path_prefix. It will be automatically set by Devise.
16
13
  OmniAuth.config.path_prefix = nil
17
14
 
data/lib/devise/orm.rb ADDED
@@ -0,0 +1,71 @@
1
+ module Devise
2
+ module Orm # :nodoc:
3
+ def self.active_record?(model)
4
+ defined?(ActiveRecord) && model < ActiveRecord::Base
5
+ end
6
+
7
+ def self.active_record_51?(model)
8
+ active_record?(model) && ActiveRecord.gem_version >= Gem::Version.new("5.1.x")
9
+ end
10
+
11
+ def self.included(model)
12
+ if Devise::Orm.active_record_51?(model)
13
+ model.include DirtyTrackingNewMethods
14
+ else
15
+ model.include DirtyTrackingOldMethods
16
+ end
17
+ end
18
+
19
+ module DirtyTrackingNewMethods
20
+ def devise_email_before_last_save
21
+ email_before_last_save
22
+ end
23
+
24
+ def devise_email_in_database
25
+ email_in_database
26
+ end
27
+
28
+ def devise_saved_change_to_email?
29
+ saved_change_to_email?
30
+ end
31
+
32
+ def devise_saved_change_to_encrypted_password?
33
+ saved_change_to_encrypted_password?
34
+ end
35
+
36
+ def devise_will_save_change_to_email?
37
+ will_save_change_to_email?
38
+ end
39
+
40
+ def devise_respond_to_and_will_save_change_to_attribute?(attribute)
41
+ respond_to?("will_save_change_to_#{attribute}?") && send("will_save_change_to_#{attribute}?")
42
+ end
43
+ end
44
+
45
+ module DirtyTrackingOldMethods
46
+ def devise_email_before_last_save
47
+ email_was
48
+ end
49
+
50
+ def devise_email_in_database
51
+ email_was
52
+ end
53
+
54
+ def devise_saved_change_to_email?
55
+ email_changed?
56
+ end
57
+
58
+ def devise_saved_change_to_encrypted_password?
59
+ encrypted_password_changed?
60
+ end
61
+
62
+ def devise_will_save_change_to_email?
63
+ email_changed?
64
+ end
65
+
66
+ def devise_respond_to_and_will_save_change_to_attribute?(attribute)
67
+ respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
68
+ end
69
+ end
70
+ end
71
+ end