devise 4.1.1 → 5.0.4

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 (255) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +68 -111
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +315 -98
  5. data/app/controllers/devise/confirmations_controller.rb +3 -0
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +7 -5
  7. data/app/controllers/devise/passwords_controller.rb +10 -2
  8. data/app/controllers/devise/registrations_controller.rb +42 -20
  9. data/app/controllers/devise/sessions_controller.rb +9 -7
  10. data/app/controllers/devise/unlocks_controller.rb +3 -0
  11. data/app/controllers/devise_controller.rb +19 -3
  12. data/app/helpers/devise_helper.rb +3 -23
  13. data/app/mailers/devise/mailer.rb +10 -4
  14. data/app/views/devise/confirmations/new.html.erb +3 -3
  15. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  16. data/app/views/devise/passwords/edit.html.erb +6 -6
  17. data/app/views/devise/passwords/new.html.erb +4 -4
  18. data/app/views/devise/registrations/edit.html.erb +13 -10
  19. data/app/views/devise/registrations/new.html.erb +9 -9
  20. data/app/views/devise/sessions/new.html.erb +8 -8
  21. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  22. data/app/views/devise/shared/_links.html.erb +13 -13
  23. data/app/views/devise/unlocks/new.html.erb +3 -3
  24. data/config/locales/en.yml +5 -2
  25. data/lib/devise/controllers/helpers.rb +24 -9
  26. data/lib/devise/controllers/rememberable.rb +3 -1
  27. data/lib/devise/controllers/responder.rb +35 -0
  28. data/lib/devise/controllers/scoped_views.rb +2 -0
  29. data/lib/devise/controllers/sign_in_out.rb +31 -21
  30. data/lib/devise/controllers/store_location.rb +25 -7
  31. data/lib/devise/controllers/url_helpers.rb +3 -1
  32. data/lib/devise/delegator.rb +2 -0
  33. data/lib/devise/encryptor.rb +2 -0
  34. data/lib/devise/failure_app.rb +71 -38
  35. data/lib/devise/hooks/activatable.rb +3 -1
  36. data/lib/devise/hooks/csrf_cleaner.rb +8 -1
  37. data/lib/devise/hooks/forgetable.rb +2 -0
  38. data/lib/devise/hooks/lockable.rb +4 -2
  39. data/lib/devise/hooks/proxy.rb +3 -1
  40. data/lib/devise/hooks/rememberable.rb +2 -0
  41. data/lib/devise/hooks/timeoutable.rb +5 -3
  42. data/lib/devise/hooks/trackable.rb +2 -0
  43. data/lib/devise/mailers/helpers.rb +15 -18
  44. data/lib/devise/mapping.rb +4 -2
  45. data/lib/devise/models/authenticatable.rb +58 -44
  46. data/lib/devise/models/confirmable.rb +52 -14
  47. data/lib/devise/models/database_authenticatable.rb +52 -20
  48. data/lib/devise/models/lockable.rb +19 -5
  49. data/lib/devise/models/omniauthable.rb +4 -2
  50. data/lib/devise/models/recoverable.rb +22 -21
  51. data/lib/devise/models/registerable.rb +4 -0
  52. data/lib/devise/models/rememberable.rb +6 -4
  53. data/lib/devise/models/timeoutable.rb +3 -1
  54. data/lib/devise/models/trackable.rb +15 -1
  55. data/lib/devise/models/validatable.rb +10 -6
  56. data/lib/devise/models.rb +4 -1
  57. data/lib/devise/modules.rb +2 -0
  58. data/lib/devise/omniauth/config.rb +2 -0
  59. data/lib/devise/omniauth/url_helpers.rb +2 -51
  60. data/lib/devise/omniauth.rb +4 -5
  61. data/lib/devise/orm/active_record.rb +5 -1
  62. data/lib/devise/orm/mongoid.rb +6 -2
  63. data/lib/devise/orm.rb +80 -0
  64. data/lib/devise/parameter_filter.rb +4 -0
  65. data/lib/devise/parameter_sanitizer.rb +16 -58
  66. data/lib/devise/rails/routes.rb +12 -11
  67. data/lib/devise/rails/warden_compat.rb +2 -0
  68. data/lib/devise/rails.rb +16 -6
  69. data/lib/devise/strategies/authenticatable.rb +3 -1
  70. data/lib/devise/strategies/base.rb +2 -0
  71. data/lib/devise/strategies/database_authenticatable.rb +8 -1
  72. data/lib/devise/strategies/rememberable.rb +2 -0
  73. data/lib/devise/test/controller_helpers.rb +156 -0
  74. data/lib/devise/test/integration_helpers.rb +63 -0
  75. data/lib/devise/time_inflector.rb +2 -0
  76. data/lib/devise/token_generator.rb +2 -0
  77. data/lib/devise/version.rb +3 -1
  78. data/lib/devise.rb +69 -28
  79. data/lib/generators/active_record/devise_generator.rb +38 -16
  80. data/lib/generators/active_record/templates/migration.rb +3 -1
  81. data/lib/generators/active_record/templates/migration_existing.rb +2 -0
  82. data/lib/generators/devise/controllers_generator.rb +4 -2
  83. data/lib/generators/devise/devise_generator.rb +5 -3
  84. data/lib/generators/devise/install_generator.rb +3 -5
  85. data/lib/generators/devise/orm_helpers.rb +5 -3
  86. data/lib/generators/devise/views_generator.rb +8 -9
  87. data/lib/generators/mongoid/devise_generator.rb +7 -5
  88. data/lib/generators/templates/README +9 -8
  89. data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
  90. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +3 -1
  91. data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
  92. data/lib/generators/templates/controllers/registrations_controller.rb +4 -2
  93. data/lib/generators/templates/controllers/sessions_controller.rb +3 -1
  94. data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
  95. data/lib/generators/templates/devise.rb +59 -11
  96. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  97. data/lib/generators/templates/markerb/password_change.markerb +2 -2
  98. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
  99. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
  100. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +5 -2
  101. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +12 -4
  102. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
  103. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
  104. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
  105. metadata +23 -302
  106. data/.gitignore +0 -10
  107. data/.travis.yml +0 -44
  108. data/.yardopts +0 -9
  109. data/CODE_OF_CONDUCT.md +0 -22
  110. data/CONTRIBUTING.md +0 -16
  111. data/Gemfile +0 -30
  112. data/Gemfile.lock +0 -182
  113. data/Rakefile +0 -36
  114. data/bin/test +0 -13
  115. data/devise.gemspec +0 -26
  116. data/devise.png +0 -0
  117. data/gemfiles/Gemfile.rails-4.1-stable +0 -30
  118. data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -170
  119. data/gemfiles/Gemfile.rails-4.2-stable +0 -30
  120. data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
  121. data/gemfiles/Gemfile.rails-5.0-beta +0 -37
  122. data/gemfiles/Gemfile.rails-5.0-beta.lock +0 -199
  123. data/lib/devise/test_helpers.rb +0 -137
  124. data/test/controllers/custom_registrations_controller_test.rb +0 -40
  125. data/test/controllers/custom_strategy_test.rb +0 -64
  126. data/test/controllers/helper_methods_test.rb +0 -22
  127. data/test/controllers/helpers_test.rb +0 -316
  128. data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -51
  129. data/test/controllers/internal_helpers_test.rb +0 -127
  130. data/test/controllers/load_hooks_controller_test.rb +0 -19
  131. data/test/controllers/passwords_controller_test.rb +0 -32
  132. data/test/controllers/sessions_controller_test.rb +0 -106
  133. data/test/controllers/url_helpers_test.rb +0 -65
  134. data/test/delegator_test.rb +0 -19
  135. data/test/devise_test.rb +0 -107
  136. data/test/failure_app_test.rb +0 -320
  137. data/test/generators/active_record_generator_test.rb +0 -83
  138. data/test/generators/controllers_generator_test.rb +0 -48
  139. data/test/generators/devise_generator_test.rb +0 -39
  140. data/test/generators/install_generator_test.rb +0 -24
  141. data/test/generators/mongoid_generator_test.rb +0 -23
  142. data/test/generators/views_generator_test.rb +0 -103
  143. data/test/helpers/devise_helper_test.rb +0 -49
  144. data/test/integration/authenticatable_test.rb +0 -698
  145. data/test/integration/confirmable_test.rb +0 -324
  146. data/test/integration/database_authenticatable_test.rb +0 -95
  147. data/test/integration/http_authenticatable_test.rb +0 -106
  148. data/test/integration/lockable_test.rb +0 -240
  149. data/test/integration/omniauthable_test.rb +0 -135
  150. data/test/integration/recoverable_test.rb +0 -347
  151. data/test/integration/registerable_test.rb +0 -357
  152. data/test/integration/rememberable_test.rb +0 -211
  153. data/test/integration/timeoutable_test.rb +0 -184
  154. data/test/integration/trackable_test.rb +0 -92
  155. data/test/mailers/confirmation_instructions_test.rb +0 -115
  156. data/test/mailers/reset_password_instructions_test.rb +0 -96
  157. data/test/mailers/unlock_instructions_test.rb +0 -91
  158. data/test/mapping_test.rb +0 -134
  159. data/test/models/authenticatable_test.rb +0 -23
  160. data/test/models/confirmable_test.rb +0 -511
  161. data/test/models/database_authenticatable_test.rb +0 -269
  162. data/test/models/lockable_test.rb +0 -350
  163. data/test/models/omniauthable_test.rb +0 -7
  164. data/test/models/recoverable_test.rb +0 -251
  165. data/test/models/registerable_test.rb +0 -7
  166. data/test/models/rememberable_test.rb +0 -169
  167. data/test/models/serializable_test.rb +0 -49
  168. data/test/models/timeoutable_test.rb +0 -51
  169. data/test/models/trackable_test.rb +0 -41
  170. data/test/models/validatable_test.rb +0 -119
  171. data/test/models_test.rb +0 -153
  172. data/test/omniauth/config_test.rb +0 -57
  173. data/test/omniauth/url_helpers_test.rb +0 -51
  174. data/test/orm/active_record.rb +0 -17
  175. data/test/orm/mongoid.rb +0 -13
  176. data/test/parameter_sanitizer_test.rb +0 -131
  177. data/test/rails_app/Rakefile +0 -6
  178. data/test/rails_app/app/active_record/admin.rb +0 -6
  179. data/test/rails_app/app/active_record/shim.rb +0 -2
  180. data/test/rails_app/app/active_record/user.rb +0 -7
  181. data/test/rails_app/app/active_record/user_on_engine.rb +0 -7
  182. data/test/rails_app/app/active_record/user_on_main_app.rb +0 -7
  183. data/test/rails_app/app/active_record/user_without_email.rb +0 -8
  184. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
  185. data/test/rails_app/app/controllers/admins_controller.rb +0 -6
  186. data/test/rails_app/app/controllers/application_controller.rb +0 -11
  187. data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -30
  188. data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -31
  189. data/test/rails_app/app/controllers/home_controller.rb +0 -29
  190. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
  191. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
  192. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
  193. data/test/rails_app/app/controllers/users_controller.rb +0 -31
  194. data/test/rails_app/app/helpers/application_helper.rb +0 -3
  195. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -3
  196. data/test/rails_app/app/mailers/users/mailer.rb +0 -3
  197. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -4
  198. data/test/rails_app/app/mongoid/admin.rb +0 -29
  199. data/test/rails_app/app/mongoid/shim.rb +0 -23
  200. data/test/rails_app/app/mongoid/user.rb +0 -39
  201. data/test/rails_app/app/mongoid/user_on_engine.rb +0 -39
  202. data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -39
  203. data/test/rails_app/app/mongoid/user_without_email.rb +0 -33
  204. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  205. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  206. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  207. data/test/rails_app/app/views/home/index.html.erb +0 -1
  208. data/test/rails_app/app/views/home/join.html.erb +0 -1
  209. data/test/rails_app/app/views/home/private.html.erb +0 -1
  210. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  211. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  212. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  213. data/test/rails_app/app/views/users/index.html.erb +0 -1
  214. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  215. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  216. data/test/rails_app/bin/bundle +0 -3
  217. data/test/rails_app/bin/rails +0 -4
  218. data/test/rails_app/bin/rake +0 -4
  219. data/test/rails_app/config/application.rb +0 -44
  220. data/test/rails_app/config/boot.rb +0 -14
  221. data/test/rails_app/config/database.yml +0 -18
  222. data/test/rails_app/config/environment.rb +0 -5
  223. data/test/rails_app/config/environments/development.rb +0 -30
  224. data/test/rails_app/config/environments/production.rb +0 -84
  225. data/test/rails_app/config/environments/test.rb +0 -46
  226. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  227. data/test/rails_app/config/initializers/devise.rb +0 -180
  228. data/test/rails_app/config/initializers/inflections.rb +0 -2
  229. data/test/rails_app/config/initializers/secret_token.rb +0 -3
  230. data/test/rails_app/config/initializers/session_store.rb +0 -1
  231. data/test/rails_app/config/routes.rb +0 -126
  232. data/test/rails_app/config.ru +0 -4
  233. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
  234. data/test/rails_app/db/schema.rb +0 -55
  235. data/test/rails_app/lib/shared_admin.rb +0 -17
  236. data/test/rails_app/lib/shared_user.rb +0 -30
  237. data/test/rails_app/lib/shared_user_without_email.rb +0 -26
  238. data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -13
  239. data/test/rails_app/public/404.html +0 -26
  240. data/test/rails_app/public/422.html +0 -26
  241. data/test/rails_app/public/500.html +0 -26
  242. data/test/rails_app/public/favicon.ico +0 -0
  243. data/test/rails_test.rb +0 -9
  244. data/test/routes_test.rb +0 -279
  245. data/test/support/action_controller/record_identifier.rb +0 -10
  246. data/test/support/assertions.rb +0 -39
  247. data/test/support/helpers.rb +0 -77
  248. data/test/support/http_method_compatibility.rb +0 -51
  249. data/test/support/integration.rb +0 -92
  250. data/test/support/locale/en.yml +0 -8
  251. data/test/support/mongoid.yml +0 -6
  252. data/test/support/webrat/integrations/rails.rb +0 -33
  253. data/test/test_helper.rb +0 -34
  254. data/test/test_helpers_test.rb +0 -178
  255. data/test/test_models.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "devise/hooks/lockable"
2
4
 
3
5
  module Devise
@@ -16,7 +18,7 @@ module Devise
16
18
  # * +maximum_attempts+: how many attempts should be accepted before blocking the user.
17
19
  # * +lock_strategy+: lock the user account by :failed_attempts or :none.
18
20
  # * +unlock_strategy+: unlock the user account by :time, :email, :both or :none.
19
- # * +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.
20
22
  # * +unlock_keys+: the keys you want to use when locking and unlocking an account
21
23
  #
22
24
  module Lockable
@@ -55,6 +57,14 @@ module Devise
55
57
  save(validate: false)
56
58
  end
57
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
+
58
68
  # Verifies whether a user is locked or not.
59
69
  def access_locked?
60
70
  !!locked_at && !lock_expired?
@@ -74,7 +84,7 @@ module Devise
74
84
  if_access_locked { send_unlock_instructions }
75
85
  end
76
86
 
77
- # Overwrites active_for_authentication? from Devise::Models::Activatable for locking purposes
87
+ # Overwrites active_for_authentication? from Devise::Models::Authenticatable for locking purposes
78
88
  # by verifying whether a user is active to sign in or not based on locked?
79
89
  def active_for_authentication?
80
90
  super && !access_locked?
@@ -99,8 +109,7 @@ module Devise
99
109
  if super && !access_locked?
100
110
  true
101
111
  else
102
- self.failed_attempts ||= 0
103
- self.failed_attempts += 1
112
+ increment_failed_attempts
104
113
  if attempts_exceeded?
105
114
  lock_access! unless access_locked?
106
115
  else
@@ -110,6 +119,11 @@ module Devise
110
119
  end
111
120
  end
112
121
 
122
+ def increment_failed_attempts
123
+ self.class.increment_counter(:failed_attempts, id)
124
+ reload
125
+ end
126
+
113
127
  def unauthenticated_message
114
128
  # If set to paranoid mode, do not show the locked message because it
115
129
  # leaks the existence of an account.
@@ -162,7 +176,7 @@ module Devise
162
176
  # unlock instructions to it. If not user is found, returns a new user
163
177
  # with an email not found error.
164
178
  # Options must contain the user's unlock keys
165
- def send_unlock_instructions(attributes={})
179
+ def send_unlock_instructions(attributes = {})
166
180
  lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
167
181
  lockable.resend_unlock_instructions if lockable.persisted?
168
182
  lockable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/omniauth'
2
4
 
3
5
  module Devise
@@ -6,11 +8,11 @@ module Devise
6
8
  #
7
9
  # == Options
8
10
  #
9
- # Oauthable adds the following options to devise_for:
11
+ # Oauthable adds the following options to +devise+:
10
12
  #
11
13
  # * +omniauth_providers+: Which providers are available to this model. It expects an array:
12
14
  #
13
- # devise_for :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
15
+ # devise :database_authenticatable, :omniauthable, omniauth_providers: [:twitter]
14
16
  #
15
17
  module Omniauthable
16
18
  extend ActiveSupport::Concern
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Models
3
5
 
@@ -5,7 +7,7 @@ module Devise
5
7
  #
6
8
  # ==Options
7
9
  #
8
- # Recoverable adds the following options to devise_for:
10
+ # Recoverable adds the following options to +devise+:
9
11
  #
10
12
  # * +reset_password_keys+: the keys you want to use when recovering the password for an account
11
13
  # * +reset_password_within+: the time period within which the password must be reset or the token expires.
@@ -27,30 +29,20 @@ module Devise
27
29
  end
28
30
 
29
31
  included do
30
- before_update do
31
- if (respond_to?(:email_changed?) && email_changed?) || encrypted_password_changed?
32
- clear_reset_password_token
33
- end
34
- end
32
+ before_update :clear_reset_password_token, if: :clear_reset_password_token?
35
33
  end
36
34
 
37
35
  # Update password saving the record and clearing token. Returns true if
38
36
  # the passwords are valid and the record was saved, false otherwise.
39
37
  def reset_password(new_password, new_password_confirmation)
40
- self.password = new_password
41
- self.password_confirmation = new_password_confirmation
42
-
43
- if respond_to?(:after_password_reset) && valid?
44
- ActiveSupport::Deprecation.warn "after_password_reset is deprecated"
45
- after_password_reset
38
+ if new_password.present?
39
+ self.password = new_password
40
+ self.password_confirmation = new_password_confirmation
41
+ save
42
+ else
43
+ errors.add(:password, :blank)
44
+ false
46
45
  end
47
-
48
- save
49
- end
50
-
51
- def reset_password!(new_password, new_password_confirmation)
52
- ActiveSupport::Deprecation.warn "reset_password! is deprecated in favor of reset_password"
53
- reset_password(new_password, new_password_confirmation)
54
46
  end
55
47
 
56
48
  # Resets reset password token and send reset password instructions by email.
@@ -107,6 +99,15 @@ module Devise
107
99
  send_devise_notification(:reset_password_instructions, token, {})
108
100
  end
109
101
 
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)
106
+ end
107
+
108
+ authentication_keys_changed || encrypted_password_changed
109
+ end
110
+
110
111
  module ClassMethods
111
112
  # Attempt to find a user by password reset token. If a user is found, return it
112
113
  # If a user is not found, return nil
@@ -119,7 +120,7 @@ module Devise
119
120
  # password instructions to it. If user is not found, returns a new user
120
121
  # with an email not found error.
121
122
  # Attributes must contain the user's email
122
- def send_reset_password_instructions(attributes={})
123
+ def send_reset_password_instructions(attributes = {})
123
124
  recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
124
125
  recoverable.send_reset_password_instructions if recoverable.persisted?
125
126
  recoverable
@@ -130,7 +131,7 @@ module Devise
130
131
  # try saving the record. If not user is found, returns a new user
131
132
  # containing an error in reset_password_token attribute.
132
133
  # Attributes must contain reset_password_token, password and confirmation
133
- def reset_password_by_token(attributes={})
134
+ def reset_password_by_token(attributes = {})
134
135
  original_token = attributes[:reset_password_token]
135
136
  reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
136
137
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Models
3
5
  # Registerable is responsible for everything related to registering a new
@@ -19,6 +21,8 @@ module Devise
19
21
  def new_with_session(params, session)
20
22
  new(params)
21
23
  end
24
+
25
+ Devise::Models.config(self, :sign_in_after_change_password)
22
26
  end
23
27
  end
24
28
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/strategies/rememberable'
2
4
  require 'devise/hooks/rememberable'
3
5
  require 'devise/hooks/forgetable'
4
6
 
5
7
  module Devise
6
8
  module Models
7
- # Rememberable manages generating and clearing token for remember the user
9
+ # Rememberable manages generating and clearing token for remembering the user
8
10
  # from a saved cookie. Rememberable also has utility methods for dealing
9
11
  # with serializing the user into the cookie and back from the cookie, trying
10
12
  # to lookup the record based on the saved information.
@@ -13,7 +15,7 @@ module Devise
13
15
  #
14
16
  # == Options
15
17
  #
16
- # Rememberable adds the following options in devise_for:
18
+ # Rememberable adds the following options to +devise+:
17
19
  #
18
20
  # * +remember_for+: the time you want the user will be remembered without
19
21
  # asking for credentials. After this time the user will be blocked and
@@ -74,7 +76,7 @@ module Devise
74
76
  elsif respond_to?(:authenticatable_salt) && (salt = authenticatable_salt.presence)
75
77
  salt
76
78
  else
77
- raise "authenticable_salt returned nil for the #{self.class.name} model. " \
79
+ raise "authenticatable_salt returned nil for the #{self.class.name} model. " \
78
80
  "In order to use rememberable, you must ensure a password is always set " \
79
81
  "or have a remember_token column in your model or implement your own " \
80
82
  "rememberable_value in the model with custom logic."
@@ -100,7 +102,7 @@ module Devise
100
102
 
101
103
  def remember_me?(token, generated_at)
102
104
  # TODO: Normalize the JSON type coercion along with the Timeoutable hook
103
- # in a single place https://github.com/plataformatec/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
105
+ # in a single place https://github.com/heartcombo/devise/blob/ffe9d6d406e79108cf32a2c6a1d0b3828849c40b/lib/devise/hooks/timeoutable.rb#L14-L18
104
106
  if generated_at.is_a?(String)
105
107
  generated_at = time_from_json(generated_at)
106
108
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/hooks/timeoutable'
2
4
 
3
5
  module Devise
@@ -9,7 +11,7 @@ module Devise
9
11
  #
10
12
  # == Options
11
13
  #
12
- # Timeoutable adds the following options to devise_for:
14
+ # Timeoutable adds the following options to +devise+:
13
15
  #
14
16
  # * +timeout_in+: the interval to timeout the user session without activity.
15
17
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/hooks/trackable'
2
4
 
3
5
  module Devise
@@ -20,7 +22,7 @@ module Devise
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.remote_ip
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
 
@@ -29,9 +31,21 @@ module Devise
29
31
  end
30
32
 
31
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/heartcombo/devise/issues/4673 for more details.
37
+ return if new_record?
38
+
32
39
  update_tracked_fields(request)
33
40
  save(validate: false)
34
41
  end
42
+
43
+ protected
44
+
45
+ def extract_ip_from(request)
46
+ request.remote_ip
47
+ end
48
+
35
49
  end
36
50
  end
37
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.
@@ -7,11 +9,13 @@ module Devise
7
9
  #
8
10
  # == Options
9
11
  #
10
- # Validatable adds the following options to devise_for:
12
+ # Validatable adds the following options to +devise+:
11
13
  #
12
14
  # * +email_regexp+: the regular expression used to validate e-mails;
13
- # * +password_length+: a range expressing password length. Defaults to 8..72.
15
+ # * +password_length+: a range expressing password length. Defaults to 6..128.
14
16
  #
17
+ # Since +password_length+ is applied in a proc within `validates_length_of` it can be overridden
18
+ # at runtime.
15
19
  module Validatable
16
20
  # All validations used by this module.
17
21
  VALIDATIONS = [:validates_presence_of, :validates_uniqueness_of, :validates_format_of,
@@ -27,12 +31,12 @@ module Devise
27
31
 
28
32
  base.class_eval do
29
33
  validates_presence_of :email, if: :email_required?
30
- validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
31
- validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
34
+ validates_uniqueness_of :email, allow_blank: true, case_sensitive: true, if: :devise_will_save_change_to_email?
35
+ validates_format_of :email, with: email_regexp, allow_blank: true, if: :devise_will_save_change_to_email?
32
36
 
33
37
  validates_presence_of :password, if: :password_required?
34
38
  validates_confirmation_of :password, if: :password_required?
35
- validates_length_of :password, within: password_length, allow_blank: true
39
+ validates_length_of :password, minimum: proc { password_length.min }, maximum: proc { password_length.max }, allow_blank: true
36
40
  end
37
41
  end
38
42
 
@@ -40,7 +44,7 @@ module Devise
40
44
  unavailable_validations = VALIDATIONS.select { |v| !base.respond_to?(v) }
41
45
 
42
46
  unless unavailable_validations.empty?
43
- raise "Could not use :validatable module since #{base} does not respond " <<
47
+ raise "Could not use :validatable module since #{base} does not respond " \
44
48
  "to the following methods: #{unavailable_validations.to_sentence}."
45
49
  end
46
50
  end
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::DatabaseAuthenticatable, :stretches)
17
+ # Devise::Models.config(Devise::Models::DatabaseAuthenticatable, :stretches)
16
18
  #
17
19
  # The line above creates:
18
20
  #
@@ -82,6 +84,7 @@ module Devise
82
84
  end
83
85
 
84
86
  devise_modules_hook! do
87
+ include Devise::Orm
85
88
  include Devise::Models::Authenticatable
86
89
 
87
90
  selected_modules.each do |m|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/core_ext/object/with_options'
2
4
 
3
5
  Devise.with_options model: true do |d|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module OmniAuth
3
5
  class StrategyNotFound < NameError
@@ -1,57 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module OmniAuth
3
5
  module UrlHelpers
4
- def self.define_helpers(mapping)
5
- return unless mapping.omniauthable?
6
-
7
- mapping = mapping.name
8
-
9
- class_eval do
10
- define_method("#{mapping}_omniauth_authorize_path") do |provider, *args|
11
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
12
- [Devise] #{mapping}_omniauth_authorize_path(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
13
-
14
- Please use #{mapping}_#{provider}_omniauth_authorize_path instead.
15
- DEPRECATION
16
- send("#{mapping}_#{provider}_omniauth_authorize_path", *args)
17
- end
18
-
19
- define_method("#{mapping}_omniauth_authorize_url") do |provider, *args|
20
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
21
- [Devise] #{mapping}_omniauth_authorize_url(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
22
-
23
- Please use #{mapping}_#{provider}_omniauth_authorize_url instead.
24
- DEPRECATION
25
- send("#{mapping}_#{provider}_omniauth_authorize_url", *args)
26
- end
27
-
28
- define_method("#{mapping}_omniauth_callback_path") do |provider, *args|
29
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
30
- [Devise] #{mapping}_omniauth_callback_path(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
31
-
32
- Please use #{mapping}_#{provider}_omniauth_callback_path instead.
33
- DEPRECATION
34
- send("#{mapping}_#{provider}_omniauth_callback_path", *args)
35
- end
36
-
37
- define_method("#{mapping}_omniauth_callback_url") do |provider, *args|
38
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
39
- [Devise] #{mapping}_omniauth_callback_url(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
40
-
41
- Please use #{mapping}_#{provider}_omniauth_callback_url instead.
42
- DEPRECATION
43
- send("#{mapping}_#{provider}_omniauth_callback_url", *args)
44
- end
45
- end
46
-
47
- ActiveSupport.on_load(:action_controller) do
48
- if respond_to?(:helper_method)
49
- helper_method "#{mapping}_omniauth_authorize_path", "#{mapping}_omniauth_authorize_url"
50
- helper_method "#{mapping}_omniauth_callback_path", "#{mapping}_omniauth_callback_url"
51
- end
52
- end
53
- end
54
-
55
6
  def omniauth_authorize_path(resource_or_scope, provider, *args)
56
7
  scope = Devise::Mapping.find_scope!(resource_or_scope)
57
8
  _devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_path", *args)
@@ -1,15 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
4
+ gem "omniauth", ">= 1.0.0"
5
+
2
6
  require "omniauth"
3
- require "omniauth/version"
4
7
  rescue LoadError
5
8
  warn "Could not load 'omniauth'. Please ensure you have the omniauth gem >= 1.0.0 installed and listed in your Gemfile."
6
9
  raise
7
10
  end
8
11
 
9
- unless OmniAuth::VERSION =~ /^1\./
10
- raise "You are using an old OmniAuth version, please ensure you have 1.0.0.pr2 version or later installed."
11
- end
12
-
13
12
  # Clean up the default path_prefix. It will be automatically set by Devise.
14
13
  OmniAuth.config.path_prefix = nil
15
14
 
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'orm_adapter/adapters/active_record'
2
4
 
3
- ActiveRecord::Base.extend Devise::Models
5
+ ActiveSupport.on_load(:active_record) do
6
+ extend Devise::Models
7
+ end
@@ -1,3 +1,7 @@
1
- require 'orm_adapter/adapters/mongoid'
1
+ # frozen_string_literal: true
2
2
 
3
- Mongoid::Document::ClassMethods.send :include, Devise::Models
3
+ ActiveSupport.on_load(:mongoid) do
4
+ require 'orm_adapter/adapters/mongoid'
5
+
6
+ Mongoid::Document::ClassMethods.send :include, Devise::Models
7
+ end
data/lib/devise/orm.rb ADDED
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ module Orm # :nodoc:
5
+ def self.active_record?(model)
6
+ defined?(ActiveRecord) && model < ActiveRecord::Base
7
+ end
8
+
9
+ def self.included(model)
10
+ if Devise::Orm.active_record?(model)
11
+ model.include DirtyTrackingActiveRecordMethods
12
+ else
13
+ model.include DirtyTrackingMongoidMethods
14
+ end
15
+ end
16
+
17
+ module DirtyTrackingActiveRecordMethods
18
+ def devise_email_before_last_save
19
+ email_before_last_save
20
+ end
21
+
22
+ def devise_email_in_database
23
+ email_in_database
24
+ end
25
+
26
+ def devise_saved_change_to_email?
27
+ saved_change_to_email?
28
+ end
29
+
30
+ def devise_saved_change_to_encrypted_password?
31
+ saved_change_to_encrypted_password?
32
+ end
33
+
34
+ def devise_will_save_change_to_email?
35
+ will_save_change_to_email?
36
+ end
37
+
38
+ def devise_unconfirmed_email_will_change!
39
+ unconfirmed_email_will_change!
40
+ end
41
+
42
+ def devise_respond_to_and_will_save_change_to_attribute?(attribute)
43
+ respond_to?("will_save_change_to_#{attribute}?") && send("will_save_change_to_#{attribute}?")
44
+ end
45
+ end
46
+
47
+ module DirtyTrackingMongoidMethods
48
+ def devise_email_before_last_save
49
+ respond_to?(:email_previously_was) ? email_previously_was : email_was
50
+ end
51
+
52
+ def devise_email_in_database
53
+ email_was
54
+ end
55
+
56
+ def devise_saved_change_to_email?
57
+ respond_to?(:email_previously_changed?) ? email_previously_changed? : email_changed?
58
+ end
59
+
60
+ def devise_saved_change_to_encrypted_password?
61
+ respond_to?(:encrypted_password_previously_changed?) ? encrypted_password_previously_changed? : encrypted_password_changed?
62
+ end
63
+
64
+ def devise_will_save_change_to_email?
65
+ email_changed?
66
+ end
67
+
68
+ def devise_unconfirmed_email_will_change!
69
+ # Mongoid's will_change! doesn't force unchanged attributes into updates,
70
+ # so we override changed_attributes to make it see a difference.
71
+ unconfirmed_email_will_change!
72
+ changed_attributes["unconfirmed_email"] = nil
73
+ end
74
+
75
+ def devise_respond_to_and_will_save_change_to_attribute?(attribute)
76
+ respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
77
+ end
78
+ end
79
+ end
80
+ 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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  # The +ParameterSanitizer+ deals with permitting specific parameters values
3
5
  # for each +Devise+ scope in the application.
@@ -68,12 +70,6 @@ module Devise
68
70
  def sanitize(action)
69
71
  permissions = @permitted[action]
70
72
 
71
- # DEPRECATED: Remove this branch on Devise 4.2.
72
- if respond_to?(action, true)
73
- deprecate_instance_method_sanitization(action)
74
- return cast_to_hash send(action)
75
- end
76
-
77
73
  if permissions.respond_to?(:call)
78
74
  cast_to_hash permissions.call(default_params)
79
75
  elsif permissions.present?
@@ -127,17 +123,6 @@ module Devise
127
123
  end
128
124
  end
129
125
 
130
- # DEPRECATED: Remove this method on Devise 4.2.
131
- def for(action, &block) # :nodoc:
132
- if block_given?
133
- deprecate_for_with_block(action)
134
- permit(action, &block)
135
- else
136
- deprecate_for_without_block(action)
137
- @permitted[action] or unknown_action!(action)
138
- end
139
- end
140
-
141
126
  private
142
127
 
143
128
  # Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
@@ -145,12 +130,23 @@ module Devise
145
130
  #
146
131
  # Returns an +ActiveSupport::HashWithIndifferentAccess+.
147
132
  def cast_to_hash(params)
148
- # TODO: Remove the `with_indifferent_access` method call when we only support Rails 5+.
149
- params && params.to_h.with_indifferent_access
133
+ params && params.to_h
150
134
  end
151
135
 
152
136
  def default_params
153
- @params.fetch(@resource_name, {})
137
+ if hashable_resource_params?
138
+ @params.fetch(@resource_name)
139
+ else
140
+ empty_params
141
+ end
142
+ end
143
+
144
+ def hashable_resource_params?
145
+ @params[@resource_name].respond_to?(:permit)
146
+ end
147
+
148
+ def empty_params
149
+ ActionController::Parameters.new({})
154
150
  end
155
151
 
156
152
  def permit_keys(parameters, keys)
@@ -172,43 +168,5 @@ module Devise
172
168
  devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
173
169
  MESSAGE
174
170
  end
175
-
176
- def deprecate_for_with_block(action)
177
- ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
178
- [Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.2.
179
- Please use the `permit` method:
180
-
181
- devise_parameter_sanitizer.permit(:#{action}) do |user|
182
- # Your block here.
183
- end
184
- MESSAGE
185
- end
186
-
187
- def deprecate_for_without_block(action)
188
- ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
189
- [Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.2.
190
- Please use the `permit` method to add or remove any key:
191
-
192
- To add any new key, use the `keys` keyword argument:
193
- devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
194
-
195
- To remove any existing key, use the `except` keyword argument:
196
- devise_parameter_sanitizer.permit(:#{action}, except: [:email])
197
- MESSAGE
198
- end
199
-
200
- def deprecate_instance_method_sanitization(action)
201
- ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
202
- [Devise] Parameter sanitization through a "#{self.class.name}##{action}" method is deprecated and it will be removed from Devise 4.2.
203
- Please use the `permit` method on your sanitizer `initialize` method.
204
-
205
- class #{self.class.name} < Devise::ParameterSanitizer
206
- def initialize(*)
207
- super
208
- permit(:#{action}, keys: [:param1, :param2, :param3])
209
- end
210
- end
211
- MESSAGE
212
- end
213
171
  end
214
172
  end