devise-security 0.16.0 → 0.18.0

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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +3 -1
  3. data/README.md +18 -7
  4. data/app/controllers/devise/paranoid_verification_code_controller.rb +26 -12
  5. data/app/controllers/devise/password_expired_controller.rb +22 -5
  6. data/config/locales/bg.yml +42 -0
  7. data/config/locales/by.yml +1 -0
  8. data/config/locales/cs.yml +5 -0
  9. data/config/locales/de.yml +3 -0
  10. data/config/locales/en.yml +2 -1
  11. data/config/locales/es.yml +12 -0
  12. data/config/locales/fa.yml +1 -0
  13. data/config/locales/fr.yml +14 -2
  14. data/config/locales/hi.yml +1 -0
  15. data/config/locales/it.yml +1 -0
  16. data/config/locales/ja.yml +12 -0
  17. data/config/locales/nl.yml +1 -0
  18. data/config/locales/pt.yml +1 -0
  19. data/config/locales/ru.yml +1 -0
  20. data/config/locales/tr.yml +25 -1
  21. data/config/locales/uk.yml +1 -0
  22. data/config/locales/zh_CN.yml +1 -0
  23. data/config/locales/zh_TW.yml +1 -0
  24. data/lib/devise-security/controllers/helpers.rb +23 -11
  25. data/lib/devise-security/hooks/expirable.rb +3 -3
  26. data/lib/devise-security/hooks/paranoid_verification.rb +1 -3
  27. data/lib/devise-security/hooks/password_expirable.rb +1 -3
  28. data/lib/devise-security/hooks/session_limitable.rb +4 -4
  29. data/lib/devise-security/models/compatibility/active_record_patch.rb +4 -3
  30. data/lib/devise-security/models/compatibility/mongoid_patch.rb +3 -2
  31. data/lib/devise-security/models/database_authenticatable_patch.rb +18 -10
  32. data/lib/devise-security/models/expirable.rb +6 -5
  33. data/lib/devise-security/models/paranoid_verification.rb +2 -2
  34. data/lib/devise-security/models/password_archivable.rb +3 -3
  35. data/lib/devise-security/models/secure_validatable.rb +57 -20
  36. data/lib/devise-security/orm/mongoid.rb +1 -1
  37. data/lib/devise-security/patches.rb +14 -8
  38. data/lib/devise-security/routes.rb +2 -3
  39. data/lib/devise-security/validators/password_complexity_validator.rb +53 -26
  40. data/lib/devise-security/version.rb +1 -1
  41. data/lib/devise-security.rb +9 -3
  42. data/lib/generators/devise_security/install_generator.rb +3 -5
  43. data/lib/generators/templates/devise_security.rb +6 -1
  44. data/test/controllers/test_paranoid_verification_code_controller.rb +133 -0
  45. data/test/controllers/test_password_expired_controller.rb +87 -33
  46. data/test/controllers/test_security_question_controller.rb +25 -19
  47. data/test/dummy/app/controllers/overrides/paranoid_verification_code_controller.rb +7 -0
  48. data/test/dummy/app/controllers/overrides/password_expired_controller.rb +17 -0
  49. data/test/dummy/app/controllers/widgets_controller.rb +3 -0
  50. data/test/dummy/app/models/application_user_record.rb +2 -1
  51. data/test/dummy/app/models/mongoid/confirmable_fields.rb +2 -0
  52. data/test/dummy/app/models/mongoid/database_authenticable_fields.rb +4 -3
  53. data/test/dummy/app/models/mongoid/expirable_fields.rb +2 -0
  54. data/test/dummy/app/models/mongoid/lockable_fields.rb +2 -0
  55. data/test/dummy/app/models/mongoid/mappings.rb +4 -2
  56. data/test/dummy/app/models/mongoid/omniauthable_fields.rb +2 -0
  57. data/test/dummy/app/models/mongoid/paranoid_verification_fields.rb +2 -0
  58. data/test/dummy/app/models/mongoid/password_archivable_fields.rb +2 -0
  59. data/test/dummy/app/models/mongoid/password_expirable_fields.rb +2 -0
  60. data/test/dummy/app/models/mongoid/recoverable_fields.rb +2 -0
  61. data/test/dummy/app/models/mongoid/registerable_fields.rb +4 -2
  62. data/test/dummy/app/models/mongoid/rememberable_fields.rb +2 -0
  63. data/test/dummy/app/models/mongoid/secure_validatable_fields.rb +2 -0
  64. data/test/dummy/app/models/mongoid/security_questionable_fields.rb +2 -0
  65. data/test/dummy/app/models/mongoid/session_limitable_fields.rb +2 -0
  66. data/test/dummy/app/models/mongoid/timeoutable_fields.rb +2 -0
  67. data/test/dummy/app/models/mongoid/trackable_fields.rb +2 -0
  68. data/test/dummy/app/models/mongoid/validatable_fields.rb +2 -0
  69. data/test/dummy/app/models/paranoid_verification_user.rb +26 -0
  70. data/test/dummy/app/models/password_expired_user.rb +26 -0
  71. data/test/dummy/app/models/user.rb +5 -5
  72. data/test/dummy/app/models/widget.rb +1 -3
  73. data/test/dummy/app/mongoid/one_user.rb +5 -5
  74. data/test/dummy/app/mongoid/user_on_engine.rb +2 -2
  75. data/test/dummy/app/mongoid/user_on_main_app.rb +2 -2
  76. data/test/dummy/app/mongoid/user_with_validations.rb +3 -3
  77. data/test/dummy/app/mongoid/user_without_email.rb +7 -4
  78. data/test/dummy/config/application.rb +3 -7
  79. data/test/dummy/config/boot.rb +1 -1
  80. data/test/dummy/config/environment.rb +1 -1
  81. data/test/dummy/config/environments/test.rb +1 -0
  82. data/test/dummy/config/initializers/devise.rb +1 -5
  83. data/test/dummy/config/locales/en.yml +10 -0
  84. data/test/dummy/config/routes.rb +3 -1
  85. data/test/dummy/config.ru +1 -1
  86. data/test/dummy/db/migrate/20120508165529_create_tables.rb +5 -5
  87. data/test/dummy/lib/shared_expirable_columns.rb +1 -0
  88. data/test/dummy/lib/shared_security_questions_fields.rb +1 -0
  89. data/test/dummy/lib/shared_user.rb +17 -6
  90. data/test/dummy/lib/shared_user_without_omniauth.rb +12 -3
  91. data/test/dummy/lib/shared_verification_fields.rb +1 -0
  92. data/test/dummy/log/test.log +39637 -16086
  93. data/test/i18n_test.rb +22 -0
  94. data/test/integration/test_paranoid_verification_code_workflow.rb +53 -0
  95. data/test/integration/test_password_expirable_workflow.rb +2 -2
  96. data/test/integration/test_session_limitable_workflow.rb +5 -3
  97. data/test/orm/active_record.rb +7 -7
  98. data/test/support/integration_helpers.rb +18 -12
  99. data/test/test_compatibility.rb +2 -0
  100. data/test/test_complexity_validator.rb +247 -37
  101. data/test/test_database_authenticatable_patch.rb +146 -0
  102. data/test/test_helper.rb +7 -8
  103. data/test/test_install_generator.rb +1 -1
  104. data/test/test_paranoid_verification.rb +8 -9
  105. data/test/test_password_archivable.rb +34 -11
  106. data/test/test_password_expirable.rb +27 -27
  107. data/test/test_secure_validatable.rb +265 -107
  108. data/test/test_secure_validatable_overrides.rb +185 -0
  109. data/test/test_session_limitable.rb +9 -9
  110. data/test/tmp/config/initializers/{devise-security.rb → devise_security.rb} +6 -1
  111. data/test/tmp/config/locales/devise.security_extension.by.yml +1 -0
  112. data/test/tmp/config/locales/devise.security_extension.cs.yml +5 -0
  113. data/test/tmp/config/locales/devise.security_extension.de.yml +3 -0
  114. data/test/tmp/config/locales/devise.security_extension.en.yml +2 -1
  115. data/test/tmp/config/locales/devise.security_extension.es.yml +12 -0
  116. data/test/tmp/config/locales/devise.security_extension.fa.yml +1 -0
  117. data/test/tmp/config/locales/devise.security_extension.fr.yml +14 -2
  118. data/test/tmp/config/locales/devise.security_extension.hi.yml +21 -20
  119. data/test/tmp/config/locales/devise.security_extension.it.yml +1 -0
  120. data/test/tmp/config/locales/devise.security_extension.ja.yml +12 -0
  121. data/test/tmp/config/locales/devise.security_extension.nl.yml +1 -0
  122. data/test/tmp/config/locales/devise.security_extension.pt.yml +1 -0
  123. data/test/tmp/config/locales/devise.security_extension.ru.yml +1 -0
  124. data/test/tmp/config/locales/devise.security_extension.tr.yml +25 -1
  125. data/test/tmp/config/locales/devise.security_extension.uk.yml +1 -0
  126. data/test/tmp/config/locales/devise.security_extension.zh_CN.yml +1 -0
  127. data/test/tmp/config/locales/devise.security_extension.zh_TW.yml +1 -0
  128. metadata +82 -41
  129. data/lib/devise-security/patches/confirmations_controller_captcha.rb +0 -23
  130. data/lib/devise-security/patches/confirmations_controller_security_question.rb +0 -26
  131. data/lib/devise-security/patches/passwords_controller_captcha.rb +0 -22
  132. data/lib/devise-security/patches/passwords_controller_security_question.rb +0 -25
  133. data/lib/devise-security/patches/registrations_controller_captcha.rb +0 -35
  134. data/lib/devise-security/patches/sessions_controller_captcha.rb +0 -26
  135. data/lib/devise-security/patches/unlocks_controller_captcha.rb +0 -22
  136. data/lib/devise-security/patches/unlocks_controller_security_question.rb +0 -25
  137. data/test/dummy/app/controllers/foos_controller.rb +0 -0
  138. data/test/dummy/app/models/secure_user.rb +0 -9
  139. data/test/dummy/lib/shared_user_without_email.rb +0 -28
  140. data/test/dummy/log/development.log +0 -883
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module ConfirmationsControllerCaptcha
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do
8
- if valid_captcha_if_defined?(params[:captcha])
9
- self.resource = resource_class.send_confirmation_instructions(params[resource_name])
10
-
11
- if successfully_sent?(resource)
12
- respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
13
- else
14
- respond_with(resource)
15
- end
16
- else
17
- flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
18
- respond_with({}, location: new_confirmation_path(resource_name))
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module ConfirmationsControllerSecurityQuestion
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do
8
- # only find via email, not login
9
- resource = resource_class.find_or_initialize_with_error_by(:email, params[resource_name][:email], :not_found)
10
-
11
- if valid_captcha_or_security_question?(resource, params)
12
- self.resource = resource_class.send_confirmation_instructions(params[resource_name])
13
-
14
- if successfully_sent?(resource)
15
- respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
16
- else
17
- respond_with(resource)
18
- end
19
- else
20
- flash[:alert] = t('devise.invalid_security_question') if is_navigational_format?
21
- respond_with({}, location: new_confirmation_path(resource_name))
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module PasswordsControllerCaptcha
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do
8
- if valid_captcha_if_defined?(params[:captcha])
9
- self.resource = resource_class.send_reset_password_instructions(params[resource_name])
10
- if successfully_sent?(resource)
11
- respond_with({}, location: new_session_path(resource_name))
12
- else
13
- respond_with(resource)
14
- end
15
- else
16
- flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
17
- respond_with({}, location: new_password_path(resource_name))
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module PasswordsControllerSecurityQuestion
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do
8
- # only find via email, not login
9
- resource = resource_class.find_or_initialize_with_error_by(:email, params[resource_name][:email], :not_found)
10
-
11
- if valid_captcha_or_security_question?(resource, params)
12
- self.resource = resource_class.send_reset_password_instructions(params[resource_name])
13
- if successfully_sent?(resource)
14
- respond_with({}, location: new_session_path(resource_name))
15
- else
16
- respond_with(resource)
17
- end
18
- else
19
- flash[:alert] = t('devise.invalid_security_question') if is_navigational_format?
20
- respond_with({}, location: new_password_path(resource_name))
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module RegistrationsControllerCaptcha
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do |&block|
8
- build_resource(sign_up_params)
9
-
10
- if valid_captcha_if_defined?(params[:captcha])
11
- if resource.save
12
- block.call(resource) if block
13
- if resource.active_for_authentication?
14
- set_flash_message :notice, :signed_up if is_flashing_format?
15
- sign_up(resource_name, resource)
16
- respond_with resource, location: after_sign_up_path_for(resource)
17
- else
18
- set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
19
- expire_data_after_sign_in!
20
- respond_with resource, location: after_inactive_sign_up_path_for(resource)
21
- end
22
- else
23
- clean_up_passwords resource
24
- respond_with resource
25
- end
26
-
27
- else
28
- resource.errors.add :base, t('devise.invalid_captcha')
29
- clean_up_passwords resource
30
- respond_with resource
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module SessionsControllerCaptcha
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do |&block|
8
- if valid_captcha_if_defined?(params[:captcha])
9
- self.resource = warden.authenticate!(auth_options)
10
- set_flash_message(:notice, :signed_in) if is_flashing_format?
11
- sign_in(resource_name, resource)
12
- block.call(resource) if block
13
- respond_with resource, location: after_sign_in_path_for(resource)
14
- else
15
- flash[:alert] = t('devise.invalid_captcha') if is_flashing_format?
16
- respond_with({}, location: new_session_path(resource_name))
17
- end
18
- end
19
-
20
- # for bad protected use in controller
21
- define_method :auth_options do
22
- { scope: resource_name, recall: "#{controller_path}#new" }
23
- end
24
- end
25
- end
26
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module UnlocksControllerCaptcha
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do
8
- if valid_captcha_if_defined?(params[:captcha])
9
- self.resource = resource_class.send_unlock_instructions(params[resource_name])
10
- if successfully_sent?(resource)
11
- respond_with({}, location: new_session_path(resource_name))
12
- else
13
- respond_with(resource)
14
- end
15
- else
16
- flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
17
- respond_with({}, location: new_unlock_path(resource_name))
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DeviseSecurity::Patches
4
- module UnlocksControllerSecurityQuestion
5
- extend ActiveSupport::Concern
6
- included do
7
- define_method :create do
8
- # only find via email, not login
9
- resource = resource_class.find_or_initialize_with_error_by(:email, params[resource_name][:email], :not_found)
10
-
11
- if valid_captcha_or_security_question?(resource, params)
12
- self.resource = resource_class.send_unlock_instructions(params[resource_name])
13
- if successfully_sent?(resource)
14
- respond_with({}, location: new_session_path(resource_name))
15
- else
16
- respond_with(resource)
17
- end
18
- else
19
- flash[:alert] = t('devise.invalid_security_question') if is_navigational_format?
20
- respond_with({}, location: new_unlock_path(resource_name))
21
- end
22
- end
23
- end
24
- end
25
- end
File without changes
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SecureUser < ApplicationUserRecord
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
9
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SharedUserWithoutEmail
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- # NOTE: This is missing :validatable and :confirmable, as they both require
8
- # an email field at the moment. It is also missing :omniauthable because that
9
- # adds unnecessary complexity to the setup
10
- devise :database_authenticatable, :lockable, :recoverable,
11
- :registerable, :rememberable, :timeoutable,
12
- :trackable
13
- end
14
-
15
- # This test stub is a bit rubbish because it's tied very closely to the
16
- # implementation where we care about this one case. However, completely
17
- # removing the email field breaks "recoverable" tests completely, so we are
18
- # just taking the approach here that "email" is something that is a not an
19
- # ActiveRecord field.
20
- def email_changed?
21
- raise NoMethodError
22
- end
23
-
24
- def respond_to?(method_name, include_all=false)
25
- return false if method_name.to_sym == :email_changed?
26
- super(method_name, include_all)
27
- end
28
- end