devise_token_auth 0.1.32.beta10 → 0.1.32

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -31
  3. data/app/controllers/devise_token_auth/confirmations_controller.rb +2 -0
  4. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +2 -0
  5. data/app/controllers/devise_token_auth/passwords_controller.rb +25 -14
  6. data/app/controllers/devise_token_auth/registrations_controller.rb +22 -11
  7. data/app/controllers/devise_token_auth/sessions_controller.rb +15 -9
  8. data/app/controllers/devise_token_auth/token_validations_controller.rb +2 -1
  9. data/app/models/devise_token_auth/concerns/user.rb +19 -14
  10. data/app/validators/email_validator.rb +1 -1
  11. data/config/locales/en.yml +30 -0
  12. data/config/locales/es.yml +30 -0
  13. data/config/locales/fr.yml +30 -0
  14. data/lib/devise_token_auth/engine.rb +10 -8
  15. data/lib/devise_token_auth/version.rb +1 -1
  16. data/lib/generators/devise_token_auth/install_generator.rb +28 -0
  17. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +6 -0
  18. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +2 -2
  19. data/test/controllers/custom/custom_confirmations_controller_test.rb +26 -0
  20. data/test/controllers/custom/custom_omniauth_callbacks_controller_test.rb +29 -0
  21. data/test/controllers/custom/custom_passwords_controller_test.rb +66 -0
  22. data/test/controllers/custom/custom_registrations_controller_test.rb +1 -1
  23. data/test/controllers/custom/custom_sessions_controller_test.rb +30 -0
  24. data/test/controllers/custom/custom_token_validations_controller_test.rb +29 -0
  25. data/test/controllers/devise_token_auth/passwords_controller_test.rb +159 -10
  26. data/test/controllers/devise_token_auth/registrations_controller_test.rb +249 -58
  27. data/test/controllers/devise_token_auth/sessions_controller_test.rb +80 -1
  28. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +17 -0
  29. data/test/dummy/app/controllers/application_controller.rb +1 -0
  30. data/test/dummy/app/controllers/custom/confirmations_controller.rb +13 -0
  31. data/test/dummy/app/controllers/custom/omniauth_callbacks_controller.rb +13 -0
  32. data/test/dummy/app/controllers/custom/passwords_controller.rb +35 -0
  33. data/test/dummy/app/controllers/custom/sessions_controller.rb +23 -0
  34. data/test/dummy/app/controllers/custom/token_validations_controller.rb +13 -0
  35. data/test/dummy/app/models/unconfirmable_user.rb +8 -0
  36. data/test/dummy/config/application.rb +1 -0
  37. data/test/dummy/config/routes.rb +8 -1
  38. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +7 -1
  39. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +7 -1
  40. data/test/dummy/db/migrate/20140928231203_devise_token_auth_create_evil_users.rb +7 -1
  41. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +7 -1
  42. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +7 -1
  43. data/test/dummy/db/migrate/20150409095712_devise_token_auth_create_nice_users.rb +7 -1
  44. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +60 -0
  45. data/test/dummy/db/schema.rb +89 -64
  46. data/test/dummy/db/test.sqlite3 +0 -0
  47. data/test/dummy/lib/migration_database_helper.rb +29 -0
  48. data/test/dummy/log/test.log +41319 -29566
  49. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +6 -0
  50. data/test/dummy/tmp/generators/config/routes.rb +4 -0
  51. data/test/dummy/tmp/generators/db/migrate/{20150617175802_devise_token_auth_create_users.rb → 20150729144233_devise_token_auth_create_users.rb} +1 -1
  52. data/test/fixtures/unconfirmable_users.yml +9 -0
  53. data/test/fixtures/users.yml +12 -0
  54. data/test/models/user_test.rb +21 -0
  55. metadata +39 -13
  56. data/config/locales/devise.en.yml +0 -59
  57. data/test/dummy/db/development.sqlite3 +0 -0
  58. data/test/dummy/log/development.log +0 -473
  59. data/test/dummy/tmp/generators/app/controllers/application_controller.rb +0 -6
@@ -6,6 +6,7 @@ module DeviseTokenAuth
6
6
  def validate_token
7
7
  # @resource will have been set by set_user_token concern
8
8
  if @resource
9
+ yield if block_given?
9
10
  render json: {
10
11
  success: true,
11
12
  data: @resource.token_validation_response
@@ -13,7 +14,7 @@ module DeviseTokenAuth
13
14
  else
14
15
  render json: {
15
16
  success: false,
16
- errors: ["Invalid login credentials"]
17
+ errors: [I18n.t("devise_token_auth.token_validations.invalid")]
17
18
  }, status: 401
18
19
  end
19
20
  end
@@ -21,7 +21,9 @@ module DeviseTokenAuth::Concerns::User
21
21
  self.devise_modules.delete(:omniauthable)
22
22
  end
23
23
 
24
- serialize :tokens, JSON
24
+ unless tokens_has_json_column_type?
25
+ serialize :tokens, JSON
26
+ end
25
27
 
26
28
  validates :email, presence: true, email: true, if: Proc.new { |u| u.provider == 'email' }
27
29
  validates_presence_of :uid, if: Proc.new { |u| u.provider != 'email' }
@@ -76,18 +78,21 @@ module DeviseTokenAuth::Concerns::User
76
78
  # fall back to "default" config name
77
79
  opts[:client_config] ||= "default"
78
80
 
79
- if respond_to?(:pending_reconfirmation?) && pending_reconfirmation?
80
- opts[:to] = unconfirmed_email
81
- else
82
- opts[:to] = email
83
- end
84
-
85
81
  send_devise_notification(:reset_password_instructions, token, opts)
86
82
 
87
83
  token
88
84
  end
89
85
  end
90
86
 
87
+ module ClassMethods
88
+ protected
89
+
90
+
91
+ def tokens_has_json_column_type?
92
+ table_exists? && self.columns_hash['tokens'] && self.columns_hash['tokens'].type.in?([:json, :jsonb])
93
+ end
94
+ end
95
+
91
96
 
92
97
  def valid_token?(token, client_id='default')
93
98
  client_id ||= 'default'
@@ -218,16 +223,14 @@ module DeviseTokenAuth::Concerns::User
218
223
  protected
219
224
 
220
225
 
221
- # NOTE: ensure that fragment comes AFTER querystring for proper $location
222
- # parsing using AngularJS.
223
226
  def generate_url(url, params = {})
224
227
  uri = URI(url)
225
228
 
226
229
  res = "#{uri.scheme}://#{uri.host}"
227
230
  res += ":#{uri.port}" if (uri.port and uri.port != 80 and uri.port != 443)
228
231
  res += "#{uri.path}" if uri.path
229
- res += "##{uri.fragment}" if uri.fragment
230
232
  res += "?#{params.to_query}"
233
+ res += "##{uri.fragment}" if uri.fragment
231
234
 
232
235
  return res
233
236
  end
@@ -248,10 +251,12 @@ module DeviseTokenAuth::Concerns::User
248
251
  end
249
252
 
250
253
  def destroy_expired_tokens
251
- self.tokens.delete_if{|cid,v|
252
- expiry = v[:expiry] || v["expiry"]
253
- DateTime.strptime(expiry.to_s, '%s') < Time.now
254
- }
254
+ if self.tokens
255
+ self.tokens.delete_if do |cid, v|
256
+ expiry = v[:expiry] || v["expiry"]
257
+ DateTime.strptime(expiry.to_s, '%s') < Time.now
258
+ end
259
+ end
255
260
  end
256
261
 
257
262
  end
@@ -1,7 +1,7 @@
1
1
  class EmailValidator < ActiveModel::EachValidator
2
2
  def validate_each(record, attribute, value)
3
3
  unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
4
- record.errors[attribute] << (options[:message] || 'is not an email')
4
+ record.errors[attribute] << (options[:message] || I18n.t("errors.not_email"))
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,30 @@
1
+ en:
2
+ devise_token_auth:
3
+ sessions:
4
+ not_confirmed: "A confirmation email was sent to your account at %{email}. You must follow the instructions in the email before your account can be activated"
5
+ bad_credentials: "Invalid login credentials. Please try again."
6
+ not_supported: "Use POST /sign_in to sign in. GET is not supported."
7
+ user_not_found: "User was not found or was not logged in."
8
+ token_validations:
9
+ invalid: "Invalid login credentials"
10
+ registrations:
11
+ missing_confirm_success_url: "Missing `confirm_success_url` param."
12
+ redirect_url_not_allowed: "Redirect to %{redirect_url} not allowed."
13
+ email_already_exists: "An account already exists for %{email}"
14
+ account_with_uid_destroyed: "Account with uid %{uid} has been destroyed."
15
+ account_to_destroy_not_found: "Unable to locate account for destruction."
16
+ user_not_found: "User not found."
17
+ passwords:
18
+ missing_email: "You must provide an email address."
19
+ missing_redirect_url: "Missing redirect url."
20
+ not_allowed_redirect_url: "Redirect to %{redirect_url} not allowed."
21
+ sended: "An email has been sent to %{email} containing instructions for resetting your password."
22
+ user_not_found: "Unable to find user with email '%{email}'."
23
+ password_not_required: "This account does not require a password. Sign in using your %{provider} account instead."
24
+ missing_passwords: 'You must fill out the fields labeled "password" and "password confirmation".'
25
+ successfully_updated: "Your password has been successfully updated."
26
+
27
+ errors:
28
+ validate_sign_up_params: "Please submit proper sign up data in request body."
29
+ validate_account_update_params: "Please submit proper account update data in request body."
30
+ not_email: "is not an email"
@@ -0,0 +1,30 @@
1
+ es:
2
+ devise_token_auth:
3
+ sessions:
4
+ not_confirmed: "Un correo electrónico de confirmación de su cuenta ha sido enviado a %{email}. Por favor, siga las instrucciones para validar su cuenta"
5
+ bad_credentials: "Identidad o contraseña no válida."
6
+ not_supported: "Use POST /sign_in para la conexión. GET no esta disponible."
7
+ user_not_found: "Usuario desconocido o no está conectado."
8
+ token_validations:
9
+ invalid: "Identidad o contraseña no válida."
10
+ registrations:
11
+ missing_confirm_success_url: "El parámetro `confirm_success_url` no esta presente."
12
+ redirect_url_not_allowed: "Redirección hacia %{redirect_url} no esta permitida."
13
+ email_already_exists: "Una cuenta ya existe con este correo electrónico: %{email}"
14
+ account_with_uid_destroyed: "La cuenta con el identificador %{uid} se ha eliminado."
15
+ account_to_destroy_not_found: "No se puede encontrar la cuenta a borrar."
16
+ user_not_found: "Usuario no encontrado."
17
+ passwords:
18
+ missing_email: "Debe incluir un correo electrónico."
19
+ missing_redirect_url: "Falta el Url de redirección."
20
+ not_allowed_redirect_url: "Redirección hacia %{redirect_url} no esta permitida."
21
+ sended: "Un correo electrónico ha sido enviado a %{email} con las instrucciones para restablecer su contraseña."
22
+ user_not_found: "No se pudo encontrar un usuario con este correo electrónico: '%{email}'."
23
+ password_not_required: "Esta cuenta no requiere contraseña. Iniciar sesión utilizando %{provider}."
24
+ missing_passwords: 'Debe llenar los campos "contraseña" y "confirmación de contraseña".'
25
+ successfully_updated: "Su contraseña ha sido actualizada con éxito."
26
+
27
+ errors:
28
+ validate_sign_up_params: "Los datos introducidos en la solicitud de acceso no son válidos."
29
+ validate_account_update_params: "Los datos introducidos en la solicitud de actualización no son válidos."
30
+ not_email: "no es un correo electrónico"
@@ -0,0 +1,30 @@
1
+ fr:
2
+ devise_token_auth:
3
+ sessions:
4
+ not_confirmed: "Une email de confirmation de votre compte a été envoyé à %{email}. Merci de suivre les instructions afin de valider votre compte"
5
+ bad_credentials: "Mot de passe ou identifiant invalide."
6
+ not_supported: "Utilisez POST /sign_in pour la connexion. GET n'est pas supporté."
7
+ user_not_found: "L'utilisateur est inconnu ou n'est pas connecté."
8
+ token_validations:
9
+ invalid: "Mot de passe ou identifiant invalide."
10
+ registrations:
11
+ missing_confirm_success_url: "Le paramètre `confirm_success_url` est manquant."
12
+ redirect_url_not_allowed: "Redirection vers %{redirect_url} n'est pas autorisée."
13
+ email_already_exists: "Un compte existe déjà avec cet email: %{email}"
14
+ account_with_uid_destroyed: "Le compte avec l'identifiant %{uid} a été supprimé."
15
+ account_to_destroy_not_found: "Impossible de trouver le compte à supprimer."
16
+ user_not_found: "Utilisateur non trouvé."
17
+ passwords:
18
+ missing_email: "Vous devez soumettre un email."
19
+ missing_redirect_url: "Url de redirection manquante."
20
+ not_allowed_redirect_url: "Redirection vers %{redirect_url} n'est pas autorisée."
21
+ sended: "Un email a été envoyé à %{email} avec les instructions pour réinitialiser votre mot de passe."
22
+ user_not_found: "Impossible de trouver un utilisateur avec cet email: '%{email}'."
23
+ password_not_required: "Ce compte ne demande pas de mot de passe. Connectez vous plutôt en utilisant %{provider}."
24
+ missing_passwords: 'Vous devez remplir les champs "mt de passe" et "confirmation de mot de passe".'
25
+ successfully_updated: "Votre mot de passe a été correctement mis à jour."
26
+
27
+ errors:
28
+ validate_sign_up_params: "Les données de l'inscription dans le corps de la requête ne sont pas valides."
29
+ validate_account_update_params: "Les données de mise à jour dans le corps de la requête ne sont pas valides."
30
+ not_email: "n'est pas un email"
@@ -15,15 +15,17 @@ module DeviseTokenAuth
15
15
  :omniauth_prefix,
16
16
  :default_confirm_success_url,
17
17
  :default_password_reset_url,
18
- :redirect_whitelist
18
+ :redirect_whitelist,
19
+ :check_current_password_before_update
19
20
 
20
- self.change_headers_on_each_request = true
21
- self.token_lifespan = 2.weeks
22
- self.batch_request_buffer_throttle = 5.seconds
23
- self.omniauth_prefix = '/omniauth'
24
- self.default_confirm_success_url = nil
25
- self.default_password_reset_url = nil
26
- self.redirect_whitelist = nil
21
+ self.change_headers_on_each_request = true
22
+ self.token_lifespan = 2.weeks
23
+ self.batch_request_buffer_throttle = 5.seconds
24
+ self.omniauth_prefix = '/omniauth'
25
+ self.default_confirm_success_url = nil
26
+ self.default_password_reset_url = nil
27
+ self.redirect_whitelist = nil
28
+ self.check_current_password_before_update = false
27
29
 
28
30
  def self.setup(&block)
29
31
  yield self
@@ -1,3 +1,3 @@
1
1
  module DeviseTokenAuth
2
- VERSION = "0.1.32.beta10"
2
+ VERSION = "0.1.32"
3
3
  end
@@ -115,5 +115,33 @@ module DeviseTokenAuth
115
115
  end
116
116
  match
117
117
  end
118
+
119
+ def json_supported_database?
120
+ (postgres? && postgres_correct_version?) || (mysql? && mysql_correct_version?)
121
+ end
122
+
123
+ def postgres?
124
+ database_name == 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter'
125
+ end
126
+
127
+ def postgres_correct_version?
128
+ database_version > '9.3'
129
+ end
130
+
131
+ def mysql?
132
+ database_name == 'ActiveRecord::ConnectionAdapters::MysqlAdapter'
133
+ end
134
+
135
+ def mysql_correct_version?
136
+ database_version > '5.7.7'
137
+ end
138
+
139
+ def database_name
140
+ ActiveRecord::Base.connection.class.name
141
+ end
142
+
143
+ def database_version
144
+ ActiveRecord::Base.connection.select_value('SELECT VERSION()')
145
+ end
118
146
  end
119
147
  end
@@ -19,4 +19,10 @@ DeviseTokenAuth.setup do |config|
19
19
  # example, using the default '/omniauth', the github oauth2 provider will
20
20
  # redirect successful authentications to '/omniauth/github/callback'
21
21
  #config.omniauth_prefix = "/omniauth"
22
+
23
+ # By defult sending current password is not needed for the password update.
24
+ # Uncomment to enforce current_password param to be checked before all
25
+ # attribute updates. Set it to :password if you want it to be checked only if
26
+ # password is updated.
27
+ # config.check_current_password_before_update = :attributes
22
28
  end
@@ -2,7 +2,7 @@ class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
2
2
  def change
3
3
  create_table(:<%= user_class.pluralize.underscore %>) do |t|
4
4
  ## Required
5
- t.string :provider, :null => false
5
+ t.string :provider, :null => false, :default => "email"
6
6
  t.string :uid, :null => false, :default => ""
7
7
 
8
8
  ## Database authenticatable
@@ -40,7 +40,7 @@ class DeviseTokenAuthCreate<%= user_class.pluralize %> < ActiveRecord::Migration
40
40
  t.string :email
41
41
 
42
42
  ## Tokens
43
- t.text :tokens
43
+ <%= json_supported_database? ? 't.json :tokens' : 't.text :tokens' %>
44
44
 
45
45
  t.timestamps
46
46
  end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ class Custom::ConfirmationsControllerTest < ActionController::TestCase
4
+
5
+ describe Custom::ConfirmationsController do
6
+
7
+ before do
8
+ @redirect_url = Faker::Internet.url
9
+ @new_user = users(:unconfirmed_email_user)
10
+ @new_user.send_confirmation_instructions({
11
+ redirect_url: @redirect_url
12
+ })
13
+ @mail = ActionMailer::Base.deliveries.last
14
+ @token = @mail.body.match(/confirmation_token=([^&]*)&/)[1]
15
+ @client_config = @mail.body.match(/config=([^&]*)&/)[1]
16
+
17
+ get :show, {confirmation_token: @token, redirect_url: @redirect_url}
18
+ end
19
+
20
+ test "yield resource to block on show success" do
21
+ assert @controller.show_block_called?, "show failed to yield resource to provided block"
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class Custom::OmniauthCallbacksControllerTest < ActionDispatch::IntegrationTest
4
+
5
+ describe Custom::OmniauthCallbacksController do
6
+
7
+ setup do
8
+ OmniAuth.config.test_mode = true
9
+ OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new({
10
+ :provider => 'facebook',
11
+ :uid => '123545',
12
+ :info => {
13
+ name: 'swong',
14
+ email: 'swongsong@yandex.ru'
15
+ }
16
+ })
17
+ end
18
+
19
+ test "yield resource to block on omniauth_sucess success" do
20
+ @redirect_url = "http://ng-token-auth.dev/"
21
+ get_via_redirect '/nice_user_auth/facebook', {
22
+ auth_origin_url: @redirect_url
23
+ }
24
+ assert @controller.omniauth_success_block_called?, "omniauth_success failed to yield resource to provided block"
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class Custom::PasswordsControllerTest < ActionController::TestCase
4
+
5
+ describe Custom::PasswordsController do
6
+
7
+ before do
8
+ @resource = users(:confirmed_email_user)
9
+ @redirect_url = 'http://ng-token-auth.dev'
10
+ end
11
+
12
+ test "yield resource to block on create success" do
13
+ post :create, {
14
+ email: @resource.email,
15
+ redirect_url: @redirect_url
16
+ }
17
+
18
+ @mail = ActionMailer::Base.deliveries.last
19
+ @resource.reload
20
+
21
+ @mail_config_name = CGI.unescape(@mail.body.match(/config=([^&]*)&/)[1])
22
+ @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
23
+ @mail_reset_token = @mail.body.match(/reset_password_token=(.*)\"/)[1]
24
+
25
+ assert @controller.create_block_called?, "create failed to yield resource to provided block"
26
+ end
27
+
28
+ test "yield resource to block on edit success" do
29
+ @resource = users(:unconfirmed_email_user)
30
+ @redirect_url = 'http://ng-token-auth.dev'
31
+
32
+ xhr :post, :create, {
33
+ email: @resource.email,
34
+ redirect_url: @redirect_url
35
+ }
36
+
37
+ @mail = ActionMailer::Base.deliveries.last
38
+ @resource.reload
39
+
40
+ @mail_config_name = CGI.unescape(@mail.body.match(/config=([^&]*)&/)[1])
41
+ @mail_redirect_url = CGI.unescape(@mail.body.match(/redirect_url=([^&]*)&/)[1])
42
+ @mail_reset_token = @mail.body.match(/reset_password_token=(.*)\"/)[1]
43
+
44
+ xhr :get, :edit, {
45
+ reset_password_token: @mail_reset_token,
46
+ redirect_url: @mail_redirect_url
47
+ }
48
+
49
+ @resource.reload
50
+ assert @controller.edit_block_called?, "edit failed to yield resource to provided block"
51
+ end
52
+
53
+ test "yield resource to block on update success" do
54
+ @auth_headers = @resource.create_new_auth_token
55
+ request.headers.merge!(@auth_headers)
56
+ @new_password = Faker::Internet.password
57
+ put :update, {
58
+ password: @new_password,
59
+ password_confirmation: @new_password
60
+ }
61
+ assert @controller.update_block_called?, "update failed to yield resource to provided block"
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -35,7 +35,7 @@ class Custom::RegistrationsControllerTest < ActionDispatch::IntegrationTest
35
35
 
36
36
  test "yield resource to block on destroy success" do
37
37
  delete '/nice_user_auth', @auth_headers
38
- assert @controller.destroy_block_called?, "update failed to yield resource to provided block"
38
+ assert @controller.destroy_block_called?, "destroy failed to yield resource to provided block"
39
39
  end
40
40
 
41
41
  end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ class Custom::SessionsControllerTest < ActionController::TestCase
4
+
5
+ describe Custom::SessionsController do
6
+
7
+ before do
8
+ @existing_user = users(:confirmed_email_user)
9
+ @existing_user.skip_confirmation!
10
+ @existing_user.save!
11
+ end
12
+
13
+ test "yield resource to block on create success" do
14
+ post :create, {
15
+ email: @existing_user.email,
16
+ password: 'secret123'
17
+ }
18
+ assert @controller.create_block_called?, "create failed to yield resource to provided block"
19
+ end
20
+
21
+ test "yield resource to block on destroy success" do
22
+ @auth_headers = @existing_user.create_new_auth_token
23
+ request.headers.merge!(@auth_headers)
24
+ delete :destroy, format: :json
25
+ assert @controller.destroy_block_called?, "destroy failed to yield resource to provided block"
26
+ end
27
+
28
+ end
29
+
30
+ end