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