devise_token_auth 1.2.2 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 135b5088d17b20d187a6ffe314356dd2a2474d9bd98898bc9e36bc931e6c9fef
4
- data.tar.gz: cf3c3c6fc19564248bdcb22e3b99624bd25a027383649a45c7e7bf1fddfd5bbd
3
+ metadata.gz: 2950da8c6b3eac0a2a3ee2b1659d5e321ca9890e5a9b0a1525dcbf11e95d67dd
4
+ data.tar.gz: d04830c1c12f69b3537e80fae17d5914b0b22272a52b78d7226a04be560cadea
5
5
  SHA512:
6
- metadata.gz: 5f6e88376261bcea31e98d8af66cc298755d2cbc2724c481a100d78273824b1dcfcc016bbc2af2b43d1dcac945fc6a4015d351f321da9a432ec4c5129f8c58f0
7
- data.tar.gz: bde72417d1882c6f69076d3bfe8cebd077e39a681898fb0c5603643770a3d81eb0ac3d42dd46f8ae27aff4dae74a138159160974c1996ef4e28d252baf6b52ba
6
+ metadata.gz: 0a7e1dcce01dabc1e270926ff05b54c166d861232ef6ecf7547d88442e2d11ab7c104fef833312bf73a69dd5e3dd7df4923f050baf3e4aee877f32df6392d352
7
+ data.tar.gz: b44b9aa57a43fb58e86a7985957e9a5d425787ae65e898b480d7fefe02bf573433f27af356512ae2a4989c3a6d9f0b91a9cc1a1b3b2ef3f95a4b39557472ffa7
data/README.md CHANGED
@@ -23,6 +23,7 @@ Also, it maintains a session for each client/device, so you can have as many ses
23
23
  * [redux-token-auth](https://github.com/kylecorbelli/redux-token-auth) for [React with Redux](https://github.com/reactjs/react-redux)
24
24
  * [jToker](https://github.com/lynndylanhurley/j-toker) for [jQuery](https://jquery.com/)
25
25
  * [vanilla-token-auth](https://github.com/theblang/vanilla-token-auth) for an unopinionated client
26
+ * [flutter_token_auth](https://github.com/diarmuidr3d/flutter_token_auth) for Flutter
26
27
  * Oauth2 authentication using [OmniAuth](https://github.com/intridea/omniauth).
27
28
  * Email authentication using [Devise](https://github.com/plataformatec/devise), including:
28
29
  * User registration, update and deletion
@@ -70,12 +71,8 @@ We have some bounties for some issues, [check them out](https://github.com/lynnd
70
71
 
71
72
  ## Live Demos
72
73
 
73
- [Here is a demo](http://ng-token-auth-demo.herokuapp.com/) of this app running with the [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) module and [AngularJS](https://github.com/angular/angular.js).
74
-
75
74
  [Here is a demo](https://stackblitz.com/github/neroniaky/angular-token) of this app running with the [Angular-Token](https://github.com/neroniaky/angular-token) service and [Angular](https://github.com/angular/angular).
76
75
 
77
- [Here is a demo](https://j-toker-demo.herokuapp.com/) of this app using the [jToker](https://github.com/lynndylanhurley/j-toker) plugin and [React](http://facebook.github.io/react/).
78
-
79
76
  The fully configured api used in these demos can be found [here](https://github.com/lynndylanhurley/devise_token_auth_demo).
80
77
 
81
78
 
@@ -27,7 +27,7 @@ module DeviseTokenAuth
27
27
  redirect_to(redirect_to_link, redirect_options)
28
28
  else
29
29
  if redirect_url
30
- redirect_to DeviseTokenAuth::Url.generate(redirect_url, account_confirmation_success: false)
30
+ redirect_to DeviseTokenAuth::Url.generate(redirect_url, account_confirmation_success: false), redirect_options
31
31
  else
32
32
  raise ActionController::RoutingError, 'Not Found'
33
33
  end
@@ -56,7 +56,7 @@ module DeviseTokenAuth
56
56
  set_token_in_cookie(@resource, token)
57
57
  end
58
58
 
59
- redirect_header_options = { reset_password: true }
59
+ redirect_header_options = { reset_password: true, reset_password_token: resource_params[:reset_password_token] }
60
60
  redirect_headers = build_redirect_headers(token.token,
61
61
  token.client,
62
62
  redirect_header_options)
@@ -73,7 +73,7 @@ module DeviseTokenAuth
73
73
  # make sure user is authorized
74
74
  if require_client_password_reset_token? && resource_params[:reset_password_token]
75
75
  @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
76
- return render_update_error_unauthorized unless @resource
76
+ return render_update_error_unauthorized unless @resource && @resource.reset_password_period_valid?
77
77
 
78
78
  @token = @resource.create_token
79
79
  else
@@ -131,7 +131,7 @@ module DeviseTokenAuth
131
131
  end
132
132
 
133
133
  def create_and_assign_token
134
- if @resource.respond_to?(:with_lock)
134
+ if @resource.respond_to?(:with_lock) && !@resource.changed?
135
135
  @resource.with_lock do
136
136
  @token = @resource.create_token
137
137
  @resource.save!
@@ -2,7 +2,11 @@ module DeviseTokenAuth::Concerns::ActiveRecordSupport
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- serialize :tokens, DeviseTokenAuth::Concerns::TokensSerialization
5
+ if Rails.gem_version >= Gem::Version.new("7.1.0.a")
6
+ serialize :tokens, coder: DeviseTokenAuth::Concerns::TokensSerialization
7
+ else
8
+ serialize :tokens, DeviseTokenAuth::Concerns::TokensSerialization
9
+ end
6
10
  end
7
11
 
8
12
  class_methods do
@@ -3,7 +3,7 @@ module DeviseTokenAuth::Concerns::ConfirmableSupport
3
3
 
4
4
  included do
5
5
  # Override standard devise `postpone_email_change?` method
6
- # for not to use `will_save_change_to_email?` & `email_changed?` methods.
6
+ # for not to use `devise_will_save_change_to_email?` methods.
7
7
  def postpone_email_change?
8
8
  postpone = self.class.reconfirmable &&
9
9
  email_value_in_database != email &&
@@ -41,8 +41,7 @@ module DeviseTokenAuth::Concerns::User
41
41
 
42
42
  # don't use default devise email validation
43
43
  def email_required?; false; end
44
- def email_changed?; false; end
45
- def will_save_change_to_email?; false; end
44
+ def devise_will_save_change_to_email?; false; end
46
45
 
47
46
  if DeviseTokenAuth.send_confirmation_email && devise_modules.include?(:confirmable)
48
47
  include DeviseTokenAuth::Concerns::ConfirmableSupport
@@ -259,17 +258,25 @@ module DeviseTokenAuth::Concerns::User
259
258
  end
260
259
 
261
260
  def clean_old_tokens
262
- if tokens.present? && max_client_tokens_exceeded?
263
- # Using Enumerable#sort_by on a Hash will typecast it into an associative
264
- # Array (i.e. an Array of key-value Array pairs). However, since Hashes
265
- # have an internal order in Ruby 1.9+, the resulting sorted associative
266
- # Array can be converted back into a Hash, while maintaining the sorted
267
- # order.
268
- self.tokens = tokens.sort_by { |_cid, v| v[:expiry] || v['expiry'] }.to_h
269
-
270
- # Since the tokens are sorted by expiry, shift the oldest client token
271
- # off the Hash until it no longer exceeds the maximum number of clients
272
- tokens.shift while max_client_tokens_exceeded?
261
+ return if tokens.blank? || !max_client_tokens_exceeded?
262
+
263
+ # First, remove any tokens with expiry greater than current max allowed lifespan
264
+ # this handles the case where token lifespan was reduced and old tokens exist
265
+ max_lifespan_expiry = Time.now.to_i + DeviseTokenAuth.token_lifespan.to_i
266
+ tokens_to_keep = tokens.select do |_cid, v|
267
+ expiry = (v[:expiry] || v['expiry']).to_i
268
+ expiry <= max_lifespan_expiry
273
269
  end
270
+
271
+ # Using Enumerable#sort_by on a Hash will typecast it into an associative
272
+ # Array (i.e. an Array of key-value Array pairs). However, since Hashes
273
+ # have an internal order in Ruby 1.9+, the resulting sorted associative
274
+ # Array can be converted back into a Hash, while maintaining the sorted
275
+ # order.
276
+ self.tokens = tokens_to_keep.sort_by { |_cid, v| v[:expiry] || v['expiry'] }.to_h
277
+
278
+ # Since the tokens are sorted by expiry, shift the oldest client token
279
+ # off the Hash until it no longer exceeds the maximum number of clients
280
+ tokens.shift while max_client_tokens_exceeded?
274
281
  end
275
282
  end
@@ -0,0 +1,60 @@
1
+ fa:
2
+ devise_token_auth:
3
+ sessions:
4
+ not_confirmed: "یک ایمیل تأیید به حساب شما در '%{email}' ارسال شده است. شما باید دستورالعمل‌های موجود در ایمیل را دنبال کنید تا حساب شما فعال شود."
5
+ bad_credentials: "اطلاعات ورود نامعتبر است. لطفاً دوباره تلاش کنید."
6
+ not_supported: "برای ورود از POST /sign_in استفاده کنید. GET پشتیبانی نمی‌شود."
7
+ user_not_found: "کاربر پیدا نشد یا وارد نشده است."
8
+ token_validations:
9
+ invalid: "اطلاعات ورود نامعتبر است."
10
+ registrations:
11
+ missing_confirm_success_url: "پارامتر 'confirm_success_url' موجود نیست."
12
+ redirect_url_not_allowed: "انتقال به '%{redirect_url}' مجاز نیست."
13
+ email_already_exists: "یک حساب برای '%{email}' قبلاً وجود دارد."
14
+ account_with_uid_destroyed: "حساب با UID '%{uid}' حذف شده است."
15
+ account_to_destroy_not_found: "نمی‌توان حساب را برای حذف پیدا کرد."
16
+ user_not_found: "کاربر پیدا نشد."
17
+ omniauth:
18
+ not_allowed_redirect_url: "انتقال به '%{redirect_url}' مجاز نیست."
19
+ passwords:
20
+ missing_email: "شما باید یک آدرس ایمیل ارائه دهید."
21
+ missing_redirect_url: "آدرس انتقال موجود نیست."
22
+ not_allowed_redirect_url: "انتقال به '%{redirect_url}' مجاز نیست."
23
+ sended: "یک ایمیل به '%{email}' ارسال شده است که شامل دستورالعمل‌های بازنشانی رمز عبور شما است."
24
+ sended_paranoid: "اگر آدرس ایمیل شما در پایگاه داده ما وجود داشته باشد، در چند دقیقه یک لینک بازیابی رمز عبور به آدرس ایمیل شما ارسال خواهد شد."
25
+ user_not_found: "نمی‌توان کاربری با ایمیل '%{email}' پیدا کرد."
26
+ password_not_required: "این حساب نیازی به رمز عبور ندارد. به جای آن با حساب '%{provider}' خود وارد شوید."
27
+ missing_passwords: "شما باید فیلدهای 'رمز عبور' و 'تأیید رمز عبور' را پر کنید."
28
+ successfully_updated: "رمز عبور شما با موفقیت به‌روزرسانی شد."
29
+ unlocks:
30
+ missing_email: "شما باید یک آدرس ایمیل ارائه دهید."
31
+ sended: "یک ایمیل به '%{email}' ارسال شده است که شامل دستورالعمل‌های باز کردن حساب شما است."
32
+ sended_paranoid: "اگر حساب شما وجود داشته باشد، در چند دقیقه یک ایمیل با دستورالعمل‌های باز کردن حساب شما ارسال خواهد شد."
33
+ user_not_found: "نمی‌توان کاربری با ایمیل '%{email}' پیدا کرد."
34
+ confirmations:
35
+ sended: "یک ایمیل به '%{email}' ارسال شده است که شامل دستورالعمل‌های تأیید حساب شما است."
36
+ sended_paranoid: "اگر آدرس ایمیل شما در پایگاه داده ما وجود داشته باشد، در چند دقیقه یک ایمیل با دستورالعمل‌های تأیید آدرس ایمیل شما ارسال خواهد شد."
37
+ user_not_found: "نمی‌توان کاربری با ایمیل '%{email}' پیدا کرد."
38
+ missing_email: "شما باید یک آدرس ایمیل ارائه دهید."
39
+
40
+ errors:
41
+ messages:
42
+ validate_sign_up_params: "لطفاً داده‌های صحیح ثبت نام را در بدنه درخواست ارسال کنید."
43
+ validate_account_update_params: "لطفاً داده‌های صحیح به‌روزرسانی حساب را در بدنه درخواست ارسال کنید."
44
+ not_email: "یک ایمیل نیست"
45
+ devise:
46
+ mailer:
47
+ confirmation_instructions:
48
+ confirm_link_msg: "شما می‌توانید ایمیل حساب خود را از طریق لینک زیر تأیید کنید:"
49
+ confirm_account_link: "تأیید حساب من"
50
+ reset_password_instructions:
51
+ request_reset_link_msg: "شخصی درخواست یک لینک برای تغییر رمز عبور شما کرده است. شما می‌توانید این کار را از طریق لینک زیر انجام دهید."
52
+ password_change_link: "تغییر رمز عبور من"
53
+ ignore_mail_msg: "اگر شما این درخواست را نکرده‌اید، لطفاً این ایمیل را نادیده بگیرید."
54
+ no_changes_msg: "رمز عبور شما تغییر نخواهد کرد تا زمانی که به لینک بالا دسترسی پیدا کنید و یک رمز عبور جدید ایجاد کنید."
55
+ unlock_instructions:
56
+ account_lock_msg: "حساب شما به دلیل تعداد زیادی تلاش ناموفق برای ورود قفل شده است."
57
+ unlock_link_msg: "برای باز کردن حساب خود، روی لینک زیر کلیک کنید:"
58
+ unlock_link: "باز کردن حساب من"
59
+ hello: "سلام"
60
+ welcome: "خوش آمدید"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeviseTokenAuth
4
- VERSION = '1.2.2'.freeze
4
+ VERSION = '1.2.6'.freeze
5
5
  end
@@ -229,42 +229,73 @@ class DeviseTokenAuth::PasswordsControllerTest < ActionController::TestCase
229
229
  end
230
230
 
231
231
  describe 'password reset link success' do
232
- before do
233
- get :edit,
234
- params: { reset_password_token: @mail_reset_token,
235
- redirect_url: @mail_redirect_url }
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 }
236
238
 
237
- @resource.reload
239
+ @resource.reload
238
240
 
239
- raw_qs = response.location.split('?')[1]
240
- @qs = Rack::Utils.parse_nested_query(raw_qs)
241
+ raw_qs = response.location.split('?')[1]
242
+ @qs = Rack::Utils.parse_nested_query(raw_qs)
241
243
 
242
- @access_token = @qs['access-token']
243
- @client_id = @qs['client_id']
244
- @client = @qs['client']
245
- @expiry = @qs['expiry']
246
- @reset_password = @qs['reset_password']
247
- @token = @qs['token']
248
- @uid = @qs['uid']
249
- end
244
+ @reset_password_token = @qs['reset_password_token']
245
+ end
250
246
 
251
- test 'response should have success redirect status' do
252
- assert_equal 302, response.status
253
- end
247
+ test 'response should have success redirect status' do
248
+ assert_equal 302, response.status
249
+ end
254
250
 
255
- test 'response should contain auth params' do
256
- assert @access_token
257
- assert @client
258
- assert @client_id
259
- assert @expiry
260
- assert @reset_password
261
- assert @token
262
- assert @uid
251
+ test 'response should contain reset_password_token param' do
252
+ assert_equal @mail_reset_token, @qs['reset_password_token']
253
+ end
263
254
  end
264
255
 
265
- test 'response auth params should be valid' do
266
- assert @resource.valid_token?(@token, @client_id)
267
- assert @resource.valid_token?(@access_token, @client)
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
268
299
  end
269
300
  end
270
301
  end
@@ -715,6 +746,36 @@ class DeviseTokenAuth::PasswordsControllerTest < ActionController::TestCase
715
746
  end
716
747
  end
717
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
+
718
779
  describe 'with invalid reset password token' do
719
780
  before do
720
781
  DeviseTokenAuth.require_client_password_reset_token = true
@@ -13,7 +13,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
13
13
 
14
14
  def mock_registration_params
15
15
  {
16
- email: Faker::Internet.email,
16
+ email: Faker::Internet.unique.email,
17
17
  password: 'secret123',
18
18
  password_confirmation: 'secret123',
19
19
  confirm_success_url: Faker::Internet.url,
@@ -152,7 +152,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
152
152
 
153
153
  test 'request to whitelisted redirect should be successful' do
154
154
  post '/auth',
155
- params: { email: Faker::Internet.email,
155
+ params: { email: Faker::Internet.unique.email,
156
156
  password: 'secret123',
157
157
  password_confirmation: 'secret123',
158
158
  confirm_success_url: @good_redirect_url,
@@ -163,7 +163,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
163
163
 
164
164
  test 'request to non-whitelisted redirect should fail' do
165
165
  post '/auth',
166
- params: { email: Faker::Internet.email,
166
+ params: { email: Faker::Internet.unique.email,
167
167
  password: 'secret123',
168
168
  password_confirmation: 'secret123',
169
169
  confirm_success_url: @bad_redirect_url,
@@ -181,7 +181,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
181
181
  describe 'failure if not redirecturl' do
182
182
  test 'request should fail if not redirect_url' do
183
183
  post '/auth',
184
- params: { email: Faker::Internet.email,
184
+ params: { email: Faker::Internet.unique.email,
185
185
  password: 'secret123',
186
186
  password_confirmation: 'secret123',
187
187
  unpermitted_param: '(x_x)' }
@@ -191,7 +191,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
191
191
 
192
192
  test 'request to non-whitelisted redirect should fail' do
193
193
  post '/auth',
194
- params: { email: Faker::Internet.email,
194
+ params: { email: Faker::Internet.unique.email,
195
195
  password: 'secret123',
196
196
  password_confirmation: 'secret123',
197
197
  unpermitted_param: '(x_x)' }
@@ -210,7 +210,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
210
210
  DeviseTokenAuth.default_confirm_success_url = @redirect_url
211
211
 
212
212
  assert_difference 'ActionMailer::Base.deliveries.size', 1 do
213
- post '/auth', params: { email: Faker::Internet.email,
213
+ post '/auth', params: { email: Faker::Internet.unique.email,
214
214
  password: 'secret123',
215
215
  password_confirmation: 'secret123',
216
216
  unpermitted_param: '(x_x)' }
@@ -240,7 +240,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
240
240
  @mails_sent = ActionMailer::Base.deliveries.count
241
241
 
242
242
  post '/api/v1/auth', params: {
243
- email: Faker::Internet.email,
243
+ email: Faker::Internet.unique.email,
244
244
  password: 'secret123',
245
245
  password_confirmation: 'secret123',
246
246
  confirm_success_url: Faker::Internet.url,
@@ -295,7 +295,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
295
295
  @operating_thetan = 2
296
296
 
297
297
  post '/auth',
298
- params: { email: Faker::Internet.email,
298
+ params: { email: Faker::Internet.unique.email,
299
299
  password: 'secret123',
300
300
  password_confirmation: 'secret123',
301
301
  confirm_success_url: @redirect_url,
@@ -388,7 +388,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
388
388
  describe 'Mismatched passwords' do
389
389
  before do
390
390
  post '/auth',
391
- params: { email: Faker::Internet.email,
391
+ params: { email: Faker::Internet.unique.email,
392
392
  password: 'secret123',
393
393
  password_confirmation: 'bogus',
394
394
  confirm_success_url: Faker::Internet.url }
@@ -505,7 +505,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
505
505
  # test valid update param
506
506
  @resource_class = User
507
507
  @new_operating_thetan = 1_000_000
508
- @email = Faker::Internet.safe_email
508
+ @email = Faker::Internet.unique.email
509
509
  @request_params = {
510
510
  operating_thetan: @new_operating_thetan,
511
511
  email: @email
@@ -612,7 +612,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
612
612
  # test valid update param
613
613
  @resource_class = User
614
614
  @new_operating_thetan = 1_000_000
615
- @email = Faker::Internet.safe_email
615
+ @email = Faker::Internet.unique.email
616
616
  @request_params = {
617
617
  operating_thetan: @new_operating_thetan,
618
618
  email: @email
@@ -663,7 +663,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
663
663
  before do
664
664
  DeviseTokenAuth.check_current_password_before_update = :password
665
665
  @new_operating_thetan = 1_000_000
666
- @email = Faker::Internet.safe_email
666
+ @email = Faker::Internet.unique.email
667
667
  end
668
668
 
669
669
  after do
@@ -773,7 +773,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
773
773
  describe 'Alternate user class' do
774
774
  before do
775
775
  post '/mangs',
776
- params: { email: Faker::Internet.email,
776
+ params: { email: Faker::Internet.unique.email,
777
777
  password: 'secret123',
778
778
  password_confirmation: 'secret123',
779
779
  confirm_success_url: Faker::Internet.url }
@@ -814,7 +814,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
814
814
  @config_name = 'altUser'
815
815
 
816
816
  post '/mangs',
817
- params: { email: Faker::Internet.email,
817
+ params: { email: Faker::Internet.unique.email,
818
818
  password: 'secret123',
819
819
  password_confirmation: 'secret123',
820
820
  confirm_success_url: Faker::Internet.url,
@@ -840,7 +840,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
840
840
  test 'UnregisterableUser should not be able to access registration routes' do
841
841
  assert_raises(ActionController::RoutingError) do
842
842
  post '/unregisterable_user_auth',
843
- params: { email: Faker::Internet.email,
843
+ params: { email: Faker::Internet.unique.email,
844
844
  password: 'secret123',
845
845
  password_confirmation: 'secret123',
846
846
  confirm_success_url: Faker::Internet.url }
@@ -853,7 +853,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
853
853
  User.set_callback(:create, :before, :skip_confirmation!)
854
854
 
855
855
  post '/auth',
856
- params: { email: Faker::Internet.email,
856
+ params: { email: Faker::Internet.unique.email,
857
857
  password: 'secret123',
858
858
  password_confirmation: 'secret123',
859
859
  confirm_success_url: Faker::Internet.url }
@@ -893,7 +893,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
893
893
  @mails_sent = ActionMailer::Base.deliveries.count
894
894
 
895
895
  post '/only_email_auth',
896
- params: { email: Faker::Internet.email,
896
+ params: { email: Faker::Internet.unique.email,
897
897
  password: 'secret123',
898
898
  password_confirmation: 'secret123',
899
899
  confirm_success_url: Faker::Internet.url,
@@ -420,7 +420,7 @@ class DeviseTokenAuth::SessionsControllerTest < ActionController::TestCase
420
420
  describe 'With paranoid mode' do
421
421
  before do
422
422
  mock_hash = '$2a$04$MUWADkfA6MHXDdWHoep6QOvX1o0Y56pNqt3NMWQ9zCRwKSp1HZJba'
423
- @bcrypt_mock = MiniTest::Mock.new
423
+ @bcrypt_mock = Minitest::Mock.new
424
424
  @bcrypt_mock.expect(:call, mock_hash, [Object, String])
425
425
 
426
426
  swap Devise, paranoid: true do
@@ -2,6 +2,7 @@
2
2
 
3
3
  require File.expand_path('boot', __dir__)
4
4
 
5
+ require 'logger'
5
6
  require 'action_controller/railtie'
6
7
  require 'action_mailer/railtie'
7
8
  require 'rails/generators'
@@ -23,7 +23,7 @@ Rails.application.configure do
23
23
  (config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }) :
24
24
  (config.static_cache_control = 'public, max-age=3600')
25
25
 
26
- if Rails::VERSION::MAJOR > 6 && ENV['DEVISE_TOKEN_AUTH_ORM'] != 'mongoid'
26
+ if Rails::VERSION::MAJOR < 7 && ENV['DEVISE_TOKEN_AUTH_ORM'] != 'mongoid'
27
27
  config.active_record.legacy_connection_handling = false
28
28
  end
29
29
 
@@ -32,7 +32,11 @@ Rails.application.configure do
32
32
  config.action_controller.perform_caching = false
33
33
 
34
34
  # Raise exceptions instead of rendering exception templates.
35
- config.action_dispatch.show_exceptions = false
35
+ if Rails::VERSION::MAJOR >= 7 && Rails::VERSION::MINOR > 0
36
+ config.action_dispatch.show_exceptions = :none
37
+ else
38
+ config.action_dispatch.show_exceptions = false
39
+ end
36
40
 
37
41
  # Disable request forgery protection in test environment.
38
42
  config.action_controller.allow_forgery_protection = false
@@ -1,9 +1,11 @@
1
- # frozen_string_literal: true
1
+ class User < ApplicationRecord
2
+ # Include default devise modules.
3
+ devise :database_authenticatable, :registerable,
4
+ :recoverable, :rememberable, :trackable, :validatable,
5
+ :confirmable, :omniauthable
6
+ include DeviseTokenAuth::Concerns::User
2
7
 
3
- class User < ActiveRecord::Base
4
- # Include default devise modules. Others available are:
5
- # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
6
- devise :database_authenticatable, :registerable,
7
- :recoverable, :rememberable, :validatable
8
- include DeviseTokenAuth::Concerns::User
9
- end
8
+ def whatever
9
+ puts 'whatever'
10
+ end
11
+ end
@@ -1,7 +1,7 @@
1
1
  class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[7.0]
2
2
  def change
3
3
 
4
- create_table(:users, id: :uuid) do |t|
4
+ create_table(:users) do |t|
5
5
  ## Required
6
6
  t.string :provider, :null => false, :default => "email"
7
7
  t.string :uid, :null => false, :default => ""
@@ -1,6 +1,6 @@
1
1
  FactoryBot.define do
2
2
  factory :user do
3
- email { Faker::Internet.unique.safe_email }
3
+ email { Faker::Internet.unique.email }
4
4
  password { Faker::Internet.password }
5
5
  provider { 'email' }
6
6
 
@@ -127,4 +127,98 @@ class UserTest < ActiveSupport::TestCase
127
127
  end
128
128
  end
129
129
  end
130
+
131
+ describe 'clean_old_tokens' do
132
+ before do
133
+ @resource = create(:user, :confirmed)
134
+ @token_lifespan = DeviseTokenAuth.token_lifespan
135
+ @max_client_count = DeviseTokenAuth.max_number_of_devices
136
+ DeviseTokenAuth.max_number_of_devices = 2
137
+ DeviseTokenAuth.token_lifespan = 1.week
138
+ end
139
+
140
+ after do
141
+ DeviseTokenAuth.token_lifespan = @token_lifespan
142
+ DeviseTokenAuth.max_number_of_devices = @max_client_count
143
+ end
144
+
145
+ test 'removes tokens with expiry beyond the maximum lifespan' do
146
+ # Create tokens with different expiry times
147
+ current_time = Time.now.to_i
148
+
149
+ max_lifespan = current_time + DeviseTokenAuth.token_lifespan.to_i
150
+
151
+ # Valid token within lifespan
152
+ @resource.tokens['valid_client'] = {
153
+ 'token' => 'valid_token',
154
+ 'expiry' => current_time + 1.day.to_i
155
+ }
156
+
157
+ # Token exactly at max lifespan (should be kept)
158
+ @resource.tokens['edge_client'] = {
159
+ 'token' => 'edge_token',
160
+ 'expiry' => max_lifespan
161
+ }
162
+
163
+ # Token beyond max lifespan (should be removed)
164
+ @resource.tokens['expired_client'] = {
165
+ 'token' => 'expired_token',
166
+ 'expiry' => max_lifespan + 1.day.to_i
167
+ }
168
+
169
+ # Call the method under test
170
+ @resource.send(:clean_old_tokens)
171
+
172
+ # Assert that tokens beyond lifespan were removed
173
+ assert @resource.tokens.key?('valid_client'), 'Valid token should be kept'
174
+ assert @resource.tokens.key?('edge_client'), 'Edge case token at max lifespan should be kept'
175
+ refute @resource.tokens.key?('expired_client'), 'Token beyond max lifespan should be removed'
176
+ end
177
+
178
+ test 'handles token lifespan reduction when creating token' do
179
+ # Setup: Create the maximum allowed number of tokens with a longer lifespan
180
+ DeviseTokenAuth.token_lifespan = 2.weeks
181
+ DeviseTokenAuth.max_number_of_devices = 3
182
+
183
+ # Create tokens at different times but all within the initial long lifespan
184
+ @resource.tokens = {}
185
+ @resource.tokens['client_1'] = {
186
+ 'token' => 'token_1',
187
+ 'expiry' => Time.now.to_i + 12.days.to_i
188
+ }
189
+
190
+ @resource.tokens['client_2'] = {
191
+ 'token' => 'token_2',
192
+ 'expiry' => Time.now.to_i + 10.days.to_i
193
+ }
194
+
195
+ @resource.tokens['client_3'] = {
196
+ 'token' => 'token_3',
197
+ 'expiry' => Time.now.to_i + 5.days.to_i
198
+ }
199
+
200
+ # We've reached the maximum number of devices/tokens
201
+ assert_equal 3, @resource.tokens.length
202
+
203
+ # Now reduce token lifespan - simulating a config change
204
+ DeviseTokenAuth.token_lifespan = 1.week
205
+
206
+ # Create a new token which should trigger clean_old_tokens
207
+ new_auth_headers = @resource.create_new_auth_token
208
+ new_client = new_auth_headers['client']
209
+
210
+ # The new token should exist
211
+ assert @resource.tokens.key?(new_client), 'New token should exist'
212
+
213
+ # Tokens exceeding the new reduced lifespan should be removed
214
+ refute @resource.tokens.key?('client_1'), 'Token with expiry > new lifespan should be removed'
215
+ refute @resource.tokens.key?('client_2'), 'Token with expiry > new lifespan should be removed'
216
+
217
+ # Token within new lifespan should be kept
218
+ assert @resource.tokens.key?('client_3'), 'Token within new reduced lifespan should be kept'
219
+
220
+ # We should have exactly 2 tokens: the new one and client_3
221
+ assert_equal 2, @resource.tokens.length
222
+ end
223
+ end
130
224
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_token_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lynn Hurley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-11 00:00:00.000000000 Z
11
+ date: 2025-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 4.2.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '7.1'
22
+ version: '8.2'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 4.2.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '7.1'
32
+ version: '8.2'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: devise
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -144,16 +144,22 @@ dependencies:
144
144
  name: mongoid-locker
145
145
  requirement: !ruby/object:Gem::Requirement
146
146
  requirements:
147
- - - "~>"
147
+ - - ">="
148
148
  - !ruby/object:Gem::Version
149
- version: '2.0'
149
+ version: '1.0'
150
+ - - "<"
151
+ - !ruby/object:Gem::Version
152
+ version: '3.0'
150
153
  type: :development
151
154
  prerelease: false
152
155
  version_requirements: !ruby/object:Gem::Requirement
153
156
  requirements:
154
- - - "~>"
157
+ - - ">="
155
158
  - !ruby/object:Gem::Version
156
- version: '2.0'
159
+ version: '1.0'
160
+ - - "<"
161
+ - !ruby/object:Gem::Version
162
+ version: '3.0'
157
163
  description: For use with client side single page apps such as the venerable https://github.com/lynndylanhurley/ng-token-auth.
158
164
  email:
159
165
  - lynn.dylan.hurley@gmail.com
@@ -189,6 +195,7 @@ files:
189
195
  - config/locales/de.yml
190
196
  - config/locales/en.yml
191
197
  - config/locales/es.yml
198
+ - config/locales/fa.yml
192
199
  - config/locales/fr.yml
193
200
  - config/locales/he.yml
194
201
  - config/locales/it.yml
@@ -321,7 +328,7 @@ files:
321
328
  - test/dummy/lib/migration_database_helper.rb
322
329
  - test/dummy/tmp/generators/app/models/user.rb
323
330
  - test/dummy/tmp/generators/config/initializers/devise_token_auth.rb
324
- - test/dummy/tmp/generators/db/migrate/20230415183419_devise_token_auth_create_users.rb
331
+ - test/dummy/tmp/generators/db/migrate/20240519164408_devise_token_auth_create_users.rb
325
332
  - test/factories/users.rb
326
333
  - test/lib/devise_token_auth/blacklist_test.rb
327
334
  - test/lib/devise_token_auth/rails/custom_routes_test.rb
@@ -357,7 +364,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
357
364
  - !ruby/object:Gem::Version
358
365
  version: '0'
359
366
  requirements: []
360
- rubygems_version: 3.3.7
367
+ rubygems_version: 3.4.19
361
368
  signing_key:
362
369
  specification_version: 4
363
370
  summary: Token based authentication for rails. Uses Devise + OmniAuth.
@@ -456,7 +463,7 @@ test_files:
456
463
  - test/dummy/lib/migration_database_helper.rb
457
464
  - test/dummy/tmp/generators/app/models/user.rb
458
465
  - test/dummy/tmp/generators/config/initializers/devise_token_auth.rb
459
- - test/dummy/tmp/generators/db/migrate/20230415183419_devise_token_auth_create_users.rb
466
+ - test/dummy/tmp/generators/db/migrate/20240519164408_devise_token_auth_create_users.rb
460
467
  - test/factories/users.rb
461
468
  - test/lib/devise_token_auth/blacklist_test.rb
462
469
  - test/lib/devise_token_auth/rails/custom_routes_test.rb