devise_token_auth 1.0.0 → 1.1.1

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.

Potentially problematic release.


This version of devise_token_auth might be problematic. Click here for more details.

Files changed (83) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +4 -2
  3. data/app/controllers/devise_token_auth/application_controller.rb +0 -1
  4. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +11 -12
  5. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +39 -55
  6. data/app/controllers/devise_token_auth/confirmations_controller.rb +62 -20
  7. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +51 -26
  8. data/app/controllers/devise_token_auth/passwords_controller.rb +19 -23
  9. data/app/controllers/devise_token_auth/registrations_controller.rb +32 -40
  10. data/app/controllers/devise_token_auth/sessions_controller.rb +5 -5
  11. data/app/controllers/devise_token_auth/unlocks_controller.rb +4 -4
  12. data/app/models/devise_token_auth/concerns/active_record_support.rb +16 -0
  13. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  14. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +19 -0
  15. data/app/models/devise_token_auth/concerns/user.rb +44 -67
  16. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +2 -2
  17. data/app/validators/{email_validator.rb → devise_token_auth_email_validator.rb} +1 -1
  18. data/config/locales/en.yml +5 -0
  19. data/config/locales/he.yml +50 -0
  20. data/config/locales/ja.yml +1 -1
  21. data/lib/devise_token_auth/blacklist.rb +2 -0
  22. data/lib/devise_token_auth/engine.rb +2 -0
  23. data/lib/devise_token_auth/rails/routes.rb +1 -1
  24. data/lib/devise_token_auth/token_factory.rb +126 -0
  25. data/lib/devise_token_auth/version.rb +1 -1
  26. data/lib/devise_token_auth.rb +6 -3
  27. data/lib/generators/devise_token_auth/install_generator.rb +3 -87
  28. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  29. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  30. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +5 -0
  31. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +0 -7
  32. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
  33. data/test/controllers/custom/custom_confirmations_controller_test.rb +1 -1
  34. data/test/controllers/demo_user_controller_test.rb +2 -2
  35. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +79 -19
  36. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +2 -0
  37. data/test/controllers/devise_token_auth/passwords_controller_test.rb +115 -94
  38. data/test/controllers/devise_token_auth/registrations_controller_test.rb +31 -4
  39. data/test/controllers/devise_token_auth/sessions_controller_test.rb +0 -38
  40. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +2 -1
  41. data/test/dummy/app/{models → active_record}/scoped_user.rb +2 -2
  42. data/test/dummy/app/{models → active_record}/unconfirmable_user.rb +1 -2
  43. data/test/dummy/app/{models → active_record}/unregisterable_user.rb +3 -3
  44. data/test/dummy/app/active_record/user.rb +6 -0
  45. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +3 -3
  46. data/test/dummy/app/controllers/overrides/passwords_controller.rb +3 -3
  47. data/test/dummy/app/controllers/overrides/registrations_controller.rb +1 -1
  48. data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
  49. data/test/dummy/app/models/{user.rb → concerns/favorite_color.rb} +7 -8
  50. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  51. data/test/dummy/app/mongoid/mang.rb +46 -0
  52. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  53. data/test/dummy/app/mongoid/scoped_user.rb +50 -0
  54. data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
  55. data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
  56. data/test/dummy/app/mongoid/user.rb +49 -0
  57. data/test/dummy/config/application.rb +23 -1
  58. data/test/dummy/config/boot.rb +4 -0
  59. data/test/dummy/config/initializers/devise.rb +285 -0
  60. data/test/dummy/config/initializers/devise_token_auth.rb +35 -4
  61. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +0 -7
  62. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +0 -7
  63. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +0 -7
  64. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +0 -7
  65. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +0 -7
  66. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +0 -7
  67. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +0 -7
  68. data/test/dummy/db/schema.rb +1 -28
  69. data/test/factories/users.rb +1 -1
  70. data/test/lib/devise_token_auth/blacklist_test.rb +11 -0
  71. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  72. data/test/lib/generators/devise_token_auth/install_generator_test.rb +51 -31
  73. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +51 -31
  74. data/test/models/concerns/mongoid_support_test.rb +31 -0
  75. data/test/models/concerns/tokens_serialization_test.rb +70 -0
  76. data/test/models/only_email_user_test.rb +0 -8
  77. data/test/models/user_test.rb +1 -33
  78. data/test/test_helper.rb +12 -2
  79. metadata +105 -25
  80. data/config/initializers/devise.rb +0 -198
  81. /data/test/dummy/app/{models → active_record}/lockable_user.rb +0 -0
  82. /data/test/dummy/app/{models → active_record}/mang.rb +0 -0
  83. /data/test/dummy/app/{models → active_record}/only_email_user.rb +0 -0
@@ -0,0 +1,126 @@
1
+ require 'bcrypt'
2
+
3
+ module DeviseTokenAuth
4
+ # A token management factory which allow generate token objects and check them.
5
+ module TokenFactory
6
+ # For BCrypt::Password class see:
7
+ # https://github.com/codahale/bcrypt-ruby/blob/master/lib/bcrypt/password.rb
8
+
9
+ # Creates a token instance. Takes an optional client, lifespan and cost options.
10
+ # Example:
11
+ # DeviseTokenAuth::TokenFactory.create
12
+ # => #<struct DeviseTokenAuth::TokenFactory::Token client="tElcgkdZ7f9XEa0unZhrYQ", token="rAMcWOs0-mGHFMnIgJD2cA", token_hash="$2a$10$wrsdlHVRGlYW11wfImxU..jr0Ux3bHo/qbXcSfgp8zmvVUNHosita", expiry=1518982690>
13
+ #
14
+ # DeviseTokenAuth::TokenFactory.create(lifespan: 10, cost: 4)
15
+ # => #<struct DeviseTokenAuth::TokenFactory::Token client="5qleT7_t9JPVcX9xmxkVYA", token="RBXX43u4xXNSO-fr2N_4pA", token_hash="$2a$04$9gpCaoFbu2dUKxU3qiTgluHX7jj9UzS.jq1QW0EkQmoaxARo1WxTy", expiry=1517773268>
16
+ def self.create(client: nil, lifespan: nil, cost: nil)
17
+ # obj_client = client.nil? ? client() : client
18
+ obj_client = client || client()
19
+ obj_token = token
20
+ obj_token_hash = token_hash(obj_token, cost)
21
+ obj_expiry = expiry(lifespan)
22
+
23
+ Token.new(obj_client, obj_token, obj_token_hash, obj_expiry)
24
+ end
25
+
26
+ # Generates a random URL-safe client.
27
+ # Example:
28
+ # DeviseTokenAuth::TokenFactory.client
29
+ # => "zNf0pNP5iGfuBItZJGCseQ"
30
+ def self.client
31
+ secure_string
32
+ end
33
+
34
+ # Generates a random URL-safe token.
35
+ # Example:
36
+ # DeviseTokenAuth::TokenFactory.token
37
+ # => "6Bqs4K9x8ChLmZogvruF3A"
38
+ def self.token
39
+ secure_string
40
+ end
41
+
42
+ # Returns token hash for a token with given cost. If no cost value is specified,
43
+ # the default value is used. The possible cost value is within range from 4 to 31.
44
+ # It is recommended to not use a value more than 10.
45
+ # Example:
46
+ # DeviseTokenAuth::TokenFactory.token_hash("_qxAxmc-biQLiYRHsmwd5Q")
47
+ # => "$2a$10$6/cTAtQ3CBLfpkeHW7dlt.PD2aVCbFRN5vDDJUUhGsZ6pzYFlh4Me"
48
+ #
49
+ # DeviseTokenAuth::TokenFactory.token_hash("_qxAxmc-biQLiYRHsmwd5Q", 4)
50
+ # => "$2a$04$RkIrosbdRtuet2eUk3si8eS4ufeNpiPc/rSSsfpniRK8ogM5YFOWS"
51
+ def self.token_hash(token, cost = nil)
52
+ cost ||= DeviseTokenAuth.token_cost
53
+ BCrypt::Password.create(token, cost: cost)
54
+ end
55
+
56
+ # Returns the value of time as an integer number of seconds. Takes one argument.
57
+ # Example:
58
+ # DeviseTokenAuth::TokenFactory.expiry
59
+ # => 1518983359
60
+ # DeviseTokenAuth::TokenFactory.expiry(10)
61
+ # => 1517773781
62
+ def self.expiry(lifespan = nil)
63
+ lifespan ||= DeviseTokenAuth.token_lifespan
64
+ (Time.zone.now + lifespan).to_i
65
+ end
66
+
67
+ # Generates a random URL-safe string.
68
+ # Example:
69
+ # DeviseTokenAuth::TokenFactory.secure_string
70
+ # => "ADBoIaqXsEDnxIpOuumrTA"
71
+ def self.secure_string
72
+ # https://ruby-doc.org/stdlib-2.5.0/libdoc/securerandom/rdoc/Random/Formatter.html#method-i-urlsafe_base64
73
+ SecureRandom.urlsafe_base64
74
+ end
75
+
76
+ # Returns true if token hash is a valid token hash.
77
+ # Example:
78
+ # token_hash = "$2a$10$ArjX0tskRIa5Z/Tmapy59OCiAXLStfhrCiaDz.8fCb6hnX1gJ0p/2"
79
+ # DeviseTokenAuth::TokenFactory.valid_token_hash?(token_hash)
80
+ # => true
81
+ def self.valid_token_hash?(token_hash)
82
+ !!BCrypt::Password.valid_hash?(token_hash)
83
+ end
84
+
85
+ # Compares a potential token against the token hash. Returns true if the token is the original token, false otherwise.
86
+ # Example:
87
+ # token = "4wZ9gcc900rMQD1McpcSNA"
88
+ # token_hash = "$2a$10$ArjX0tskRIa5Z/Tmapy59OCiAXLStfhrCiaDz.8fCb6hnX1gJ0p/2"
89
+ # DeviseTokenAuth::TokenFactory.token_hash_is_token?(token_hash, token)
90
+ # => true
91
+ def self.token_hash_is_token?(token_hash, token)
92
+ BCrypt::Password.new(token_hash).is_password?(token)
93
+ rescue StandardError
94
+ false
95
+ end
96
+
97
+ # Creates a token instance with instance variables equal nil.
98
+ # Example:
99
+ # DeviseTokenAuth::TokenFactory.new
100
+ # => #<struct DeviseTokenAuth::TokenFactory::Token client=nil, token=nil, token_hash=nil, expiry=nil>
101
+ def self.new
102
+ Token.new
103
+ end
104
+
105
+ Token = Struct.new(:client, :token, :token_hash, :expiry) do
106
+ # Sets all instance variables of the token to nil. It is faster than creating new empty token.
107
+ # Example:
108
+ # token.clear!
109
+ # => true
110
+ # token
111
+ # => #<struct DeviseTokenAuth::TokenFactory::Token client=nil, token=nil, token_hash=nil, expiry=nil>
112
+ def clear!
113
+ size.times { |i| self[i] = nil }
114
+ true
115
+ end
116
+
117
+ # Checks token attribute presence
118
+ # Example:
119
+ # token.present?
120
+ # => true
121
+ def present?
122
+ token.present?
123
+ end
124
+ end
125
+ end
126
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeviseTokenAuth
4
- VERSION = '1.0.0'.freeze
4
+ VERSION = '1.1.1'.freeze
5
5
  end
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'devise'
4
+
5
+ module DeviseTokenAuth
6
+ end
7
+
4
8
  require 'devise_token_auth/engine'
5
9
  require 'devise_token_auth/controllers/helpers'
6
10
  require 'devise_token_auth/controllers/url_helpers'
7
11
  require 'devise_token_auth/url'
8
12
  require 'devise_token_auth/errors'
9
-
10
- module DeviseTokenAuth
11
- end
13
+ require 'devise_token_auth/blacklist'
14
+ require 'devise_token_auth/token_factory'
@@ -1,20 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'install_generator_helpers'
4
+
3
5
  module DeviseTokenAuth
4
6
  class InstallGenerator < Rails::Generators::Base
5
7
  include Rails::Generators::Migration
8
+ include DeviseTokenAuth::InstallGeneratorHelpers
6
9
 
7
10
  class_option :primary_key_type, type: :string, desc: 'The type for primary key'
8
11
 
9
- source_root File.expand_path('templates', __dir__)
10
-
11
- argument :user_class, type: :string, default: 'User'
12
- argument :mount_path, type: :string, default: 'auth'
13
-
14
- def create_initializer_file
15
- copy_file('devise_token_auth.rb', 'config/initializers/devise_token_auth.rb')
16
- end
17
-
18
12
  def copy_migrations
19
13
  if self.class.migration_exists?('db/migrate', "devise_token_auth_create_#{user_class.pluralize.gsub('::','').underscore}")
20
14
  say_status('skipped', "Migration 'devise_token_auth_create_#{user_class.pluralize.gsub('::','').underscore}' already exists")
@@ -47,90 +41,12 @@ module DeviseTokenAuth
47
41
  end
48
42
  end
49
43
 
50
- def include_controller_concerns
51
- fname = 'app/controllers/application_controller.rb'
52
- line = 'include DeviseTokenAuth::Concerns::SetUserByToken'
53
-
54
- if File.exist?(File.join(destination_root, fname))
55
- if parse_file_for_line(fname, line)
56
- say_status('skipped', 'Concern is already included in the application controller.')
57
- elsif is_rails_api?
58
- inject_into_file fname, after: "class ApplicationController < ActionController::API\n" do <<-'RUBY'
59
- include DeviseTokenAuth::Concerns::SetUserByToken
60
- RUBY
61
- end
62
- else
63
- inject_into_file fname, after: "class ApplicationController < ActionController::Base\n" do <<-'RUBY'
64
- include DeviseTokenAuth::Concerns::SetUserByToken
65
- RUBY
66
- end
67
- end
68
- else
69
- say_status('skipped', "app/controllers/application_controller.rb not found. Add 'include DeviseTokenAuth::Concerns::SetUserByToken' to any controllers that require authentication.")
70
- end
71
- end
72
-
73
- def add_route_mount
74
- f = 'config/routes.rb'
75
- str = "mount_devise_token_auth_for '#{user_class}', at: '#{mount_path}'"
76
-
77
- if File.exist?(File.join(destination_root, f))
78
- line = parse_file_for_line(f, 'mount_devise_token_auth_for')
79
-
80
- if line
81
- existing_user_class = true
82
- else
83
- line = 'Rails.application.routes.draw do'
84
- existing_user_class = false
85
- end
86
-
87
- if parse_file_for_line(f, str)
88
- say_status('skipped', "Routes already exist for #{user_class} at #{mount_path}")
89
- else
90
- insert_after_line(f, line, str)
91
-
92
- if existing_user_class
93
- scoped_routes = ''\
94
- "as :#{user_class.underscore} do\n"\
95
- " # Define routes for #{user_class} within this block.\n"\
96
- " end\n"
97
- insert_after_line(f, str, scoped_routes)
98
- end
99
- end
100
- else
101
- say_status('skipped', "config/routes.rb not found. Add \"mount_devise_token_auth_for '#{user_class}', at: '#{mount_path}'\" to your routes file.")
102
- end
103
- end
104
-
105
44
  private
106
45
 
107
46
  def self.next_migration_number(path)
108
47
  Time.zone.now.utc.strftime('%Y%m%d%H%M%S')
109
48
  end
110
49
 
111
- def insert_after_line(filename, line, str)
112
- gsub_file filename, /(#{Regexp.escape(line)})/mi do |match|
113
- "#{match}\n #{str}"
114
- end
115
- end
116
-
117
- def parse_file_for_line(filename, str)
118
- match = false
119
-
120
- File.open(File.join(destination_root, filename)) do |f|
121
- f.each_line do |line|
122
- match = line if line =~ /(#{Regexp.escape(str)})/mi
123
- end
124
- end
125
- match
126
- end
127
-
128
- def is_rails_api?
129
- fname = 'app/controllers/application_controller.rb'
130
- line = 'class ApplicationController < ActionController::API'
131
- parse_file_for_line(fname, line)
132
- end
133
-
134
50
  def json_supported_database?
135
51
  (postgres? && postgres_correct_version?) || (mysql? && mysql_correct_version?)
136
52
  end
@@ -0,0 +1,98 @@
1
+ module DeviseTokenAuth
2
+ module InstallGeneratorHelpers
3
+ class << self
4
+ def included(mod)
5
+ mod.class_eval do
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ argument :user_class, type: :string, default: 'User'
9
+ argument :mount_path, type: :string, default: 'auth'
10
+
11
+ def create_initializer_file
12
+ copy_file('devise_token_auth.rb', 'config/initializers/devise_token_auth.rb')
13
+ end
14
+
15
+ def include_controller_concerns
16
+ fname = 'app/controllers/application_controller.rb'
17
+ line = 'include DeviseTokenAuth::Concerns::SetUserByToken'
18
+
19
+ if File.exist?(File.join(destination_root, fname))
20
+ if parse_file_for_line(fname, line)
21
+ say_status('skipped', 'Concern is already included in the application controller.')
22
+ elsif is_rails_api?
23
+ inject_into_file fname, after: "class ApplicationController < ActionController::API\n" do <<-'RUBY'
24
+ include DeviseTokenAuth::Concerns::SetUserByToken
25
+ RUBY
26
+ end
27
+ else
28
+ inject_into_file fname, after: "class ApplicationController < ActionController::Base\n" do <<-'RUBY'
29
+ include DeviseTokenAuth::Concerns::SetUserByToken
30
+ RUBY
31
+ end
32
+ end
33
+ else
34
+ say_status('skipped', "app/controllers/application_controller.rb not found. Add 'include DeviseTokenAuth::Concerns::SetUserByToken' to any controllers that require authentication.")
35
+ end
36
+ end
37
+
38
+ def add_route_mount
39
+ f = 'config/routes.rb'
40
+ str = "mount_devise_token_auth_for '#{user_class}', at: '#{mount_path}'"
41
+
42
+ if File.exist?(File.join(destination_root, f))
43
+ line = parse_file_for_line(f, 'mount_devise_token_auth_for')
44
+
45
+ if line
46
+ existing_user_class = true
47
+ else
48
+ line = 'Rails.application.routes.draw do'
49
+ existing_user_class = false
50
+ end
51
+
52
+ if parse_file_for_line(f, str)
53
+ say_status('skipped', "Routes already exist for #{user_class} at #{mount_path}")
54
+ else
55
+ insert_after_line(f, line, str)
56
+
57
+ if existing_user_class
58
+ scoped_routes = ''\
59
+ "as :#{user_class.underscore} do\n"\
60
+ " # Define routes for #{user_class} within this block.\n"\
61
+ " end\n"
62
+ insert_after_line(f, str, scoped_routes)
63
+ end
64
+ end
65
+ else
66
+ say_status('skipped', "config/routes.rb not found. Add \"mount_devise_token_auth_for '#{user_class}', at: '#{mount_path}'\" to your routes file.")
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def insert_after_line(filename, line, str)
73
+ gsub_file filename, /(#{Regexp.escape(line)})/mi do |match|
74
+ "#{match}\n #{str}"
75
+ end
76
+ end
77
+
78
+ def parse_file_for_line(filename, str)
79
+ match = false
80
+
81
+ File.open(File.join(destination_root, filename)) do |f|
82
+ f.each_line do |line|
83
+ match = line if line =~ /(#{Regexp.escape(str)})/mi
84
+ end
85
+ end
86
+ match
87
+ end
88
+
89
+ def is_rails_api?
90
+ fname = 'app/controllers/application_controller.rb'
91
+ line = 'class ApplicationController < ActionController::API'
92
+ parse_file_for_line(fname, line)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'install_generator_helpers'
4
+
5
+ module DeviseTokenAuth
6
+ class InstallMongoidGenerator < Rails::Generators::Base
7
+ include DeviseTokenAuth::InstallGeneratorHelpers
8
+
9
+ def create_user_model
10
+ fname = "app/models/#{user_class.underscore}.rb"
11
+ if File.exist?(File.join(destination_root, fname))
12
+ inclusion = 'include DeviseTokenAuth::Concerns::User'
13
+ unless parse_file_for_line(fname, inclusion)
14
+ inject_into_file fname, before: /end\s\z/ do <<-'RUBY'
15
+
16
+ include Mongoid::Locker
17
+
18
+ field :locker_locked_at, type: Time
19
+ field :locker_locked_until, type: Time
20
+
21
+ locker locked_at_field: :locker_locked_at,
22
+ locked_until_field: :locker_locked_until
23
+
24
+ ## Required
25
+ field :provider, type: String
26
+ field :uid, type: String, default: ''
27
+
28
+ ## Tokens
29
+ field :tokens, type: Hash, default: {}
30
+
31
+ # Include default devise modules. Others available are:
32
+ # :confirmable, :lockable, :timeoutable and :omniauthable
33
+ devise :database_authenticatable, :registerable,
34
+ :recoverable, :rememberable, :trackable, :validatable
35
+ include DeviseTokenAuth::Concerns::User
36
+
37
+ index({ uid: 1, provider: 1}, { name: 'uid_provider_index', unique: true, background: true })
38
+ RUBY
39
+ end
40
+ end
41
+ else
42
+ template('user_mongoid.rb.erb', fname)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -11,6 +11,11 @@ DeviseTokenAuth.setup do |config|
11
11
  # determines how long tokens will remain valid after they are issued.
12
12
  # config.token_lifespan = 2.weeks
13
13
 
14
+ # Limiting the token_cost to just 4 in testing will increase the performance of
15
+ # your test suite dramatically. The possible cost value is within range from 4
16
+ # to 31. It is recommended to not use a value more than 10 in other environments.
17
+ config.token_cost = Rails.env.test? ? 4 : 10
18
+
14
19
  # Sets the max number of concurrent devices per user, which is 10 by default.
15
20
  # After this limit is reached, the oldest tokens will be removed.
16
21
  # config.max_number_of_devices = 10
@@ -17,13 +17,6 @@ class DeviseTokenAuthCreate<%= user_class.pluralize.gsub("::","") %> < ActiveRec
17
17
  ## Rememberable
18
18
  t.datetime :remember_created_at
19
19
 
20
- ## Trackable
21
- t.integer :sign_in_count, :default => 0, :null => false
22
- t.datetime :current_sign_in_at
23
- t.datetime :last_sign_in_at
24
- t.string :current_sign_in_ip
25
- t.string :last_sign_in_ip
26
-
27
20
  ## Confirmable
28
21
  t.string :confirmation_token
29
22
  t.datetime :confirmed_at
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= user_class %>
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
+
45
+ # Include default devise modules. Others available are:
46
+ # :confirmable, :lockable, :timeoutable and :omniauthable
47
+ devise :database_authenticatable, :registerable,
48
+ :recoverable, :rememberable, :trackable, :validatable
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 })
56
+ end
@@ -5,7 +5,7 @@ require 'test_helper'
5
5
  class Custom::ConfirmationsControllerTest < ActionController::TestCase
6
6
  describe Custom::ConfirmationsController do
7
7
  include CustomControllersRoutes
8
-
8
+
9
9
  before do
10
10
  @redirect_url = Faker::Internet.url
11
11
  @new_user = create(:user)
@@ -321,8 +321,8 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
321
321
  assert @resource.tokens.count > 1
322
322
 
323
323
  # password changed from new device
324
- @resource.update_attributes(password: 'newsecret123',
325
- password_confirmation: 'newsecret123')
324
+ @resource.update(password: 'newsecret123',
325
+ password_confirmation: 'newsecret123')
326
326
 
327
327
  get '/demo/members_only',
328
328
  params: {},
@@ -23,6 +23,7 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
23
23
  @new_user.send_confirmation_instructions(redirect_url: @redirect_url)
24
24
  mail = ActionMailer::Base.deliveries.last
25
25
  @token, @client_config = token_and_client_config_from(mail.body)
26
+ @token_params = %w[access-token client client_id config expiry token uid]
26
27
  end
27
28
 
28
29
  test 'should generate raw token' do
@@ -38,32 +39,79 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
38
39
  end
39
40
 
40
41
  describe 'success' do
41
- before do
42
- get :show,
43
- params: { confirmation_token: @token,
44
- redirect_url: @redirect_url },
45
- xhr: true
46
- @resource = assigns(:resource)
47
- end
42
+ describe 'when authenticated' do
43
+ before do
44
+ sign_in(@new_user)
45
+ get :show,
46
+ params: { confirmation_token: @token,
47
+ redirect_url: @redirect_url },
48
+ xhr: true
49
+ @resource = assigns(:resource)
50
+ end
48
51
 
49
- test 'user should now be confirmed' do
50
- assert @resource.confirmed?
51
- end
52
+ test 'user should now be confirmed' do
53
+ assert @resource.confirmed?
54
+ end
52
55
 
53
- test 'should redirect to success url' do
54
- assert_redirected_to(/^#{@redirect_url}/)
55
- end
56
+ test 'should redirect to success url' do
57
+ assert_redirected_to(/^#{@redirect_url}/)
58
+ end
56
59
 
57
- test 'the sign_in_count should be 1' do
58
- assert @resource.sign_in_count == 1
60
+ test 'redirect url includes token params' do
61
+ assert @token_params.all? { |param| response.body.include?(param) }
62
+ assert response.body.include?('account_confirmation_success')
63
+ end
59
64
  end
60
65
 
61
- test 'User shoud have the signed in info filled' do
62
- assert @resource.current_sign_in_at?
66
+ describe 'when unauthenticated' do
67
+ before do
68
+ sign_out(@new_user)
69
+ get :show,
70
+ params: { confirmation_token: @token,
71
+ redirect_url: @redirect_url },
72
+ xhr: true
73
+ @resource = assigns(:resource)
74
+ end
75
+
76
+ test 'user should now be confirmed' do
77
+ assert @resource.confirmed?
78
+ end
79
+
80
+ test 'should redirect to success url' do
81
+ assert_redirected_to(/^#{@redirect_url}/)
82
+ end
83
+
84
+ test 'redirect url does not include token params' do
85
+ refute @token_params.any? { |param| response.body.include?(param) }
86
+ assert response.body.include?('account_confirmation_success')
87
+ end
63
88
  end
64
89
 
65
- test 'User shoud have the Last checkin filled' do
66
- assert @resource.last_sign_in_at?
90
+ describe 'resend confirmation' do
91
+ before do
92
+ post :create,
93
+ params: { email: @new_user.email,
94
+ redirect_url: @redirect_url },
95
+ xhr: true
96
+ @resource = assigns(:resource)
97
+
98
+ @mail = ActionMailer::Base.deliveries.last
99
+ @token, @client_config = token_and_client_config_from(@mail.body)
100
+ end
101
+
102
+ test 'user should not be confirmed' do
103
+ assert_nil @resource.confirmed_at
104
+ end
105
+
106
+ test 'should generate raw token' do
107
+ assert @token
108
+ assert_equal @new_user.confirmation_token, @token
109
+ end
110
+
111
+ test 'user should receive confirmation email' do
112
+ assert_equal @resource.email, @mail['to'].to_s
113
+ end
114
+
67
115
  end
68
116
  end
69
117
 
@@ -75,6 +123,18 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
75
123
  @resource = assigns(:resource)
76
124
  refute @resource.confirmed?
77
125
  end
126
+
127
+ test 'request resend confirmation without email' do
128
+ post :create, params: { email: nil }, xhr: true
129
+
130
+ assert_equal 401, response.status
131
+ end
132
+
133
+ test 'user should not be found on resend confirmation request' do
134
+ post :create, params: { email: 'bogus' }, xhr: true
135
+
136
+ assert_equal 404, response.status
137
+ end
78
138
  end
79
139
  end
80
140
 
@@ -155,6 +155,8 @@ class OmniauthTest < ActionDispatch::IntegrationTest
155
155
  describe 'with new user' do
156
156
  before do
157
157
  User.any_instance.expects(:new_record?).returns(true).at_least_once
158
+ # https://docs.mongodb.com/mongoid/master/tutorials/mongoid-documents/#notes-on-persistence
159
+ User.any_instance.expects(:save!).returns(true)
158
160
  end
159
161
 
160
162
  test 'response contains oauth_registration attr' do