devise_token_auth 1.1.5 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/devise_token_auth/application_controller.rb +8 -0
  3. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +14 -1
  4. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +28 -4
  5. data/app/controllers/devise_token_auth/confirmations_controller.rb +8 -4
  6. data/app/controllers/devise_token_auth/passwords_controller.rb +6 -2
  7. data/app/controllers/devise_token_auth/sessions_controller.rb +6 -0
  8. data/app/controllers/devise_token_auth/unlocks_controller.rb +6 -2
  9. data/app/models/devise_token_auth/concerns/user.rb +2 -7
  10. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +2 -2
  11. data/app/views/devise_token_auth/omniauth_external_window.html.erb +1 -1
  12. data/config/locales/en.yml +3 -0
  13. data/lib/devise_token_auth/blacklist.rb +5 -1
  14. data/lib/devise_token_auth/engine.rb +6 -0
  15. data/lib/devise_token_auth/version.rb +1 -1
  16. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +91 -19
  17. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +2 -2
  18. data/test/controllers/devise_token_auth/passwords_controller_test.rb +73 -21
  19. data/test/controllers/devise_token_auth/registrations_controller_test.rb +28 -15
  20. data/test/controllers/devise_token_auth/sessions_controller_test.rb +39 -10
  21. data/test/controllers/devise_token_auth/unlocks_controller_test.rb +21 -4
  22. data/test/controllers/overrides/confirmations_controller_test.rb +1 -1
  23. data/test/dummy/tmp/generators/app/controllers/application_controller.rb +6 -0
  24. data/test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb +48 -1
  25. data/test/lib/devise_token_auth/blacklist_test.rb +11 -3
  26. data/test/test_helper.rb +34 -3
  27. metadata +5 -5
  28. data/test/dummy/tmp/generators/db/migrate/20210126004321_devise_token_auth_create_azpire_v1_human_resource_users.rb +0 -49
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a64d8fc927471b28cec59b5191e06ef4d2fd7152dadcc9f49b5c512611ba4e6
4
- data.tar.gz: 3ac708a845da1df134975f293a7db9e8977cd116c0d8dbdc7650e249bb99df82
3
+ metadata.gz: fb2d73d7859e1754b505d6f554c8d298ba899444b4fe4e1b47d50ca9bab453e8
4
+ data.tar.gz: 3572d4ff07d68f62d8e51270959fd20451d9edb4832d576b9342939275390dee
5
5
  SHA512:
6
- metadata.gz: 51a73c32d0debfc772ff7f7b8b5a524a67fde1676bb66a1d77d243c451a3ca5b375c593287bfb1be2abff7ff881947e39470a6d46421c73f112d4a5b1d774858
7
- data.tar.gz: a79f4e32938818a92fddbcb88eb918da3c53afe8bf304769fa9d02f1841ed67093ab0bf7b004263094737da15d3dae222b785c70ef233e1b6f43a07a7f49f2b5
6
+ metadata.gz: 50c95181401bedfd959a407d450f222ab185d75000825385dd691a064e831b36263eb1338d25f6378a743ac9009b73f80df3e24cb09ce5680a0e6723fc98acb9
7
+ data.tar.gz: 91910874d7e473d31eb39cf40c6860da4ab5b59aa874a0f1296faa17718103124018568cf289486a9d49a3ec1b967f14e23c18afb8d3f6cd3ec2fd837d663a83
@@ -75,5 +75,13 @@ module DeviseTokenAuth
75
75
  response = response.merge(data) if data
76
76
  render json: response, status: status
77
77
  end
78
+
79
+ def success_message(name, email)
80
+ if Devise.paranoid
81
+ I18n.t("devise_token_auth.#{name}.sended_paranoid")
82
+ else
83
+ I18n.t("devise_token_auth.#{name}.sended", email: email)
84
+ end
85
+ end
78
86
  end
79
87
  end
@@ -20,7 +20,7 @@ module DeviseTokenAuth::Concerns::ResourceFinder
20
20
  end
21
21
 
22
22
  def find_resource(field, value)
23
- @resource = if resource_class.try(:connection_config).try(:[], :adapter).try(:include?, 'mysql')
23
+ @resource = if database_adapter&.include?('mysql')
24
24
  # fix for mysql default case insensitivity
25
25
  resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
26
26
  else
@@ -28,6 +28,19 @@ module DeviseTokenAuth::Concerns::ResourceFinder
28
28
  end
29
29
  end
30
30
 
31
+ def database_adapter
32
+ @database_adapter ||= begin
33
+ rails_version = [Rails::VERSION::MAJOR, Rails::VERSION::MINOR].join(".")
34
+
35
+ adapter =
36
+ if rails_version >= "6.1"
37
+ resource_class.try(:connection_db_config)&.try(:adapter)
38
+ else
39
+ resource_class.try(:connection_config)&.try(:[], :adapter)
40
+ end
41
+ end
42
+ end
43
+
31
44
  def resource_class(m = nil)
32
45
  mapping = if m
33
46
  Devise.mappings[m]
@@ -35,11 +35,20 @@ module DeviseTokenAuth::Concerns::SetUserByToken
35
35
  access_token_name = DeviseTokenAuth.headers_names[:'access-token']
36
36
  client_name = DeviseTokenAuth.headers_names[:'client']
37
37
 
38
+ # gets values from cookie if configured and present
39
+ parsed_auth_cookie = {}
40
+ if DeviseTokenAuth.cookie_enabled
41
+ auth_cookie = request.cookies[DeviseTokenAuth.cookie_name]
42
+ if auth_cookie.present?
43
+ parsed_auth_cookie = JSON.parse(auth_cookie)
44
+ end
45
+ end
46
+
38
47
  # parse header for values necessary for authentication
39
- uid = request.headers[uid_name] || params[uid_name]
48
+ uid = request.headers[uid_name] || params[uid_name] || parsed_auth_cookie[uid_name]
40
49
  @token = DeviseTokenAuth::TokenFactory.new unless @token
41
- @token.token ||= request.headers[access_token_name] || params[access_token_name]
42
- @token.client ||= request.headers[client_name] || params[client_name]
50
+ @token.token ||= request.headers[access_token_name] || params[access_token_name] || parsed_auth_cookie[access_token_name]
51
+ @token.client ||= request.headers[client_name] || params[client_name] || parsed_auth_cookie[client_name]
43
52
 
44
53
  # client isn't required, set to 'default' if absent
45
54
  @token.client ||= 'default'
@@ -101,6 +110,10 @@ module DeviseTokenAuth::Concerns::SetUserByToken
101
110
  # update the response header
102
111
  response.headers.merge!(auth_header)
103
112
 
113
+ # set a server cookie if configured
114
+ if DeviseTokenAuth.cookie_enabled
115
+ set_cookie(auth_header)
116
+ end
104
117
  else
105
118
  unless @resource.reload.valid?
106
119
  @resource = @resource.class.find(@resource.to_param) # errors remain after reload
@@ -123,11 +136,22 @@ module DeviseTokenAuth::Concerns::SetUserByToken
123
136
  # cleared by sign out in the meantime
124
137
  return if @used_auth_by_token && @resource.tokens[@token.client].nil?
125
138
 
139
+ _auth_header_from_batch_request = auth_header_from_batch_request
140
+
126
141
  # update the response header
127
- response.headers.merge!(auth_header_from_batch_request)
142
+ response.headers.merge!(_auth_header_from_batch_request)
143
+
144
+ # set a server cookie if configured
145
+ if DeviseTokenAuth.cookie_enabled
146
+ set_cookie(_auth_header_from_batch_request)
147
+ end
128
148
  end # end lock
129
149
  end
130
150
 
151
+ def set_cookie(auth_header)
152
+ cookies[DeviseTokenAuth.cookie_name] = DeviseTokenAuth.cookie_attributes.merge(value: auth_header.to_json)
153
+ end
154
+
131
155
  def is_batch_request?(user, client)
132
156
  !params[:unbatch] &&
133
157
  user.tokens[client] &&
@@ -55,13 +55,17 @@ module DeviseTokenAuth
55
55
 
56
56
  def render_create_success
57
57
  render json: {
58
- success: true,
59
- message: I18n.t('devise_token_auth.confirmations.sended', email: @email)
60
- }
58
+ success: true,
59
+ message: success_message('confirmations', @email)
60
+ }
61
61
  end
62
62
 
63
63
  def render_not_found_error
64
- render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
64
+ if Devise.paranoid
65
+ render_error(404, I18n.t('devise_token_auth.confirmations.sended_paranoid'))
66
+ else
67
+ render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
68
+ end
65
69
  end
66
70
 
67
71
  private
@@ -128,7 +128,7 @@ module DeviseTokenAuth
128
128
  def render_create_success
129
129
  render json: {
130
130
  success: true,
131
- message: I18n.t('devise_token_auth.passwords.sended', email: @email)
131
+ message: success_message('passwords', @email)
132
132
  }
133
133
  end
134
134
 
@@ -181,7 +181,11 @@ module DeviseTokenAuth
181
181
  end
182
182
 
183
183
  def render_not_found_error
184
- render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
184
+ if Devise.paranoid
185
+ render_error(404, I18n.t('devise_token_auth.passwords.sended_paranoid'))
186
+ else
187
+ render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
188
+ end
185
189
  end
186
190
 
187
191
  def validate_redirect_url_param
@@ -55,6 +55,12 @@ module DeviseTokenAuth
55
55
  user.tokens.delete(client)
56
56
  user.save!
57
57
 
58
+ if DeviseTokenAuth.cookie_enabled
59
+ # If a cookie is set with a domain specified then it must be deleted with that domain specified
60
+ # See https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html
61
+ cookies.delete(DeviseTokenAuth.cookie_name, domain: DeviseTokenAuth.cookie_attributes[:domain])
62
+ end
63
+
58
64
  yield user if block_given?
59
65
 
60
66
  render_destroy_success
@@ -63,7 +63,7 @@ module DeviseTokenAuth
63
63
  def render_create_success
64
64
  render json: {
65
65
  success: true,
66
- message: I18n.t('devise_token_auth.unlocks.sended', email: @email)
66
+ message: success_message('unlocks', @email)
67
67
  }
68
68
  end
69
69
 
@@ -79,7 +79,11 @@ module DeviseTokenAuth
79
79
  end
80
80
 
81
81
  def render_not_found_error
82
- render_error(404, I18n.t('devise_token_auth.unlocks.user_not_found', email: @email))
82
+ if Devise.paranoid
83
+ render_error(404, I18n.t('devise_token_auth.unlocks.sended_paranoid'))
84
+ else
85
+ render_error(404, I18n.t('devise_token_auth.unlocks.user_not_found', email: @email))
86
+ end
83
87
  end
84
88
 
85
89
  def resource_params
@@ -218,13 +218,8 @@ module DeviseTokenAuth::Concerns::User
218
218
  end
219
219
 
220
220
  def should_remove_tokens_after_password_reset?
221
- if Rails::VERSION::MAJOR <= 5 ||defined?('Mongoid')
222
- encrypted_password_changed? &&
223
- DeviseTokenAuth.remove_tokens_after_password_reset
224
- else
225
- saved_change_to_attribute?(:encrypted_password) &&
226
- DeviseTokenAuth.remove_tokens_after_password_reset
227
- end
221
+ DeviseTokenAuth.remove_tokens_after_password_reset &&
222
+ (respond_to?(:encrypted_password_changed?) && encrypted_password_changed?)
228
223
  end
229
224
 
230
225
  def remove_tokens_after_password_reset
@@ -23,8 +23,8 @@ module DeviseTokenAuth::Concerns::UserOmniauthCallbacks
23
23
  end
24
24
 
25
25
  def sync_uid
26
- if devise_modules.include?(:confirmable) && !@bypass_confirmation_postpone
27
- return if postpone_email_change?
26
+ unless self.new_record?
27
+ return if devise_modules.include?(:confirmable) && !@bypass_confirmation_postpone && postpone_email_change?
28
28
  end
29
29
  self.uid = email if email_provider?
30
30
  end
@@ -15,7 +15,7 @@
15
15
  Cordova / PhoneGap)
16
16
  */
17
17
 
18
- var data = JSON.parse(decodeURIComponent('<%= URI::escape( @data.to_json ) %>'));
18
+ var data = JSON.parse(decodeURIComponent('<%= ERB::Util.url_encode( @data.to_json ) %>'));
19
19
 
20
20
  window.addEventListener("message", function(ev) {
21
21
  if (ev.data === "requestCredentials") {
@@ -21,6 +21,7 @@ en:
21
21
  missing_redirect_url: "Missing redirect URL."
22
22
  not_allowed_redirect_url: "Redirect to '%{redirect_url}' not allowed."
23
23
  sended: "An email has been sent to '%{email}' containing instructions for resetting your password."
24
+ sended_paranoid: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
24
25
  user_not_found: "Unable to find user with email '%{email}'."
25
26
  password_not_required: "This account does not require a password. Sign in using your '%{provider}' account instead."
26
27
  missing_passwords: "You must fill out the fields labeled 'Password' and 'Password confirmation'."
@@ -28,9 +29,11 @@ en:
28
29
  unlocks:
29
30
  missing_email: "You must provide an email address."
30
31
  sended: "An email has been sent to '%{email}' containing instructions for unlocking your account."
32
+ sended_paranoid: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
31
33
  user_not_found: "Unable to find user with email '%{email}'."
32
34
  confirmations:
33
35
  sended: "An email has been sent to '%{email}' containing instructions for confirming your account."
36
+ sended_paranoid: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
34
37
  user_not_found: "Unable to find user with email '%{email}'."
35
38
  missing_email: "You must provide an email address."
36
39
 
@@ -1,2 +1,6 @@
1
1
  # don't serialize tokens
2
- Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION << :tokens
2
+ if defined? Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION
3
+ Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION << :tokens
4
+ else
5
+ Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION << :tokens
6
+ end
@@ -25,6 +25,9 @@ module DeviseTokenAuth
25
25
  :remove_tokens_after_password_reset,
26
26
  :default_callbacks,
27
27
  :headers_names,
28
+ :cookie_enabled,
29
+ :cookie_name,
30
+ :cookie_attributes,
28
31
  :bypass_sign_in,
29
32
  :send_confirmation_email,
30
33
  :require_client_password_reset_token
@@ -47,6 +50,9 @@ module DeviseTokenAuth
47
50
  'expiry': 'expiry',
48
51
  'uid': 'uid',
49
52
  'token-type': 'token-type' }
53
+ self.cookie_enabled = false
54
+ self.cookie_name = 'auth_cookie'
55
+ self.cookie_attributes = {}
50
56
  self.bypass_sign_in = true
51
57
  self.send_confirmation_email = false
52
58
  self.require_client_password_reset_token = false
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeviseTokenAuth
4
- VERSION = '1.1.5'.freeze
4
+ VERSION = '1.2.0'.freeze
5
5
  end
@@ -92,30 +92,102 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
92
92
  end
93
93
 
94
94
  describe 'resend confirmation' do
95
- before do
96
- post :create,
97
- params: { email: @new_user.email,
98
- redirect_url: @redirect_url },
99
- xhr: true
100
- @resource = assigns(:resource)
101
-
102
- @mail = ActionMailer::Base.deliveries.last
103
- @token, @client_config = token_and_client_config_from(@mail.body)
104
- end
105
-
106
- test 'user should not be confirmed' do
107
- assert_nil @resource.confirmed_at
95
+ describe 'without paranoid mode' do
96
+
97
+ describe 'on success' do
98
+ before do
99
+ post :create,
100
+ params: { email: @new_user.email,
101
+ redirect_url: @redirect_url },
102
+ xhr: true
103
+ @resource = assigns(:resource)
104
+ @data = JSON.parse(response.body)
105
+ @mail = ActionMailer::Base.deliveries.last
106
+ @token, @client_config = token_and_client_config_from(@mail.body)
107
+ end
108
+
109
+ test 'user should not be confirmed' do
110
+ assert_nil @resource.confirmed_at
111
+ end
112
+
113
+ test 'should generate raw token' do
114
+ assert @token
115
+ assert_equal @new_user.confirmation_token, @token
116
+ end
117
+
118
+ test 'user should receive confirmation email' do
119
+ assert_equal @resource.email, @mail['to'].to_s
120
+ end
121
+
122
+ test 'response should contain message' do
123
+ assert_equal @data['message'], I18n.t('devise_token_auth.confirmations.sended', email: @resource.email)
124
+ end
125
+ end
126
+
127
+ describe 'on failure' do
128
+ before do
129
+ post :create,
130
+ params: { email: 'chester@cheet.ah',
131
+ redirect_url: @redirect_url },
132
+ xhr: true
133
+ @data = JSON.parse(response.body)
134
+ end
135
+
136
+ test 'response should contain errors' do
137
+ assert_equal @data['errors'], [I18n.t('devise_token_auth.confirmations.user_not_found', email: 'chester@cheet.ah')]
138
+ end
139
+ end
108
140
  end
141
+ end
109
142
 
110
- test 'should generate raw token' do
111
- assert @token
112
- assert_equal @new_user.confirmation_token, @token
143
+ describe 'with paranoid mode' do
144
+ describe 'on success' do
145
+ before do
146
+ swap Devise, paranoid: true do
147
+ post :create,
148
+ params: { email: @new_user.email,
149
+ redirect_url: @redirect_url },
150
+ xhr: true
151
+ @resource = assigns(:resource)
152
+ @data = JSON.parse(response.body)
153
+ @mail = ActionMailer::Base.deliveries.last
154
+ @token, @client_config = token_and_client_config_from(@mail.body)
155
+ end
156
+ end
157
+
158
+ test 'user should not be confirmed' do
159
+ assert_nil @resource.confirmed_at
160
+ end
161
+
162
+ test 'should generate raw token' do
163
+ assert @token
164
+ assert_equal @new_user.confirmation_token, @token
165
+ end
166
+
167
+ test 'user should receive confirmation email' do
168
+ assert_equal @resource.email, @mail['to'].to_s
169
+ end
170
+
171
+ test 'response should contain message' do
172
+ assert_equal @data['message'], I18n.t('devise_token_auth.confirmations.sended_paranoid', email: @resource.email)
173
+ end
113
174
  end
114
175
 
115
- test 'user should receive confirmation email' do
116
- assert_equal @resource.email, @mail['to'].to_s
176
+ describe 'on failure' do
177
+ before do
178
+ swap Devise, paranoid: true do
179
+ post :create,
180
+ params: { email: 'chester@cheet.ah',
181
+ redirect_url: @redirect_url },
182
+ xhr: true
183
+ @data = JSON.parse(response.body)
184
+ end
185
+ end
186
+
187
+ test 'response should contain errors' do
188
+ assert_equal @data['errors'], [I18n.t('devise_token_auth.confirmations.sended_paranoid')]
189
+ end
117
190
  end
118
-
119
191
  end
120
192
  end
121
193
 
@@ -18,7 +18,7 @@ class OmniauthTest < ActionDispatch::IntegrationTest
18
18
 
19
19
  def get_parsed_data_json
20
20
  encoded_json_data = @response.body.match(/var data \= JSON.parse\(decodeURIComponent\(\'(.+)\'\)\)\;/)[1]
21
- JSON.parse(URI.unescape(encoded_json_data))
21
+ JSON.parse(CGI.unescape(encoded_json_data))
22
22
  end
23
23
 
24
24
  describe 'success callback' do
@@ -346,7 +346,7 @@ class OmniauthTest < ActionDispatch::IntegrationTest
346
346
  follow_all_redirects!
347
347
 
348
348
  data = get_parsed_data_json
349
- assert_equal "Redirect to &#39;#{@bad_redirect_url}&#39; not allowed.",
349
+ assert_equal "Redirect to '#{@bad_redirect_url}' not allowed.",
350
350
  data['error']
351
351
  end
352
352
 
@@ -85,37 +85,89 @@ class DeviseTokenAuth::PasswordsControllerTest < ActionController::TestCase
85
85
  end
86
86
 
87
87
  describe 'request password reset' do
88
- describe 'unknown user should return 404' do
89
- before do
90
- post :create,
91
- params: { email: 'chester@cheet.ah',
92
- redirect_url: @redirect_url }
93
- @data = JSON.parse(response.body)
94
- end
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
95
96
 
96
- test 'unknown user should return 404' do
97
- assert_equal 404, response.status
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
98
107
  end
99
108
 
100
- test 'errors should be returned' do
101
- assert @data['errors']
102
- assert_equal @data['errors'],
103
- [I18n.t('devise_token_auth.passwords.user_not_found',
104
- email: 'chester@cheet.ah')]
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 'unknown user should return 404' do
120
+ assert_equal 404, response.status
121
+ end
122
+
123
+ test 'errors should be returned' do
124
+ assert @data['errors']
125
+ assert_equal @data['errors'],
126
+ [I18n.t('devise_token_auth.passwords.sended_paranoid')]
127
+ end
105
128
  end
106
129
  end
107
130
 
108
131
  describe 'successfully requested password reset' do
109
- before do
110
- post :create,
111
- params: { email: @resource.email,
112
- redirect_url: @redirect_url }
132
+ describe 'without paranoid mode' do
133
+ before do
134
+ post :create,
135
+ params: { email: @resource.email,
136
+ redirect_url: @redirect_url }
113
137
 
114
- @data = JSON.parse(response.body)
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
115
150
  end
116
151
 
117
- test 'response should not contain extra data' do
118
- assert_nil @data['data']
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
119
171
  end
120
172
  end
121
173
 
@@ -10,6 +10,17 @@ require 'test_helper'
10
10
 
11
11
  class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::IntegrationTest
12
12
  describe DeviseTokenAuth::RegistrationsController do
13
+
14
+ def mock_registration_params
15
+ {
16
+ email: Faker::Internet.email,
17
+ password: 'secret123',
18
+ password_confirmation: 'secret123',
19
+ confirm_success_url: Faker::Internet.url,
20
+ unpermitted_param: '(x_x)'
21
+ }
22
+ end
23
+
13
24
  describe 'Validate non-empty body' do
14
25
  before do
15
26
  # need to post empty data
@@ -41,13 +52,7 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
41
52
  @mails_sent = ActionMailer::Base.deliveries.count
42
53
 
43
54
  post '/auth',
44
- params: {
45
- email: Faker::Internet.email,
46
- password: 'secret123',
47
- password_confirmation: 'secret123',
48
- confirm_success_url: Faker::Internet.url,
49
- unpermitted_param: '(x_x)'
50
- }
55
+ params: mock_registration_params
51
56
 
52
57
  @resource = assigns(:resource)
53
58
  @data = JSON.parse(response.body)
@@ -87,17 +92,10 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
87
92
  before do
88
93
  @original_duration = Devise.allow_unconfirmed_access_for
89
94
  Devise.allow_unconfirmed_access_for = nil
90
- post '/auth',
91
- params: {
92
- email: Faker::Internet.email,
93
- password: 'secret123',
94
- password_confirmation: 'secret123',
95
- confirm_success_url: Faker::Internet.url,
96
- unpermitted_param: '(x_x)'
97
- }
98
95
  end
99
96
 
100
97
  test 'auth headers were returned in response' do
98
+ post '/auth', params: mock_registration_params
101
99
  assert response.headers['access-token']
102
100
  assert response.headers['token-type']
103
101
  assert response.headers['client']
@@ -105,6 +103,21 @@ class DeviseTokenAuth::RegistrationsControllerTest < ActionDispatch::Integration
105
103
  assert response.headers['uid']
106
104
  end
107
105
 
106
+ describe 'using auth cookie' do
107
+ before do
108
+ DeviseTokenAuth.cookie_enabled = true
109
+ end
110
+
111
+ test 'auth cookie was returned in response' do
112
+ post '/auth', params: mock_registration_params
113
+ assert response.cookies[DeviseTokenAuth.cookie_name]
114
+ end
115
+
116
+ after do
117
+ DeviseTokenAuth.cookie_enabled = false
118
+ end
119
+ end
120
+
108
121
  after do
109
122
  Devise.allow_unconfirmed_access_for = @original_duration
110
123
  end
@@ -17,11 +17,12 @@ class DeviseTokenAuth::SessionsControllerTest < ActionController::TestCase
17
17
 
18
18
  describe 'success' do
19
19
  before do
20
- post :create,
21
- params: {
22
- email: @existing_user.email,
23
- password: @existing_user.password
24
- }
20
+ @user_session_params = {
21
+ email: @existing_user.email,
22
+ password: @existing_user.password
23
+ }
24
+
25
+ post :create, params: @user_session_params
25
26
 
26
27
  @resource = assigns(:resource)
27
28
  @data = JSON.parse(response.body)
@@ -35,17 +36,27 @@ class DeviseTokenAuth::SessionsControllerTest < ActionController::TestCase
35
36
  assert_equal @existing_user.email, @data['data']['email']
36
37
  end
37
38
 
39
+ describe 'using auth cookie' do
40
+ before do
41
+ DeviseTokenAuth.cookie_enabled = true
42
+ end
43
+
44
+ test 'request should return auth cookie' do
45
+ post :create, params: @user_session_params
46
+ assert response.cookies[DeviseTokenAuth.cookie_name]
47
+ end
48
+
49
+ after do
50
+ DeviseTokenAuth.cookie_enabled = false
51
+ end
52
+ end
53
+
38
54
  describe "with multiple clients and headers don't change in each request" do
39
55
  before do
40
56
  # Set the max_number_of_devices to a lower number
41
57
  # to expedite tests! (Default is 10)
42
58
  DeviseTokenAuth.max_number_of_devices = 2
43
59
  DeviseTokenAuth.change_headers_on_each_request = false
44
-
45
- @user_session_params = {
46
- email: @existing_user.email,
47
- password: @existing_user.password
48
- }
49
60
  end
50
61
 
51
62
  test 'should limit the maximum number of concurrent devices' do
@@ -159,6 +170,24 @@ class DeviseTokenAuth::SessionsControllerTest < ActionController::TestCase
159
170
  test 'session was destroyed' do
160
171
  assert_equal true, @controller.reset_session_called
161
172
  end
173
+
174
+ describe 'using auth cookie' do
175
+ before do
176
+ DeviseTokenAuth.cookie_enabled = true
177
+ @auth_token = @existing_user.create_new_auth_token
178
+ @controller.send(:cookies)[DeviseTokenAuth.cookie_name] = { value: @auth_token.to_json }
179
+ end
180
+
181
+ test 'auth cookie was destroyed' do
182
+ assert_equal @auth_token.to_json, @controller.send(:cookies)[DeviseTokenAuth.cookie_name] # sanity check
183
+ delete :destroy, format: :json
184
+ assert_nil @controller.send(:cookies)[DeviseTokenAuth.cookie_name]
185
+ end
186
+
187
+ after do
188
+ DeviseTokenAuth.cookie_enabled = false
189
+ end
190
+ end
162
191
  end
163
192
 
164
193
  describe 'unauthed user sign out' do
@@ -57,7 +57,7 @@ class DeviseTokenAuth::UnlocksControllerTest < ActionController::TestCase
57
57
  end
58
58
 
59
59
  describe 'request unlock' do
60
- describe 'unknown user should return 404' do
60
+ describe 'without paranoid mode' do
61
61
  before do
62
62
  post :create, params: { email: 'chester@cheet.ah' }
63
63
  @data = JSON.parse(response.body)
@@ -68,9 +68,26 @@ class DeviseTokenAuth::UnlocksControllerTest < ActionController::TestCase
68
68
 
69
69
  test 'errors should be returned' do
70
70
  assert @data['errors']
71
- assert_equal @data['errors'],
72
- [I18n.t('devise_token_auth.passwords.user_not_found',
73
- email: 'chester@cheet.ah')]
71
+ assert_equal @data['errors'], [I18n.t('devise_token_auth.unlocks.user_not_found',
72
+ email: 'chester@cheet.ah')]
73
+ end
74
+ end
75
+
76
+ describe 'with paranoid mode' do
77
+ before do
78
+ swap Devise, paranoid: true do
79
+ post :create, params: { email: 'chester@cheet.ah' }
80
+ @data = JSON.parse(response.body)
81
+ end
82
+ end
83
+
84
+ test 'unknown user should return 404' do
85
+ assert_equal 404, response.status
86
+ end
87
+
88
+ test 'errors should be returned' do
89
+ assert @data['errors']
90
+ assert_equal @data['errors'], [I18n.t('devise_token_auth.unlocks.sended_paranoid')]
74
91
  end
75
92
  end
76
93
 
@@ -38,7 +38,7 @@ class Overrides::ConfirmationsControllerTest < ActionDispatch::IntegrationTest
38
38
  override_proof_str = '(^^,)'
39
39
 
40
40
  # ensure present in redirect URL
41
- override_proof_param = URI.unescape(response.headers['Location']
41
+ override_proof_param = CGI.unescape(response.headers['Location']
42
42
  .match(/override_proof=([^&]*)&/)[1])
43
43
 
44
44
  assert_equal override_proof_str, override_proof_param
@@ -0,0 +1,6 @@
1
+ class ApplicationController < ActionController::Base
2
+ include DeviseTokenAuth::Concerns::SetUserByToken
3
+ def whatever
4
+ 'whatever'
5
+ end
6
+ end
@@ -1,9 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Azpire::V1::HumanResource::User < ActiveRecord::Base
3
+ class Azpire::V1::HumanResource::User
4
+ include Mongoid::Document
5
+ include Mongoid::Timestamps
6
+ include Mongoid::Locker
7
+
8
+ field :locker_locked_at, type: Time
9
+ field :locker_locked_until, type: Time
10
+
11
+ locker locked_at_field: :locker_locked_at,
12
+ locked_until_field: :locker_locked_until
13
+
14
+ ## Database authenticatable
15
+ field :email, type: String, default: ''
16
+ field :encrypted_password, type: String, default: ''
17
+
18
+ ## Recoverable
19
+ field :reset_password_token, type: String
20
+ field :reset_password_sent_at, type: Time
21
+ field :reset_password_redirect_url, type: String
22
+ field :allow_password_change, type: Boolean, default: false
23
+
24
+ ## Rememberable
25
+ field :remember_created_at, type: Time
26
+
27
+ ## Confirmable
28
+ field :confirmation_token, type: String
29
+ field :confirmed_at, type: Time
30
+ field :confirmation_sent_at, type: Time
31
+ field :unconfirmed_email, type: String # Only if using reconfirmable
32
+
33
+ ## Lockable
34
+ # field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
35
+ # field :unlock_token, type: String # Only if unlock strategy is :email or :both
36
+ # field :locked_at, type: Time
37
+
38
+ ## Required
39
+ field :provider, type: String
40
+ field :uid, type: String, default: ''
41
+
42
+ ## Tokens
43
+ field :tokens, type: Hash, default: {}
44
+
4
45
  # Include default devise modules. Others available are:
5
46
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
6
47
  devise :database_authenticatable, :registerable,
7
48
  :recoverable, :rememberable, :validatable
8
49
  include DeviseTokenAuth::Concerns::User
50
+
51
+ index({ email: 1 }, { name: 'email_index', unique: true, background: true })
52
+ index({ reset_password_token: 1 }, { name: 'reset_password_token_index', unique: true, sparse: true, background: true })
53
+ index({ confirmation_token: 1 }, { name: 'confirmation_token_index', unique: true, sparse: true, background: true })
54
+ index({ uid: 1, provider: 1}, { name: 'uid_provider_index', unique: true, background: true })
55
+ # index({ unlock_token: 1 }, { name: 'unlock_token_index', unique: true, sparse: true, background: true })
9
56
  end
@@ -3,9 +3,17 @@
3
3
  require 'test_helper'
4
4
 
5
5
  class DeviseTokenAuth::BlacklistTest < ActiveSupport::TestCase
6
- describe Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION do
7
- test 'should include :tokens' do
8
- assert Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION.include?(:tokens)
6
+ if defined? Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION
7
+ describe Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION do
8
+ test 'should include :tokens' do
9
+ assert Devise::Models::Authenticatable::UNSAFE_ATTRIBUTES_FOR_SERIALIZATION.include?(:tokens)
10
+ end
11
+ end
12
+ else
13
+ describe Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION do
14
+ test 'should include :tokens' do
15
+ assert Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION.include?(:tokens)
16
+ end
9
17
  end
10
18
  end
11
19
  end
data/test/test_helper.rb CHANGED
@@ -15,7 +15,11 @@ require File.expand_path('dummy/config/environment', __dir__)
15
15
  require 'active_support/testing/autorun'
16
16
  require 'minitest/rails'
17
17
  require 'mocha/minitest'
18
- require 'database_cleaner'
18
+ if DEVISE_TOKEN_AUTH_ORM == :active_record
19
+ require 'database_cleaner'
20
+ else
21
+ require 'database_cleaner/mongoid'
22
+ end
19
23
 
20
24
  FactoryBot.definition_file_paths = [File.expand_path('factories', __dir__)]
21
25
  FactoryBot.find_definitions
@@ -37,13 +41,40 @@ class ActiveSupport::TestCase
37
41
  ActiveRecord::Migration.check_pending! if DEVISE_TOKEN_AUTH_ORM == :active_record
38
42
 
39
43
  strategies = { active_record: :transaction,
40
- mongoid: :truncation }
44
+ mongoid: :deletion }
41
45
  DatabaseCleaner.strategy = strategies[DEVISE_TOKEN_AUTH_ORM]
42
46
  setup { DatabaseCleaner.start }
43
47
  teardown { DatabaseCleaner.clean }
44
48
 
45
49
  # Add more helper methods to be used by all tests here...
46
50
 
51
+ # Execute the block setting the given values and restoring old values after
52
+ # the block is executed.
53
+ # shamelessly copied from devise test_helper.
54
+ def swap(object, new_values)
55
+ old_values = {}
56
+ new_values.each do |key, value|
57
+ old_values[key] = object.send key
58
+ object.send :"#{key}=", value
59
+ end
60
+ clear_cached_variables(new_values)
61
+ yield
62
+ ensure
63
+ clear_cached_variables(new_values)
64
+ old_values.each do |key, value|
65
+ object.send :"#{key}=", value
66
+ end
67
+ end
68
+
69
+ # shamelessly copied from devise test_helper.
70
+ def clear_cached_variables(options)
71
+ if options.key?(:case_insensitive_keys) || options.key?(:strip_whitespace_keys)
72
+ Devise.mappings.each do |_, mapping|
73
+ mapping.to.instance_variable_set(:@devise_parameter_filter, nil)
74
+ end
75
+ end
76
+ end
77
+
47
78
  def age_token(user, client_id)
48
79
  if user.tokens[client_id]
49
80
  user.tokens[client_id]['updated_at'] = (Time.zone.now - (DeviseTokenAuth.batch_request_buffer_throttle + 10.seconds))
@@ -85,7 +116,7 @@ module Rails
85
116
  %w[get post patch put head delete get_via_redirect post_via_redirect].each do |method|
86
117
  define_method(method) do |path_or_action, **args|
87
118
  if Rails::VERSION::MAJOR >= 5
88
- super path_or_action, args
119
+ super path_or_action, **args
89
120
  else
90
121
  super path_or_action, args[:params], args[:headers]
91
122
  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.1.5
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lynn Hurley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-09 00:00:00.000000000 Z
11
+ date: 2021-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -319,9 +319,9 @@ files:
319
319
  - test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb
320
320
  - test/dummy/db/schema.rb
321
321
  - test/dummy/lib/migration_database_helper.rb
322
+ - test/dummy/tmp/generators/app/controllers/application_controller.rb
322
323
  - test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb
323
324
  - test/dummy/tmp/generators/config/initializers/devise_token_auth.rb
324
- - test/dummy/tmp/generators/db/migrate/20210126004321_devise_token_auth_create_azpire_v1_human_resource_users.rb
325
325
  - test/factories/users.rb
326
326
  - test/lib/devise_token_auth/blacklist_test.rb
327
327
  - test/lib/devise_token_auth/rails/custom_routes_test.rb
@@ -357,7 +357,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
357
357
  - !ruby/object:Gem::Version
358
358
  version: '0'
359
359
  requirements: []
360
- rubygems_version: 3.0.3
360
+ rubygems_version: 3.1.4
361
361
  signing_key:
362
362
  specification_version: 4
363
363
  summary: Token based authentication for rails. Uses Devise + OmniAuth.
@@ -432,8 +432,8 @@ test_files:
432
432
  - test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb
433
433
  - test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb
434
434
  - test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb
435
+ - test/dummy/tmp/generators/app/controllers/application_controller.rb
435
436
  - test/dummy/tmp/generators/config/initializers/devise_token_auth.rb
436
- - test/dummy/tmp/generators/db/migrate/20210126004321_devise_token_auth_create_azpire_v1_human_resource_users.rb
437
437
  - test/dummy/README.rdoc
438
438
  - test/models/only_email_user_test.rb
439
439
  - test/models/confirmable_user_test.rb
@@ -1,49 +0,0 @@
1
- class DeviseTokenAuthCreateAzpireV1HumanResourceUsers < ActiveRecord::Migration[5.2]
2
- def change
3
-
4
- create_table(:azpire_v1_human_resource_users) do |t|
5
- ## Required
6
- t.string :provider, :null => false, :default => "email"
7
- t.string :uid, :null => false, :default => ""
8
-
9
- ## Database authenticatable
10
- t.string :encrypted_password, :null => false, :default => ""
11
-
12
- ## Recoverable
13
- t.string :reset_password_token
14
- t.datetime :reset_password_sent_at
15
- t.boolean :allow_password_change, :default => false
16
-
17
- ## Rememberable
18
- t.datetime :remember_created_at
19
-
20
- ## Confirmable
21
- t.string :confirmation_token
22
- t.datetime :confirmed_at
23
- t.datetime :confirmation_sent_at
24
- t.string :unconfirmed_email # Only if using reconfirmable
25
-
26
- ## Lockable
27
- # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
28
- # t.string :unlock_token # Only if unlock strategy is :email or :both
29
- # t.datetime :locked_at
30
-
31
- ## User Info
32
- t.string :name
33
- t.string :nickname
34
- t.string :image
35
- t.string :email
36
-
37
- ## Tokens
38
- t.text :tokens
39
-
40
- t.timestamps
41
- end
42
-
43
- add_index :azpire_v1_human_resource_users, :email, unique: true
44
- add_index :azpire_v1_human_resource_users, [:uid, :provider], unique: true
45
- add_index :azpire_v1_human_resource_users, :reset_password_token, unique: true
46
- add_index :azpire_v1_human_resource_users, :confirmation_token, unique: true
47
- # add_index :azpire_v1_human_resource_users, :unlock_token, unique: true
48
- end
49
- end