devise-security 0.13.0 → 0.14.0.rc1

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -1
  3. data/.gitignore +1 -0
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +30 -12
  6. data/Appraisals +21 -5
  7. data/Gemfile +8 -1
  8. data/README.md +47 -7
  9. data/app/views/devise/paranoid_verification_code/show.html.erb +1 -1
  10. data/app/views/devise/password_expired/show.html.erb +1 -1
  11. data/config/locales/de.yml +11 -11
  12. data/config/locales/fr.yml +13 -13
  13. data/config/locales/ja.yml +29 -0
  14. data/devise-security.gemspec +12 -6
  15. data/gemfiles/rails_4.2_stable.gemfile +9 -1
  16. data/gemfiles/rails_5.0_stable.gemfile +8 -1
  17. data/gemfiles/rails_5.1_stable.gemfile +8 -1
  18. data/gemfiles/{rails_5.2.0.gemfile → rails_5.2_stable.gemfile} +8 -1
  19. data/gemfiles/rails_6.0_beta.gemfile +15 -0
  20. data/lib/devise-security.rb +2 -4
  21. data/lib/devise-security/models/{old_password.rb → active_record/old_password.rb} +1 -2
  22. data/lib/devise-security/models/compatibility.rb +6 -15
  23. data/lib/devise-security/models/compatibility/active_record.rb +29 -0
  24. data/lib/devise-security/models/compatibility/mongoid.rb +21 -0
  25. data/lib/devise-security/models/database_authenticatable_patch.rb +1 -1
  26. data/lib/devise-security/models/expirable.rb +6 -2
  27. data/lib/devise-security/models/mongoid/old_password.rb +21 -0
  28. data/lib/devise-security/models/password_archivable.rb +16 -7
  29. data/lib/devise-security/models/password_expirable.rb +5 -0
  30. data/lib/devise-security/models/secure_validatable.rb +2 -2
  31. data/lib/devise-security/orm/mongoid.rb +7 -0
  32. data/lib/devise-security/patches/controller_security_question.rb +1 -1
  33. data/lib/devise-security/version.rb +1 -1
  34. data/lib/generators/devise_security/install_generator.rb +1 -1
  35. data/test/dummy/app/models/application_record.rb +8 -2
  36. data/test/dummy/app/models/application_user_record.rb +11 -0
  37. data/test/dummy/app/models/captcha_user.rb +5 -2
  38. data/test/dummy/app/models/mongoid/confirmable_fields.rb +13 -0
  39. data/test/dummy/app/models/mongoid/database_authenticable_fields.rb +17 -0
  40. data/test/dummy/app/models/mongoid/expirable_fields.rb +11 -0
  41. data/test/dummy/app/models/mongoid/lockable_fields.rb +13 -0
  42. data/test/dummy/app/models/mongoid/mappings.rb +13 -0
  43. data/test/dummy/app/models/mongoid/omniauthable_fields.rb +11 -0
  44. data/test/dummy/app/models/mongoid/paranoid_verification_fields.rb +10 -0
  45. data/test/dummy/app/models/mongoid/password_archivable_fields.rb +9 -0
  46. data/test/dummy/app/models/mongoid/password_expirable_fields.rb +10 -0
  47. data/test/dummy/app/models/mongoid/recoverable_fields.rb +11 -0
  48. data/test/dummy/app/models/mongoid/registerable_fields.rb +19 -0
  49. data/test/dummy/app/models/mongoid/rememberable_fields.rb +10 -0
  50. data/test/dummy/app/models/mongoid/secure_validatable_fields.rb +11 -0
  51. data/test/dummy/app/models/mongoid/security_questionable_fields.rb +13 -0
  52. data/test/dummy/app/models/mongoid/session_limitable_fields.rb +10 -0
  53. data/test/dummy/app/models/mongoid/timeoutable_fields.rb +9 -0
  54. data/test/dummy/app/models/mongoid/trackable_fields.rb +14 -0
  55. data/test/dummy/app/models/mongoid/validatable_fields.rb +7 -0
  56. data/test/dummy/app/models/secure_user.rb +5 -1
  57. data/test/dummy/app/models/security_question_user.rb +7 -4
  58. data/test/dummy/app/models/user.rb +5 -0
  59. data/test/dummy/app/models/widget.rb +4 -0
  60. data/test/dummy/app/mongoid/admin.rb +31 -0
  61. data/test/dummy/app/mongoid/one_user.rb +58 -0
  62. data/test/dummy/app/mongoid/shim.rb +25 -0
  63. data/test/dummy/app/mongoid/user_on_engine.rb +41 -0
  64. data/test/dummy/app/mongoid/user_on_main_app.rb +41 -0
  65. data/test/dummy/app/mongoid/user_with_validations.rb +37 -0
  66. data/test/dummy/app/mongoid/user_without_email.rb +35 -0
  67. data/test/dummy/config/application.rb +10 -7
  68. data/test/dummy/config/environments/test.rb +2 -2
  69. data/test/dummy/config/initializers/devise.rb +3 -4
  70. data/test/dummy/config/initializers/migration_class.rb +8 -6
  71. data/test/dummy/config/mongoid.yml +6 -0
  72. data/test/dummy/lib/shared_expirable_columns.rb +14 -0
  73. data/test/dummy/lib/shared_security_questions_fields.rb +16 -0
  74. data/test/dummy/lib/shared_user.rb +32 -0
  75. data/test/dummy/lib/shared_user_with_password_verification.rb +13 -0
  76. data/test/dummy/lib/shared_user_without_email.rb +28 -0
  77. data/test/dummy/lib/shared_user_without_omniauth.rb +15 -0
  78. data/test/dummy/lib/shared_verification_fields.rb +15 -0
  79. data/test/orm/active_record.rb +12 -0
  80. data/test/orm/mongoid.rb +12 -0
  81. data/test/support/mongoid.yml +6 -0
  82. data/test/test_helper.rb +16 -9
  83. data/test/test_install_generator.rb +1 -0
  84. data/test/test_password_archivable.rb +6 -7
  85. data/test/test_password_expirable.rb +3 -1
  86. data/test/test_secure_validatable.rb +11 -10
  87. data/test/test_security_question_controller.rb +9 -11
  88. metadata +125 -16
@@ -0,0 +1,13 @@
1
+ Dir[File.expand_path("*_fields.rb", __dir__)].each { |f| require_relative f }
2
+
3
+ module Mongoid
4
+ module Mappings
5
+ extend ::ActiveSupport::Concern
6
+
7
+ included do
8
+ self.devise_modules.each do |devise_module_name|
9
+ include "#{devise_module_name.to_s.classify}Fields".constantize
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module OmniauthableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Omniautable
8
+ field :username, type: String
9
+ field :facebook_token, type: String
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module ParanoidVerificationFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+ field :paranoid_verification_code, type: String
7
+ field :paranoid_verified_at, type: Time
8
+ field :paranoid_verification_attempt, type: Integer, default: 0
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module PasswordArchivableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## PasswordArchivableFields
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module PasswordExpirableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ field :expired_at, type: Time
8
+ field :last_activity_at, type: Time
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module RecoverableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Recoverable
8
+ field :reset_password_token, type: String
9
+ field :reset_password_sent_at, type: Time
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module RegisterableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Database authenticatable
8
+ field :email, type: String, default: ""
9
+ validates_presence_of :email
10
+
11
+ field :encrypted_password, type: String, default: ""
12
+ validates_presence_of :encrypted_password
13
+
14
+ field :password_changed_at, type: Time
15
+ index({ password_changed_at: 1 }, {})
16
+ index({ email: 1 }, {})
17
+ include Mongoid::Timestamps
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module RememberableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Rememberable
8
+ field :remember_created_at, type: Time
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module SecureValidatableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ field :password_changed_at, type: Time
8
+ index({ password_changed_at: 1 }, {})
9
+ include Mongoid::Timestamps
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module SecurityQuestionableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Security Questionable
8
+ field :locked_at, type: Time
9
+ field :unlock_token, type: String
10
+ field :security_question_id, type: Integer
11
+ field :security_question_answer, type: String
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module SessionLimitableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Session Limitable
8
+ field :unique_session_id, type: String
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module TimeoutableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Timeoutable
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module TrackableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+
7
+ ## Trackable
8
+ field :sign_in_count, type: Integer, default: 0
9
+ field :current_sign_in_at, type: Time
10
+ field :last_sign_in_at, type: Time
11
+ field :current_sign_in_ip, type: String
12
+ field :last_sign_in_ip, type: String
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module ValidatableFields
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+ include Mongoid::Document
6
+ end
7
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class SecureUser < ApplicationRecord
3
+ class SecureUser < ApplicationUserRecord
4
4
  devise :database_authenticatable, :secure_validatable, email_validation: false
5
+ if DEVISE_ORM == :mongoid
6
+ require './test/dummy/app/models/mongoid/mappings'
7
+ include ::Mongoid::Mappings
8
+ end
5
9
  end
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class SecurityQuestionUser < ApplicationRecord
4
- self.table_name = 'users'
5
- devise :database_authenticatable, :password_archivable, :lockable,
6
- :paranoid_verification, :password_expirable, :security_questionable
3
+ class SecurityQuestionUser < ApplicationUserRecord
4
+ devise :database_authenticatable, :lockable, :security_questionable
5
+ if DEVISE_ORM == :mongoid
6
+ require './test/dummy/app/models/mongoid/mappings'
7
+ include ::Mongoid::Mappings
8
+ field :security_question_answer, type: String
9
+ end
7
10
  end
@@ -21,4 +21,9 @@ class User < ApplicationRecord
21
21
  :validatable
22
22
 
23
23
  has_many :widgets
24
+
25
+ if DEVISE_ORM == :mongoid
26
+ require './test/dummy/app/models/mongoid/mappings'
27
+ include ::Mongoid::Mappings
28
+ end
24
29
  end
@@ -3,4 +3,8 @@
3
3
  class Widget < ApplicationRecord
4
4
  belongs_to :user
5
5
  validates_associated :user
6
+
7
+ if DEVISE_ORM == :mongoid
8
+ field :name, type: String
9
+ end
6
10
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shared_admin'
4
+
5
+ class Admin
6
+ include Mongoid::Document
7
+ include Shim
8
+ include SharedAdmin
9
+
10
+ ## Database authenticatable
11
+ field :email, type: String
12
+ field :encrypted_password, type: String
13
+
14
+ ## Recoverable
15
+ field :reset_password_token, type: String
16
+ field :reset_password_sent_at, type: Time
17
+
18
+ ## Rememberable
19
+ field :remember_created_at, type: Time
20
+
21
+ ## Confirmable
22
+ field :confirmation_token, type: String
23
+ field :confirmed_at, type: Time
24
+ field :confirmation_sent_at, type: Time
25
+ field :unconfirmed_email, type: String # Only if using reconfirmable
26
+
27
+ ## Lockable
28
+ field :locked_at, type: Time
29
+
30
+ field :active, type: Boolean, default: false
31
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shared_user_with_password_verification'
4
+
5
+ class OneUser
6
+ include Mongoid::Document
7
+ include Shim
8
+ include SharedUserWithPasswordVerification
9
+ include SharedSecurityQuestionsFields
10
+
11
+ field :password_changed_at, type: Time
12
+ index({ password_changed_at: 1 }, {})
13
+
14
+ #field :paranoid_verification_code, type: String
15
+ #field :paranoid_verified_at, type: Time
16
+ #field :paranoid_verification_attempt, type: Integer, default: 0
17
+
18
+ field :username, type: String
19
+ field :facebook_token, type: String
20
+
21
+ ## Database authenticatable
22
+ field :email, type: String, default: ""
23
+ field :encrypted_password, type: String, default: ""
24
+
25
+ ## Recoverable
26
+ field :reset_password_token, type: String
27
+ field :reset_password_sent_at, type: Time
28
+
29
+ ## Rememberable
30
+ field :remember_created_at, type: Time
31
+
32
+ ## Trackable
33
+ field :sign_in_count, type: Integer, default: 0
34
+ field :current_sign_in_at, type: Time
35
+ field :last_sign_in_at, type: Time
36
+ field :current_sign_in_ip, type: String
37
+ field :last_sign_in_ip, type: String
38
+
39
+ ## Confirmable
40
+ field :confirmation_token, type: String
41
+ field :confirmed_at, type: Time
42
+ field :confirmation_sent_at, type: Time
43
+ # field :unconfirmed_email, type: String # Only if using reconfirmable
44
+
45
+ ## Lockable
46
+ field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
47
+ field :unlock_token, type: String # Only if unlock strategy is :email or :both
48
+ field :locked_at, type: Time
49
+
50
+ cattr_accessor :validations_performed
51
+
52
+ after_validation :after_validation_callback
53
+
54
+ def after_validation_callback
55
+ # used to check in our test if the validations were called
56
+ @@validations_performed = true
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shim
4
+ extend ::ActiveSupport::Concern
5
+
6
+ included do
7
+ include ::Mongoid::Timestamps
8
+ field :created_at, type: DateTime
9
+ end
10
+
11
+ class_methods do
12
+ def order(attribute)
13
+ asc(attribute)
14
+ end
15
+
16
+ def find_by_email(email)
17
+ find_by(email: email)
18
+ end
19
+ end
20
+
21
+ # overwrite equality (because some devise tests use this for asserting model equality)
22
+ def ==(other)
23
+ other.is_a?(self.class) && _id == other._id
24
+ end
25
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shared_user_without_omniauth'
4
+
5
+ class UserOnEngine
6
+ include Mongoid::Document
7
+ include Shim
8
+ include SharedUserWithoutOmniauth
9
+
10
+ field :username, type: String
11
+ field :facebook_token, type: String
12
+
13
+ ## Database authenticatable
14
+ field :email, type: String, default: ""
15
+ field :encrypted_password, type: String, default: ""
16
+
17
+ ## Recoverable
18
+ field :reset_password_token, type: String
19
+ field :reset_password_sent_at, type: Time
20
+
21
+ ## Rememberable
22
+ field :remember_created_at, type: Time
23
+
24
+ ## Trackable
25
+ field :sign_in_count, type: Integer, default: 0
26
+ field :current_sign_in_at, type: Time
27
+ field :last_sign_in_at, type: Time
28
+ field :current_sign_in_ip, type: String
29
+ field :last_sign_in_ip, type: String
30
+
31
+ ## Confirmable
32
+ field :confirmation_token, type: String
33
+ field :confirmed_at, type: Time
34
+ field :confirmation_sent_at, type: Time
35
+ # field :unconfirmed_email, type: String # Only if using reconfirmable
36
+
37
+ ## Lockable
38
+ field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
39
+ field :unlock_token, type: String # Only if unlock strategy is :email or :both
40
+ field :locked_at, type: Time
41
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shared_user_without_omniauth'
4
+
5
+ class UserOnMainApp
6
+ include Mongoid::Document
7
+ include Shim
8
+ include SharedUserWithoutOmniauth
9
+
10
+ field :username, type: String
11
+ field :facebook_token, type: String
12
+
13
+ ## Database authenticatable
14
+ field :email, type: String, default: ""
15
+ field :encrypted_password, type: String, default: ""
16
+
17
+ ## Recoverable
18
+ field :reset_password_token, type: String
19
+ field :reset_password_sent_at, type: Time
20
+
21
+ ## Rememberable
22
+ field :remember_created_at, type: Time
23
+
24
+ ## Trackable
25
+ field :sign_in_count, type: Integer, default: 0
26
+ field :current_sign_in_at, type: Time
27
+ field :last_sign_in_at, type: Time
28
+ field :current_sign_in_ip, type: String
29
+ field :last_sign_in_ip, type: String
30
+
31
+ ## Confirmable
32
+ field :confirmation_token, type: String
33
+ field :confirmed_at, type: Time
34
+ field :confirmation_sent_at, type: Time
35
+ # field :unconfirmed_email, type: String # Only if using reconfirmable
36
+
37
+ ## Lockable
38
+ field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
39
+ field :unlock_token, type: String # Only if unlock strategy is :email or :both
40
+ field :locked_at, type: Time
41
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shared_user"
4
+
5
+ class UserWithValidations
6
+ include Mongoid::Document
7
+ include Shim
8
+ include SharedUser
9
+
10
+ field :username, type: String
11
+ field :facebook_token, type: String
12
+
13
+ ## Database authenticatable
14
+ field :email, type: String, default: ""
15
+ field :encrypted_password, type: String, default: ""
16
+
17
+ ## Recoverable
18
+ field :reset_password_token, type: String
19
+ field :reset_password_sent_at, type: Time
20
+
21
+ ## Rememberable
22
+ field :remember_created_at, type: Time
23
+
24
+ ## Trackable
25
+ field :sign_in_count, type: Integer, default: 0
26
+ field :current_sign_in_at, type: Time
27
+ field :last_sign_in_at, type: Time
28
+ field :current_sign_in_ip, type: String
29
+ field :last_sign_in_ip, type: String
30
+
31
+ ## Lockable
32
+ field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
33
+ field :unlock_token, type: String # Only if unlock strategy is :email or :both
34
+ field :locked_at, type: Time
35
+
36
+ validates :email, presence: true
37
+ end