devise_token_auth_multi_email 0.9.0

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 (183) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +13 -0
  3. data/README.md +97 -0
  4. data/Rakefile +42 -0
  5. data/app/controllers/devise_token_auth/application_controller.rb +100 -0
  6. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +68 -0
  7. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +199 -0
  8. data/app/controllers/devise_token_auth/confirmations_controller.rb +89 -0
  9. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +284 -0
  10. data/app/controllers/devise_token_auth/passwords_controller.rb +216 -0
  11. data/app/controllers/devise_token_auth/registrations_controller.rb +205 -0
  12. data/app/controllers/devise_token_auth/sessions_controller.rb +153 -0
  13. data/app/controllers/devise_token_auth/token_validations_controller.rb +31 -0
  14. data/app/controllers/devise_token_auth/unlocks_controller.rb +94 -0
  15. data/app/models/devise_token_auth/concerns/active_record_support.rb +18 -0
  16. data/app/models/devise_token_auth/concerns/confirmable_support.rb +28 -0
  17. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  18. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +31 -0
  19. data/app/models/devise_token_auth/concerns/user.rb +282 -0
  20. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +39 -0
  21. data/app/validators/devise_token_auth_email_validator.rb +31 -0
  22. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  23. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  24. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  25. data/app/views/devise_token_auth/omniauth_external_window.html.erb +38 -0
  26. data/config/locales/da-DK.yml +52 -0
  27. data/config/locales/de.yml +51 -0
  28. data/config/locales/en.yml +60 -0
  29. data/config/locales/es.yml +51 -0
  30. data/config/locales/fa.yml +60 -0
  31. data/config/locales/fr.yml +51 -0
  32. data/config/locales/he.yml +52 -0
  33. data/config/locales/it.yml +48 -0
  34. data/config/locales/ja.yml +60 -0
  35. data/config/locales/ko.yml +51 -0
  36. data/config/locales/nl.yml +32 -0
  37. data/config/locales/pl.yml +51 -0
  38. data/config/locales/pt-BR.yml +48 -0
  39. data/config/locales/pt.yml +51 -0
  40. data/config/locales/ro.yml +48 -0
  41. data/config/locales/ru.yml +52 -0
  42. data/config/locales/sq.yml +48 -0
  43. data/config/locales/sv.yml +52 -0
  44. data/config/locales/uk.yml +61 -0
  45. data/config/locales/vi.yml +52 -0
  46. data/config/locales/zh-CN.yml +48 -0
  47. data/config/locales/zh-HK.yml +50 -0
  48. data/config/locales/zh-TW.yml +50 -0
  49. data/lib/devise_token_auth/blacklist.rb +6 -0
  50. data/lib/devise_token_auth/controllers/helpers.rb +157 -0
  51. data/lib/devise_token_auth/controllers/url_helpers.rb +10 -0
  52. data/lib/devise_token_auth/engine.rb +105 -0
  53. data/lib/devise_token_auth/errors.rb +8 -0
  54. data/lib/devise_token_auth/rails/routes.rb +122 -0
  55. data/lib/devise_token_auth/token_factory.rb +126 -0
  56. data/lib/devise_token_auth/url.rb +44 -0
  57. data/lib/devise_token_auth/version.rb +5 -0
  58. data/lib/devise_token_auth.rb +14 -0
  59. data/lib/generators/devise_token_auth/USAGE +31 -0
  60. data/lib/generators/devise_token_auth/install_generator.rb +91 -0
  61. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  62. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  63. data/lib/generators/devise_token_auth/install_views_generator.rb +18 -0
  64. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +66 -0
  65. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +49 -0
  66. data/lib/generators/devise_token_auth/templates/user.rb.erb +9 -0
  67. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
  68. data/lib/tasks/devise_token_auth_tasks.rake +6 -0
  69. data/test/controllers/custom/custom_confirmations_controller_test.rb +25 -0
  70. data/test/controllers/custom/custom_omniauth_callbacks_controller_test.rb +33 -0
  71. data/test/controllers/custom/custom_passwords_controller_test.rb +79 -0
  72. data/test/controllers/custom/custom_registrations_controller_test.rb +63 -0
  73. data/test/controllers/custom/custom_sessions_controller_test.rb +39 -0
  74. data/test/controllers/custom/custom_token_validations_controller_test.rb +42 -0
  75. data/test/controllers/demo_group_controller_test.rb +151 -0
  76. data/test/controllers/demo_mang_controller_test.rb +313 -0
  77. data/test/controllers/demo_user_controller_test.rb +658 -0
  78. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +275 -0
  79. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +438 -0
  80. data/test/controllers/devise_token_auth/passwords_controller_test.rb +893 -0
  81. data/test/controllers/devise_token_auth/registrations_controller_test.rb +920 -0
  82. data/test/controllers/devise_token_auth/sessions_controller_test.rb +605 -0
  83. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +142 -0
  84. data/test/controllers/devise_token_auth/unlocks_controller_test.rb +235 -0
  85. data/test/controllers/overrides/confirmations_controller_test.rb +47 -0
  86. data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +53 -0
  87. data/test/controllers/overrides/passwords_controller_test.rb +64 -0
  88. data/test/controllers/overrides/registrations_controller_test.rb +46 -0
  89. data/test/controllers/overrides/sessions_controller_test.rb +35 -0
  90. data/test/controllers/overrides/token_validations_controller_test.rb +43 -0
  91. data/test/dummy/README.rdoc +28 -0
  92. data/test/dummy/app/active_record/confirmable_user.rb +11 -0
  93. data/test/dummy/app/active_record/lockable_user.rb +7 -0
  94. data/test/dummy/app/active_record/mang.rb +5 -0
  95. data/test/dummy/app/active_record/only_email_user.rb +7 -0
  96. data/test/dummy/app/active_record/scoped_user.rb +9 -0
  97. data/test/dummy/app/active_record/unconfirmable_user.rb +9 -0
  98. data/test/dummy/app/active_record/unregisterable_user.rb +9 -0
  99. data/test/dummy/app/active_record/user.rb +6 -0
  100. data/test/dummy/app/controllers/application_controller.rb +14 -0
  101. data/test/dummy/app/controllers/auth_origin_controller.rb +7 -0
  102. data/test/dummy/app/controllers/custom/confirmations_controller.rb +13 -0
  103. data/test/dummy/app/controllers/custom/omniauth_callbacks_controller.rb +13 -0
  104. data/test/dummy/app/controllers/custom/passwords_controller.rb +39 -0
  105. data/test/dummy/app/controllers/custom/registrations_controller.rb +39 -0
  106. data/test/dummy/app/controllers/custom/sessions_controller.rb +29 -0
  107. data/test/dummy/app/controllers/custom/token_validations_controller.rb +19 -0
  108. data/test/dummy/app/controllers/demo_group_controller.rb +15 -0
  109. data/test/dummy/app/controllers/demo_mang_controller.rb +14 -0
  110. data/test/dummy/app/controllers/demo_user_controller.rb +27 -0
  111. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +29 -0
  112. data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +16 -0
  113. data/test/dummy/app/controllers/overrides/passwords_controller.rb +36 -0
  114. data/test/dummy/app/controllers/overrides/registrations_controller.rb +29 -0
  115. data/test/dummy/app/controllers/overrides/sessions_controller.rb +36 -0
  116. data/test/dummy/app/controllers/overrides/token_validations_controller.rb +23 -0
  117. data/test/dummy/app/helpers/application_helper.rb +1058 -0
  118. data/test/dummy/app/models/concerns/favorite_color.rb +19 -0
  119. data/test/dummy/app/mongoid/confirmable_user.rb +52 -0
  120. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  121. data/test/dummy/app/mongoid/mang.rb +46 -0
  122. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  123. data/test/dummy/app/mongoid/scoped_user.rb +50 -0
  124. data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
  125. data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
  126. data/test/dummy/app/mongoid/user.rb +49 -0
  127. data/test/dummy/app/views/layouts/application.html.erb +12 -0
  128. data/test/dummy/config/application.rb +50 -0
  129. data/test/dummy/config/application.yml.bk +0 -0
  130. data/test/dummy/config/boot.rb +11 -0
  131. data/test/dummy/config/environment.rb +7 -0
  132. data/test/dummy/config/environments/development.rb +36 -0
  133. data/test/dummy/config/environments/production.rb +68 -0
  134. data/test/dummy/config/environments/test.rb +58 -0
  135. data/test/dummy/config/initializers/backtrace_silencers.rb +9 -0
  136. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  137. data/test/dummy/config/initializers/devise.rb +290 -0
  138. data/test/dummy/config/initializers/devise_token_auth.rb +55 -0
  139. data/test/dummy/config/initializers/figaro.rb +3 -0
  140. data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  141. data/test/dummy/config/initializers/inflections.rb +18 -0
  142. data/test/dummy/config/initializers/mime_types.rb +6 -0
  143. data/test/dummy/config/initializers/omniauth.rb +11 -0
  144. data/test/dummy/config/initializers/session_store.rb +5 -0
  145. data/test/dummy/config/initializers/wrap_parameters.rb +16 -0
  146. data/test/dummy/config/routes.rb +57 -0
  147. data/test/dummy/config/spring.rb +3 -0
  148. data/test/dummy/config.ru +18 -0
  149. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +58 -0
  150. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +57 -0
  151. data/test/dummy/db/migrate/20140829044006_add_operating_thetan_to_user.rb +8 -0
  152. data/test/dummy/db/migrate/20140916224624_add_favorite_color_to_mangs.rb +7 -0
  153. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +55 -0
  154. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +56 -0
  155. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +56 -0
  156. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +56 -0
  157. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +56 -0
  158. data/test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb +49 -0
  159. data/test/dummy/db/schema.rb +198 -0
  160. data/test/dummy/lib/migration_database_helper.rb +43 -0
  161. data/test/dummy/tmp/generators/app/models/mang.rb +9 -0
  162. data/test/dummy/tmp/generators/app/models/user.rb +9 -0
  163. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +60 -0
  164. data/test/dummy/tmp/generators/config/routes.rb +9 -0
  165. data/test/dummy/tmp/generators/db/migrate/20210305040222_devise_token_auth_create_mangs.rb +49 -0
  166. data/test/dummy/tmp/generators/db/migrate/20210305040222_devise_token_auth_create_users.rb +49 -0
  167. data/test/factories/users.rb +41 -0
  168. data/test/lib/devise_token_auth/blacklist_test.rb +19 -0
  169. data/test/lib/devise_token_auth/rails/custom_routes_test.rb +29 -0
  170. data/test/lib/devise_token_auth/rails/routes_test.rb +87 -0
  171. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  172. data/test/lib/devise_token_auth/url_test.rb +26 -0
  173. data/test/lib/generators/devise_token_auth/install_generator_test.rb +217 -0
  174. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +222 -0
  175. data/test/lib/generators/devise_token_auth/install_views_generator_test.rb +25 -0
  176. data/test/models/concerns/mongoid_support_test.rb +31 -0
  177. data/test/models/concerns/tokens_serialization_test.rb +104 -0
  178. data/test/models/confirmable_user_test.rb +35 -0
  179. data/test/models/only_email_user_test.rb +29 -0
  180. data/test/models/user_test.rb +224 -0
  181. data/test/support/controllers/routes.rb +43 -0
  182. data/test/test_helper.rb +134 -0
  183. metadata +502 -0
@@ -0,0 +1,893 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ # was the web request successful?
6
+ # was the user redirected to the right page?
7
+ # was the user successfully authenticated?
8
+ # was the correct object stored in the response?
9
+ # was the appropriate message delivered in the json payload?
10
+
11
+ class DeviseTokenAuth::PasswordsControllerTest < ActionController::TestCase
12
+ describe DeviseTokenAuth::PasswordsController do
13
+ describe 'Password reset' do
14
+ before do
15
+ @resource = create(:user, :confirmed)
16
+ @redirect_url = 'http://ng-token-auth.dev'
17
+ end
18
+
19
+ describe 'not email should return 401' do
20
+ before do
21
+ @auth_headers = @resource.create_new_auth_token
22
+ @new_password = Faker::Internet.password
23
+
24
+ post :create,
25
+ params: { redirect_url: @redirect_url }
26
+ @data = JSON.parse(response.body)
27
+ end
28
+
29
+ test 'response should fail' do
30
+ assert_equal 401, response.status
31
+ end
32
+
33
+ test 'error message should be returned' do
34
+ assert @data['errors']
35
+ assert_equal @data['errors'],
36
+ [I18n.t('devise_token_auth.passwords.missing_email')]
37
+ end
38
+ end
39
+
40
+ describe 'not redirect_url should return 401' do
41
+ before do
42
+ @auth_headers = @resource.create_new_auth_token
43
+ @new_password = Faker::Internet.password
44
+ end
45
+
46
+ describe 'for create' do
47
+ before do
48
+ post :create,
49
+ params: { email: 'chester@cheet.ah' }
50
+ @data = JSON.parse(response.body)
51
+ end
52
+
53
+ test 'response should fail' do
54
+ assert_equal 401, response.status
55
+ end
56
+
57
+ test 'error message should be returned' do
58
+ assert @data['errors']
59
+ assert_equal(
60
+ @data['errors'],
61
+ [I18n.t('devise_token_auth.passwords.missing_redirect_url')]
62
+ )
63
+ end
64
+ end
65
+
66
+ describe 'for edit' do
67
+ before do
68
+ get_reset_token
69
+ get :edit, params: { reset_password_token: @mail_reset_token}
70
+ @data = JSON.parse(response.body)
71
+ end
72
+
73
+ test 'response should fail' do
74
+ assert_equal 401, response.status
75
+ end
76
+
77
+ test 'error message should be returned' do
78
+ assert @data['errors']
79
+ assert_equal(
80
+ @data['errors'],
81
+ [I18n.t('devise_token_auth.passwords.missing_redirect_url')]
82
+ )
83
+ end
84
+ end
85
+ end
86
+
87
+ describe 'request password reset' do
88
+ describe 'unknown user' do
89
+ describe 'without paranoid mode' do
90
+ before do
91
+ post :create,
92
+ params: { email: 'chester@cheet.ah',
93
+ redirect_url: @redirect_url }
94
+ @data = JSON.parse(response.body)
95
+ end
96
+
97
+ test 'unknown user should return 404' do
98
+ assert_equal 404, response.status
99
+ end
100
+
101
+ test 'errors should be returned' do
102
+ assert @data['errors']
103
+ assert_equal @data['errors'],
104
+ [I18n.t('devise_token_auth.passwords.user_not_found',
105
+ email: 'chester@cheet.ah')]
106
+ end
107
+ end
108
+
109
+ describe 'with paranoid mode' do
110
+ before do
111
+ swap Devise, paranoid: true do
112
+ post :create,
113
+ params: { email: 'chester@cheet.ah',
114
+ redirect_url: @redirect_url }
115
+ @data = JSON.parse(response.body)
116
+ end
117
+ end
118
+
119
+ test 'response should return success status' do
120
+ assert_equal 200, response.status
121
+ end
122
+
123
+ test 'response should contain message' do
124
+ assert_equal \
125
+ @data['message'],
126
+ I18n.t('devise_token_auth.passwords.sended_paranoid')
127
+ end
128
+ end
129
+ end
130
+
131
+ describe 'successfully requested password reset' do
132
+ describe 'without paranoid mode' do
133
+ before do
134
+ post :create,
135
+ params: { email: @resource.email,
136
+ redirect_url: @redirect_url }
137
+
138
+ @data = JSON.parse(response.body)
139
+ end
140
+
141
+ test 'response should not contain extra data' do
142
+ assert_nil @data['data']
143
+ end
144
+
145
+ test 'response should contains message' do
146
+ assert_equal \
147
+ @data['message'],
148
+ I18n.t('devise_token_auth.passwords.sended', email: @resource.email)
149
+ end
150
+ end
151
+
152
+ describe 'with paranoid mode' do
153
+ before do
154
+ swap Devise, paranoid: true do
155
+ post :create,
156
+ params: { email: @resource.email,
157
+ redirect_url: @redirect_url }
158
+ @data = JSON.parse(response.body)
159
+ end
160
+ end
161
+
162
+ test 'response should return success status' do
163
+ assert_equal 200, response.status
164
+ end
165
+
166
+ test 'response should contain message' do
167
+ assert_equal \
168
+ @data['message'],
169
+ I18n.t('devise_token_auth.passwords.sended_paranoid')
170
+ end
171
+ end
172
+ end
173
+
174
+ describe 'case-sensitive email' do
175
+ before do
176
+ post :create,
177
+ params: { email: @resource.email,
178
+ redirect_url: @redirect_url }
179
+
180
+ @mail = ActionMailer::Base.deliveries.last
181
+ @resource.reload
182
+ @data = JSON.parse(response.body)
183
+
184
+ @mail_config_name = CGI.unescape(@mail.body.match(/config=([^&]*)&/)[1])
185
+ @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
186
+ @mail_reset_token = @mail.body.match(/reset_password_token=(.*)\"/)[1]
187
+ end
188
+
189
+ test 'response should return success status' do
190
+ assert_equal 200, response.status
191
+ end
192
+
193
+ test 'response should contains message' do
194
+ assert_equal \
195
+ @data['message'],
196
+ I18n.t('devise_token_auth.passwords.sended', email: @resource.email)
197
+ end
198
+
199
+ test 'action should send an email' do
200
+ assert @mail
201
+ end
202
+
203
+ test 'the email should be addressed to the user' do
204
+ assert_equal @mail.to.first, @resource.email
205
+ end
206
+
207
+ test 'the email body should contain a link with redirect url as a query param' do
208
+ assert_equal @redirect_url, @mail_redirect_url
209
+ end
210
+
211
+ test 'the client config name should fall back to "default"' do
212
+ assert_equal 'default', @mail_config_name
213
+ end
214
+
215
+ test 'the email body should contain a link with reset token as a query param' do
216
+ user = User.reset_password_by_token(reset_password_token: @mail_reset_token)
217
+
218
+ assert_equal user.id, @resource.id
219
+ end
220
+
221
+ describe 'password reset link failure' do
222
+ test 'response should return 404' do
223
+ assert_raises(ActionController::RoutingError) do
224
+ get :edit,
225
+ params: { reset_password_token: 'bogus',
226
+ redirect_url: @mail_redirect_url }
227
+ end
228
+ end
229
+ end
230
+
231
+ describe 'password reset link success' do
232
+ describe 'with require_client_password_reset_token is enabled' do
233
+ before do
234
+ DeviseTokenAuth.require_client_password_reset_token = true
235
+ get :edit,
236
+ params: { reset_password_token: @mail_reset_token,
237
+ redirect_url: @mail_redirect_url }
238
+
239
+ @resource.reload
240
+
241
+ raw_qs = response.location.split('?')[1]
242
+ @qs = Rack::Utils.parse_nested_query(raw_qs)
243
+
244
+ @reset_password_token = @qs['reset_password_token']
245
+ end
246
+
247
+ test 'response should have success redirect status' do
248
+ assert_equal 302, response.status
249
+ end
250
+
251
+ test 'response should contain reset_password_token param' do
252
+ assert_equal @mail_reset_token, @qs['reset_password_token']
253
+ end
254
+ end
255
+
256
+ describe 'require_client_password_reset_token is disabled' do
257
+ before do
258
+ DeviseTokenAuth.require_client_password_reset_token = false
259
+ get :edit,
260
+ params: { reset_password_token: @mail_reset_token,
261
+ redirect_url: @mail_redirect_url }
262
+
263
+ @resource.reload
264
+
265
+ raw_qs = response.location.split('?')[1]
266
+ @qs = Rack::Utils.parse_nested_query(raw_qs)
267
+
268
+ @access_token = @qs['access-token']
269
+ @client_id = @qs['client_id']
270
+ @client = @qs['client']
271
+ @expiry = @qs['expiry']
272
+ @reset_password = @qs['reset_password']
273
+ @token = @qs['token']
274
+ @uid = @qs['uid']
275
+ end
276
+
277
+ test 'response should have success redirect status' do
278
+ assert_equal 302, response.status
279
+ end
280
+
281
+ test 'response should contain auth params' do
282
+ assert @access_token
283
+ assert @client
284
+ assert @client_id
285
+ assert @expiry
286
+ assert @reset_password
287
+ assert @token
288
+ assert @uid
289
+ end
290
+
291
+ test 'response auth params should be valid' do
292
+ assert @resource.valid_token?(@token, @client_id)
293
+ assert @resource.valid_token?(@access_token, @client)
294
+ end
295
+
296
+ test 'response should contain reset_password_token param' do
297
+ assert_equal @mail_reset_token, @qs['reset_password_token']
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ describe 'case-insensitive email' do
304
+ before do
305
+ @resource_class = User
306
+ @request_params = {
307
+ email: @resource.email.upcase,
308
+ redirect_url: @redirect_url
309
+ }
310
+ end
311
+
312
+ test 'response should return success status if configured' do
313
+ @resource_class.case_insensitive_keys = [:email]
314
+ post :create, params: @request_params
315
+ assert_equal 200, response.status
316
+ end
317
+
318
+ test 'response should return failure status if not configured' do
319
+ @resource_class.case_insensitive_keys = []
320
+ post :create, params: @request_params
321
+ assert_equal 404, response.status
322
+ end
323
+ end
324
+
325
+ describe 'Checking reset_password_token' do
326
+ before do
327
+ post :create, params: {
328
+ email: @resource.email,
329
+ redirect_url: @redirect_url
330
+ }
331
+
332
+ @mail = ActionMailer::Base.deliveries.last
333
+ @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
334
+ @mail_reset_token = @mail.body.match(/reset_password_token=(.*)\"/)[1]
335
+
336
+ @resource.reload
337
+ end
338
+
339
+ describe 'reset_password_token is valid' do
340
+
341
+ test 'mail_reset_token should be the same as reset_password_token' do
342
+ assert_equal Devise.token_generator.digest(self, :reset_password_token, @mail_reset_token), @resource.reset_password_token
343
+ end
344
+
345
+ test 'reset_password_token should not be rewritten by origin mail_reset_token' do
346
+ get :edit, params: {
347
+ reset_password_token: @mail_reset_token,
348
+ redirect_url: @mail_redirect_url
349
+ }
350
+ @resource.reload
351
+
352
+ assert_equal Devise.token_generator.digest(self, :reset_password_token, @mail_reset_token), @resource.reset_password_token
353
+ end
354
+
355
+ test 'response should return success status' do
356
+ get :edit, params: {
357
+ reset_password_token: @mail_reset_token,
358
+ redirect_url: @mail_redirect_url
359
+ }
360
+
361
+ assert_equal 302, response.status
362
+ end
363
+
364
+ test 'reset_password_sent_at should be valid' do
365
+ assert_equal @resource.reset_password_period_valid?, true
366
+
367
+ get :edit, params: {
368
+ reset_password_token: @mail_reset_token,
369
+ redirect_url: @mail_redirect_url
370
+ }
371
+
372
+ @resource.reload
373
+ assert_equal Devise.token_generator.digest(self, :reset_password_token, @mail_reset_token), @resource.reset_password_token
374
+ end
375
+
376
+ test 'reset_password_sent_at should be expired' do
377
+ assert_equal @resource.reset_password_period_valid?, true
378
+
379
+ @resource.update reset_password_sent_at: @resource.reset_password_sent_at - Devise.reset_password_within - 1.seconds
380
+ assert_equal @resource.reset_password_period_valid?, false
381
+
382
+ assert_raises(ActionController::RoutingError) {
383
+ get :edit, params: {
384
+ reset_password_token: @mail_reset_token,
385
+ redirect_url: @mail_redirect_url
386
+ }
387
+ }
388
+ end
389
+ end
390
+
391
+ describe 'reset_password_token is not valid' do
392
+ test 'response should return error status' do
393
+ @resource.update reset_password_token: 'koskoskoskos'
394
+
395
+ assert_not_equal Devise.token_generator.digest(self, :reset_password_token, @mail_reset_token), @resource.reset_password_token
396
+
397
+ assert_raises(ActionController::RoutingError) {
398
+ get :edit, params: {
399
+ reset_password_token: @mail_reset_token,
400
+ redirect_url: @mail_redirect_url
401
+ }
402
+ }
403
+ end
404
+ end
405
+ end
406
+ end
407
+
408
+ describe 'Using default_password_reset_url' do
409
+ before do
410
+ @resource = create(:user, :confirmed)
411
+ @redirect_url = 'http://ng-token-auth.dev'
412
+
413
+ DeviseTokenAuth.default_password_reset_url = @redirect_url
414
+
415
+ post :create,
416
+ params: { email: @resource.email,
417
+ redirect_url: @redirect_url }
418
+
419
+ @mail = ActionMailer::Base.deliveries.last
420
+ @resource.reload
421
+
422
+ @sent_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
423
+ end
424
+
425
+ teardown do
426
+ DeviseTokenAuth.default_password_reset_url = nil
427
+ end
428
+
429
+ test 'response should return success status' do
430
+ assert_equal 200, response.status
431
+ end
432
+
433
+ test 'action should send an email' do
434
+ assert @mail
435
+ end
436
+
437
+ test 'the email body should contain a link with redirect url as a query param' do
438
+ assert_equal @redirect_url, @sent_redirect_url
439
+ end
440
+ end
441
+
442
+ describe 'Using redirect_whitelist' do
443
+ before do
444
+ @good_redirect_url = @redirect_url
445
+ @bad_redirect_url = Faker::Internet.url
446
+ DeviseTokenAuth.redirect_whitelist = [@good_redirect_url]
447
+ end
448
+
449
+ teardown do
450
+ DeviseTokenAuth.redirect_whitelist = nil
451
+ end
452
+
453
+ describe 'for create' do
454
+ test 'request to whitelisted redirect should be successful' do
455
+ post :create,
456
+ params: { email: @resource.email,
457
+ redirect_url: @good_redirect_url }
458
+
459
+ assert_equal 200, response.status
460
+ end
461
+
462
+ test 'request to non-whitelisted redirect should fail' do
463
+ post :create,
464
+ params: { email: @resource.email,
465
+ redirect_url: @bad_redirect_url }
466
+
467
+ assert_equal 422, response.status
468
+ end
469
+
470
+ test 'request to non-whitelisted redirect should return error message' do
471
+ post :create,
472
+ params: { email: @resource.email,
473
+ redirect_url: @bad_redirect_url }
474
+
475
+ @data = JSON.parse(response.body)
476
+ assert @data['errors']
477
+ assert_equal @data['errors'],
478
+ [I18n.t('devise_token_auth.passwords.not_allowed_redirect_url',
479
+ redirect_url: @bad_redirect_url)]
480
+ end
481
+ end
482
+
483
+ describe 'for edit' do
484
+ before do
485
+ @auth_headers = @resource.create_new_auth_token
486
+ @new_password = Faker::Internet.password
487
+
488
+ get_reset_token
489
+ end
490
+
491
+ test 'request to whitelisted redirect should be successful' do
492
+ get :edit, params: { reset_password_token: @mail_reset_token, redirect_url: @good_redirect_url }
493
+
494
+ assert_equal 302, response.status
495
+ end
496
+
497
+ test 'request to non-whitelisted redirect should fail' do
498
+ get :edit, params: { reset_password_token: @mail_reset_token, redirect_url: @bad_redirect_url }
499
+
500
+ assert_equal 422, response.status
501
+ end
502
+
503
+ test 'request to non-whitelisted redirect should return error message' do
504
+ get :edit, params: { reset_password_token: @mail_reset_token, redirect_url: @bad_redirect_url }
505
+
506
+ @data = JSON.parse(response.body)
507
+ assert @data['errors']
508
+ assert_equal @data['errors'],
509
+ [I18n.t('devise_token_auth.passwords.not_allowed_redirect_url',
510
+ redirect_url: @bad_redirect_url)]
511
+ end
512
+ end
513
+ end
514
+
515
+ describe 'change password with current password required' do
516
+ before do
517
+ DeviseTokenAuth.check_current_password_before_update = :password
518
+ end
519
+
520
+ after do
521
+ DeviseTokenAuth.check_current_password_before_update = false
522
+ end
523
+
524
+ describe 'success' do
525
+ before do
526
+ DeviseTokenAuth.require_client_password_reset_token = false
527
+ @auth_headers = @resource.create_new_auth_token
528
+ request.headers.merge!(@auth_headers)
529
+ @new_password = Faker::Internet.password
530
+ @resource.update password: 'secret123', password_confirmation: 'secret123'
531
+
532
+ put :update,
533
+ params: { password: @new_password,
534
+ password_confirmation: @new_password,
535
+ current_password: 'secret123' }
536
+
537
+ @data = JSON.parse(response.body)
538
+ @resource.reload
539
+ end
540
+
541
+ test 'request should be successful' do
542
+ assert_equal 200, response.status
543
+ end
544
+ end
545
+
546
+ describe 'success with after password reset' do
547
+ before do
548
+ # create a new password reset request
549
+ post :create, params: { email: @resource.email,
550
+ redirect_url: @redirect_url }
551
+
552
+ @mail = ActionMailer::Base.deliveries.last
553
+ @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
554
+ @mail_reset_token = @mail.body.match(/reset_password_token=(.*)\"/)[1]
555
+
556
+ # confirm via password reset email link
557
+ get :edit, params: { reset_password_token: @mail_reset_token,
558
+ redirect_url: @mail_redirect_url }
559
+
560
+ @resource.reload
561
+ @allow_password_change_after_reset = @resource.allow_password_change
562
+
563
+ @auth_headers = @resource.create_new_auth_token
564
+ request.headers.merge!(@auth_headers)
565
+ @new_password = Faker::Internet.password
566
+
567
+ put :update, params: { password: @new_password,
568
+ password_confirmation: @new_password }
569
+
570
+ @data = JSON.parse(response.body)
571
+ @resource.reload
572
+ @allow_password_change = @resource.allow_password_change
573
+ @resource.reload
574
+ end
575
+
576
+ test 'request should be successful' do
577
+ assert_equal 200, response.status
578
+ end
579
+
580
+ test 'changes allow_password_change to true on reset' do
581
+ assert_equal true, @allow_password_change_after_reset
582
+ end
583
+
584
+ test 'sets allow_password_change false' do
585
+ assert_equal false, @allow_password_change
586
+ end
587
+ end
588
+
589
+ describe 'current password mismatch error' do
590
+ before do
591
+ DeviseTokenAuth.require_client_password_reset_token = false
592
+ @auth_headers = @resource.create_new_auth_token
593
+ request.headers.merge!(@auth_headers)
594
+ @new_password = Faker::Internet.password
595
+
596
+ put :update, params: { password: @new_password,
597
+ password_confirmation: @new_password,
598
+ current_password: 'not_very_secret321' }
599
+ end
600
+
601
+ test 'response should fail unauthorized' do
602
+ assert_equal 422, response.status
603
+ end
604
+ end
605
+ end
606
+
607
+ describe 'change password' do
608
+ describe 'using reset token' do
609
+ before do
610
+ DeviseTokenAuth.require_client_password_reset_token = true
611
+ @redirect_url = 'http://client-app.dev'
612
+ get_reset_token
613
+ edit_url = CGI.unescape(@mail.body.match(/href=\"(.+)\"/)[1])
614
+ query_parts = Rack::Utils.parse_nested_query(URI.parse(edit_url).query)
615
+ get :edit, params: query_parts
616
+ end
617
+
618
+ test 'request should be redirect' do
619
+ assert_equal 302, response.status
620
+ end
621
+
622
+ test 'request should redirect to correct redirect url' do
623
+ host = URI.parse(response.location).host
624
+ query_parts = Rack::Utils.parse_nested_query(URI.parse(response.location).query)
625
+
626
+ assert_equal 'client-app.dev', host
627
+ assert_equal @mail_reset_token, query_parts['reset_password_token']
628
+ assert_equal 1, query_parts.keys.size
629
+ end
630
+
631
+ teardown do
632
+ DeviseTokenAuth.require_client_password_reset_token = false
633
+ end
634
+ end
635
+
636
+ describe 'with valid headers' do
637
+ before do
638
+ @auth_headers = @resource.create_new_auth_token
639
+ request.headers.merge!(@auth_headers)
640
+ @new_password = Faker::Internet.password
641
+
642
+ put :update, params: { password: @new_password,
643
+ password_confirmation: @new_password }
644
+
645
+ @data = JSON.parse(response.body)
646
+ @resource.reload
647
+ end
648
+
649
+ test 'request should be successful' do
650
+ assert_equal 200, response.status
651
+ end
652
+
653
+ test 'request should return success message' do
654
+ assert @data['message']
655
+ assert_equal @data['message'],
656
+ I18n.t('devise_token_auth.passwords.successfully_updated')
657
+ end
658
+
659
+ test 'new password should authenticate user' do
660
+ assert @resource.valid_password?(@new_password)
661
+ end
662
+
663
+ test 'reset_password_token should be removed' do
664
+ assert_nil @resource.reset_password_token
665
+ end
666
+ end
667
+
668
+ describe 'password mismatch error' do
669
+ before do
670
+ @auth_headers = @resource.create_new_auth_token
671
+ request.headers.merge!(@auth_headers)
672
+ @new_password = Faker::Internet.password
673
+
674
+ put :update, params: { password: 'chong',
675
+ password_confirmation: 'bong' }
676
+ end
677
+
678
+ test 'response should fail' do
679
+ assert_equal 422, response.status
680
+ end
681
+ end
682
+
683
+ describe 'without valid headers' do
684
+ before do
685
+ @resource.create_new_auth_token
686
+ new_password = Faker::Internet.password
687
+
688
+ put :update, params: { password: new_password,
689
+ password_confirmation: new_password }
690
+ end
691
+
692
+ test 'response should fail' do
693
+ assert_equal 401, response.status
694
+ end
695
+ end
696
+
697
+ describe 'with valid reset password token' do
698
+ before do
699
+ reset_password_token = @resource.send_reset_password_instructions
700
+ @new_password = Faker::Internet.password
701
+ @params = { password: @new_password,
702
+ password_confirmation: @new_password,
703
+ reset_password_token: reset_password_token }
704
+ end
705
+
706
+ describe 'with require_client_password_reset_token disabled' do
707
+ before do
708
+ DeviseTokenAuth.require_client_password_reset_token = false
709
+ put :update, params: @params
710
+
711
+ @data = JSON.parse(response.body)
712
+ @resource.reload
713
+ end
714
+
715
+ test 'request should be not be successful' do
716
+ assert_equal 401, response.status
717
+ end
718
+ end
719
+
720
+ describe 'with require_client_password_reset_token enabled' do
721
+ before do
722
+ DeviseTokenAuth.require_client_password_reset_token = true
723
+ put :update, params: @params
724
+
725
+ @data = JSON.parse(response.body)
726
+ @resource.reload
727
+ end
728
+
729
+ test 'request should be successful' do
730
+ assert_equal 200, response.status
731
+ end
732
+
733
+ test 'request should return success message' do
734
+ assert @data['message']
735
+ assert_equal @data['message'],
736
+ I18n.t('devise_token_auth.passwords.successfully_updated')
737
+ end
738
+
739
+ test 'new password should authenticate user' do
740
+ assert @resource.valid_password?(@new_password)
741
+ end
742
+
743
+ teardown do
744
+ DeviseTokenAuth.require_client_password_reset_token = false
745
+ end
746
+ end
747
+ end
748
+
749
+ describe 'with expired reset password token' do
750
+ before do
751
+ DeviseTokenAuth.require_client_password_reset_token = true
752
+ reset_password_token = @resource.send_reset_password_instructions
753
+ @resource.update! reset_password_sent_at: 2.days.ago
754
+
755
+ @new_password = Faker::Internet.password
756
+ @params = { password: @new_password,
757
+ password_confirmation: @new_password,
758
+ reset_password_token: reset_password_token }
759
+
760
+ put :update, params: @params
761
+
762
+ @data = JSON.parse(response.body)
763
+ @resource.reload
764
+ end
765
+
766
+ test 'request should fail' do
767
+ assert_equal 401, response.status
768
+ end
769
+
770
+ test 'new password should not authenticate user' do
771
+ assert !@resource.valid_password?(@new_password)
772
+ end
773
+
774
+ teardown do
775
+ DeviseTokenAuth.require_client_password_reset_token = false
776
+ end
777
+ end
778
+
779
+ describe 'with invalid reset password token' do
780
+ before do
781
+ DeviseTokenAuth.require_client_password_reset_token = true
782
+ @resource.update reset_password_token: 'koskoskoskos'
783
+ put :update, params: @params
784
+ @data = JSON.parse(response.body)
785
+ @resource.reload
786
+ end
787
+
788
+ test 'request should fail' do
789
+ assert_equal 401, response.status
790
+ end
791
+
792
+ test 'new password should not authenticate user' do
793
+ assert !@resource.valid_password?(@new_password)
794
+ end
795
+
796
+ teardown do
797
+ DeviseTokenAuth.require_client_password_reset_token = false
798
+ end
799
+ end
800
+ end
801
+ end
802
+
803
+ describe 'Alternate user class' do
804
+ setup do
805
+ @request.env['devise.mapping'] = Devise.mappings[:mang]
806
+ end
807
+
808
+ teardown do
809
+ @request.env['devise.mapping'] = Devise.mappings[:user]
810
+ end
811
+
812
+ before do
813
+ @resource = create(:mang_user, :confirmed)
814
+ @redirect_url = 'http://ng-token-auth.dev'
815
+ get_reset_token
816
+ end
817
+
818
+ test 'response should return success status' do
819
+ assert_equal 200, response.status
820
+ end
821
+
822
+ test 'the email body should contain a link with reset token as a query param' do
823
+ user = Mang.reset_password_by_token(reset_password_token: @mail_reset_token)
824
+
825
+ assert_equal user.id, @resource.id
826
+ end
827
+ end
828
+
829
+ describe 'unconfirmed user' do
830
+ before do
831
+ @resource = create(:user)
832
+ @redirect_url = 'http://ng-token-auth.dev'
833
+
834
+ get_reset_token
835
+
836
+ get :edit, params: { reset_password_token: @mail_reset_token,
837
+ redirect_url: @mail_redirect_url }
838
+
839
+ @resource.reload
840
+ end
841
+ end
842
+
843
+ describe 'unconfirmable user' do
844
+ setup do
845
+ @request.env['devise.mapping'] = Devise.mappings[:unconfirmable_user]
846
+ end
847
+
848
+ teardown do
849
+ @request.env['devise.mapping'] = Devise.mappings[:user]
850
+ end
851
+
852
+ before do
853
+ @resource = unconfirmable_users(:user)
854
+
855
+ get_reset_token
856
+
857
+ get :edit, params: { reset_password_token: @mail_reset_token,
858
+ redirect_url: @mail_redirect_url }
859
+
860
+ @resource.reload
861
+ end
862
+ end
863
+
864
+ describe 'alternate user type' do
865
+ before do
866
+ @resource = create(:user, :confirmed)
867
+ @redirect_url = 'http://ng-token-auth.dev'
868
+ @config_name = 'altUser'
869
+
870
+ params = { email: @resource.email,
871
+ redirect_url: @redirect_url,
872
+ config_name: @config_name }
873
+ get_reset_token params
874
+ end
875
+
876
+ test 'config_name param is included in the confirmation email link' do
877
+ assert_equal @config_name, @mail_config_name
878
+ end
879
+ end
880
+
881
+ def get_reset_token(params = nil)
882
+ params ||= { email: @resource.email, redirect_url: @redirect_url }
883
+ post :create, params: params
884
+
885
+ @mail = ActionMailer::Base.deliveries.last
886
+ @resource.reload
887
+
888
+ @mail_config_name = CGI.unescape(@mail.body.match(/config=([^&]*)&/)[1])
889
+ @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
890
+ @mail_reset_token = @mail.body.match(/reset_password_token=(.*)\"/)[1]
891
+ end
892
+ end
893
+ end