devise-security 0.14.1 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +3 -1
  3. data/README.md +136 -61
  4. data/app/controllers/devise/paranoid_verification_code_controller.rb +26 -12
  5. data/app/controllers/devise/password_expired_controller.rb +32 -10
  6. data/app/views/devise/paranoid_verification_code/show.html.erb +3 -3
  7. data/app/views/devise/password_expired/show.html.erb +5 -5
  8. data/config/locales/bg.yml +42 -0
  9. data/config/locales/by.yml +50 -0
  10. data/config/locales/cs.yml +46 -0
  11. data/config/locales/de.yml +16 -2
  12. data/config/locales/en.yml +15 -2
  13. data/config/locales/es.yml +22 -9
  14. data/config/locales/fa.yml +42 -0
  15. data/config/locales/fr.yml +15 -2
  16. data/config/locales/hi.yml +43 -0
  17. data/config/locales/it.yml +36 -4
  18. data/config/locales/ja.yml +14 -1
  19. data/config/locales/nl.yml +42 -0
  20. data/config/locales/pt.yml +42 -0
  21. data/config/locales/ru.yml +50 -0
  22. data/config/locales/tr.yml +26 -1
  23. data/config/locales/uk.yml +50 -0
  24. data/config/locales/zh_CN.yml +42 -0
  25. data/config/locales/zh_TW.yml +42 -0
  26. data/lib/devise-security/controllers/helpers.rb +72 -51
  27. data/lib/devise-security/hooks/expirable.rb +3 -3
  28. data/lib/devise-security/hooks/paranoid_verification.rb +1 -3
  29. data/lib/devise-security/hooks/password_expirable.rb +3 -3
  30. data/lib/devise-security/hooks/session_limitable.rb +29 -14
  31. data/lib/devise-security/models/compatibility/{active_record.rb → active_record_patch.rb} +14 -2
  32. data/lib/devise-security/models/compatibility/{mongoid.rb → mongoid_patch.rb} +12 -1
  33. data/lib/devise-security/models/compatibility.rb +2 -2
  34. data/lib/devise-security/models/database_authenticatable_patch.rb +18 -10
  35. data/lib/devise-security/models/expirable.rb +6 -5
  36. data/lib/devise-security/models/paranoid_verification.rb +2 -2
  37. data/lib/devise-security/models/password_archivable.rb +3 -3
  38. data/lib/devise-security/models/password_expirable.rb +5 -1
  39. data/lib/devise-security/models/secure_validatable.rb +62 -11
  40. data/lib/devise-security/models/session_limitable.rb +17 -2
  41. data/lib/devise-security/orm/mongoid.rb +1 -1
  42. data/lib/devise-security/patches.rb +14 -8
  43. data/lib/devise-security/routes.rb +2 -3
  44. data/lib/devise-security/validators/password_complexity_validator.rb +53 -24
  45. data/lib/devise-security/version.rb +1 -1
  46. data/lib/devise-security.rb +15 -6
  47. data/lib/generators/devise_security/install_generator.rb +4 -6
  48. data/lib/generators/templates/{devise-security.rb → devise_security.rb} +9 -1
  49. data/test/controllers/test_paranoid_verification_code_controller.rb +133 -0
  50. data/test/controllers/test_password_expired_controller.rb +164 -0
  51. data/test/{test_security_question_controller.rb → controllers/test_security_question_controller.rb} +19 -37
  52. data/test/dummy/app/assets/config/manifest.js +3 -0
  53. data/test/dummy/app/controllers/overrides/paranoid_verification_code_controller.rb +7 -0
  54. data/test/dummy/app/controllers/overrides/password_expired_controller.rb +17 -0
  55. data/test/dummy/app/controllers/widgets_controller.rb +9 -0
  56. data/test/dummy/app/models/application_user_record.rb +2 -1
  57. data/test/dummy/app/models/mongoid/confirmable_fields.rb +2 -0
  58. data/test/dummy/app/models/mongoid/database_authenticable_fields.rb +4 -3
  59. data/test/dummy/app/models/mongoid/expirable_fields.rb +2 -0
  60. data/test/dummy/app/models/mongoid/lockable_fields.rb +2 -0
  61. data/test/dummy/app/models/mongoid/mappings.rb +4 -2
  62. data/test/dummy/app/models/mongoid/omniauthable_fields.rb +2 -0
  63. data/test/dummy/app/models/mongoid/paranoid_verification_fields.rb +2 -0
  64. data/test/dummy/app/models/mongoid/password_archivable_fields.rb +2 -0
  65. data/test/dummy/app/models/mongoid/password_expirable_fields.rb +2 -0
  66. data/test/dummy/app/models/mongoid/recoverable_fields.rb +2 -0
  67. data/test/dummy/app/models/mongoid/registerable_fields.rb +4 -2
  68. data/test/dummy/app/models/mongoid/rememberable_fields.rb +2 -0
  69. data/test/dummy/app/models/mongoid/secure_validatable_fields.rb +2 -0
  70. data/test/dummy/app/models/mongoid/security_questionable_fields.rb +2 -0
  71. data/test/dummy/app/models/mongoid/session_limitable_fields.rb +2 -0
  72. data/test/dummy/app/models/mongoid/timeoutable_fields.rb +2 -0
  73. data/test/dummy/app/models/mongoid/trackable_fields.rb +2 -0
  74. data/test/dummy/app/models/mongoid/validatable_fields.rb +2 -0
  75. data/test/dummy/app/models/paranoid_verification_user.rb +26 -0
  76. data/test/dummy/app/models/password_expired_user.rb +26 -0
  77. data/test/dummy/app/models/user.rb +10 -2
  78. data/test/dummy/app/models/widget.rb +1 -3
  79. data/test/dummy/app/mongoid/one_user.rb +5 -5
  80. data/test/dummy/app/mongoid/user_on_engine.rb +2 -2
  81. data/test/dummy/app/mongoid/user_on_main_app.rb +2 -2
  82. data/test/dummy/app/mongoid/user_with_validations.rb +3 -3
  83. data/test/dummy/app/mongoid/user_without_email.rb +7 -4
  84. data/test/dummy/config/application.rb +3 -7
  85. data/test/dummy/config/boot.rb +1 -1
  86. data/test/dummy/config/environment.rb +1 -1
  87. data/test/dummy/config/environments/test.rb +4 -13
  88. data/test/dummy/config/initializers/devise.rb +1 -5
  89. data/test/dummy/config/initializers/migration_class.rb +1 -8
  90. data/test/dummy/config/locales/en.yml +10 -0
  91. data/test/dummy/config/mongoid.yml +1 -1
  92. data/test/dummy/config/routes.rb +6 -3
  93. data/test/dummy/config.ru +1 -1
  94. data/test/dummy/db/migrate/20120508165529_create_tables.rb +15 -6
  95. data/test/dummy/lib/shared_expirable_columns.rb +1 -0
  96. data/test/dummy/lib/shared_security_questions_fields.rb +1 -0
  97. data/test/dummy/lib/shared_user.rb +17 -6
  98. data/test/dummy/lib/shared_user_without_omniauth.rb +12 -3
  99. data/test/dummy/lib/shared_verification_fields.rb +1 -0
  100. data/test/dummy/log/test.log +45240 -0
  101. data/test/i18n_test.rb +22 -0
  102. data/test/integration/test_paranoid_verification_code_workflow.rb +53 -0
  103. data/test/integration/test_password_expirable_workflow.rb +53 -0
  104. data/test/integration/test_session_limitable_workflow.rb +69 -0
  105. data/test/orm/active_record.rb +7 -4
  106. data/test/orm/mongoid.rb +2 -1
  107. data/test/support/integration_helpers.rb +35 -0
  108. data/test/support/mongoid.yml +1 -1
  109. data/test/test_compatibility.rb +15 -0
  110. data/test/test_complexity_validator.rb +251 -29
  111. data/test/test_database_authenticatable_patch.rb +146 -0
  112. data/test/test_helper.rb +23 -8
  113. data/test/test_install_generator.rb +12 -2
  114. data/test/test_paranoid_verification.rb +8 -9
  115. data/test/test_password_archivable.rb +34 -11
  116. data/test/test_password_expirable.rb +27 -27
  117. data/test/test_secure_validatable.rb +284 -50
  118. data/test/test_secure_validatable_overrides.rb +185 -0
  119. data/test/test_session_limitable.rb +57 -0
  120. data/test/tmp/config/initializers/devise_security.rb +52 -0
  121. data/test/tmp/config/locales/devise.security_extension.by.yml +50 -0
  122. data/test/tmp/config/locales/devise.security_extension.cs.yml +46 -0
  123. data/test/tmp/config/locales/devise.security_extension.de.yml +42 -0
  124. data/test/tmp/config/locales/devise.security_extension.en.yml +42 -0
  125. data/test/tmp/config/locales/devise.security_extension.es.yml +42 -0
  126. data/test/tmp/config/locales/devise.security_extension.fa.yml +42 -0
  127. data/test/tmp/config/locales/devise.security_extension.fr.yml +42 -0
  128. data/test/tmp/config/locales/devise.security_extension.hi.yml +43 -0
  129. data/test/tmp/config/locales/devise.security_extension.it.yml +42 -0
  130. data/test/tmp/config/locales/devise.security_extension.ja.yml +42 -0
  131. data/test/tmp/config/locales/devise.security_extension.nl.yml +42 -0
  132. data/test/tmp/config/locales/devise.security_extension.pt.yml +42 -0
  133. data/test/tmp/config/locales/devise.security_extension.ru.yml +50 -0
  134. data/test/tmp/config/locales/devise.security_extension.tr.yml +42 -0
  135. data/test/tmp/config/locales/devise.security_extension.uk.yml +50 -0
  136. data/test/tmp/config/locales/devise.security_extension.zh_CN.yml +42 -0
  137. data/test/tmp/config/locales/devise.security_extension.zh_TW.yml +42 -0
  138. metadata +202 -138
  139. data/.codeclimate.yml +0 -63
  140. data/.document +0 -5
  141. data/.gitignore +0 -43
  142. data/.mdlrc +0 -1
  143. data/.rubocop.yml +0 -64
  144. data/.ruby-version +0 -1
  145. data/.travis.yml +0 -39
  146. data/Appraisals +0 -35
  147. data/Gemfile +0 -10
  148. data/Rakefile +0 -27
  149. data/devise-security.gemspec +0 -50
  150. data/gemfiles/rails_4.2_stable.gemfile +0 -16
  151. data/gemfiles/rails_5.0_stable.gemfile +0 -15
  152. data/gemfiles/rails_5.1_stable.gemfile +0 -15
  153. data/gemfiles/rails_5.2_stable.gemfile +0 -15
  154. data/gemfiles/rails_6.0_beta.gemfile +0 -15
  155. data/lib/devise-security/orm/active_record.rb +0 -20
  156. data/lib/devise-security/patches/confirmations_controller_captcha.rb +0 -23
  157. data/lib/devise-security/patches/confirmations_controller_security_question.rb +0 -26
  158. data/lib/devise-security/patches/passwords_controller_captcha.rb +0 -22
  159. data/lib/devise-security/patches/passwords_controller_security_question.rb +0 -25
  160. data/lib/devise-security/patches/registrations_controller_captcha.rb +0 -35
  161. data/lib/devise-security/patches/sessions_controller_captcha.rb +0 -26
  162. data/lib/devise-security/patches/unlocks_controller_captcha.rb +0 -22
  163. data/lib/devise-security/patches/unlocks_controller_security_question.rb +0 -25
  164. data/lib/devise-security/schema.rb +0 -66
  165. data/test/dummy/app/controllers/foos_controller.rb +0 -0
  166. data/test/dummy/app/models/.gitkeep +0 -0
  167. data/test/dummy/app/models/secure_user.rb +0 -9
  168. data/test/dummy/lib/shared_user_without_email.rb +0 -28
  169. data/test/test_password_expired_controller.rb +0 -46
  170. /data/test/{test_captcha_controller.rb → controllers/test_captcha_controller.rb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc16bc5c313bb9834b1ab7aedb0e84ff51b9e2f9a2574cea1191bd9c9ac59f81
4
- data.tar.gz: 0b2129cc1557cf83338be9cf88792bdb60dca838c06b9903ec8b189289389572
3
+ metadata.gz: 30c17693a3331769b786cf6925dcce0b62087a894960309ad316189613b62291
4
+ data.tar.gz: defa2b29a2d67e7615062ab6bea7518b37b6f24ed4735016a4fca4ef860ffbd0
5
5
  SHA512:
6
- metadata.gz: fe84191b2373f752b0de75b0d6072dfffe52ca2f76a332dde63db79e39d1ae9e80c7878f011e586080e8b9a7b8fbd488c0f02a3a47a2924a322ab188c9cbb17f
7
- data.tar.gz: 2eece1cf95ebbbca4f1f0a6f03e780d5f24b2e8ba1134fe381d6cd2966e43aee7ef1d6f0d1bdedeb683bd634af7544143fb60e7b2b2c53585719dcfd390b76e6
6
+ metadata.gz: 54fa56d5e200c73e329d1f07eb1845ce2be695ffb4afa20f475d624fb6615f1583a161c8eec8fa5f84643b957a0d9e4d4d653d5f5071f7b73784bf843a520a70
7
+ data.tar.gz: 891fcf2b29571ee6fca9d667ddbc211cf27a5ba64e6048b33d3f63a6f395e02ef88d51a6c35da3bfe761b42c04bf1a57e118ae9bb46ebb22212eb85f9a0b3179
data/LICENSE.txt CHANGED
@@ -1,4 +1,6 @@
1
- Copyright (c) 2011 Marco Scholl
1
+ Copyright (c) 2017-2022 Dillon Welch & Kevin Olbrich.
2
+
3
+ Copyright (c) 2011-2017 Marco Scholl
2
4
 
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,28 +1,45 @@
1
1
  # Devise Security
2
2
 
3
- [![Build Status](https://travis-ci.org/devise-security/devise-security.svg?branch=master)](https://travis-ci.org/devise-security/devise-security)[![Coverage Status](https://coveralls.io/repos/github/devise-security/devise-security/badge.svg?branch=master)](https://coveralls.io/github/devise-security/devise-security?branch=master)[![Maintainability](https://api.codeclimate.com/v1/badges/ace7cd003a0db8bffa5a/maintainability)](https://codeclimate.com/github/devise-security/devise-security/maintainability)
3
+ [![Build Status](https://github.com/devise-security/devise-security/actions/workflows/test_suite.yml/badge.svg?branch=master)](https://github.com/devise-security/devise-security/actions/workflows/test_suite.yml)
4
+ [![Coverage Status](https://coveralls.io/repos/github/devise-security/devise-security/badge.svg?branch=master)](https://coveralls.io/github/devise-security/devise-security?branch=master)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/ace7cd003a0db8bffa5a/maintainability)](https://codeclimate.com/github/devise-security/devise-security/maintainability)
4
6
 
5
- A [Devise](https://github.com/plataformatec/devise) extension to add additional security features required by modern web applications. Forked from [Devise Security Extension](https://github.com/phatworx/devise_security_extension)
7
+ A [Devise](https://github.com/heartcombo/devise) extension to add additional
8
+ security features required by modern web applications. Forked from
9
+ [Devise Security Extension](https://github.com/phatworx/devise_security_extension)
6
10
 
7
11
  It is composed of 7 additional Devise modules:
8
12
 
9
- - `:password_expirable` - passwords will expire after a configured time (and will need to be changed by the user). You will most likely want to use `:password_expirable` together with the `:password_archivable` module to [prevent the current expired password being reused](https://github.com/phatworx/devise_security_extension/issues/175) immediately as the new password.
10
- - `:secure_validatable` - better way to validate a model (email, stronger password validation). Don't use with Devise `:validatable` module!
11
- - `:password_archivable` - save used passwords in an `old_passwords` table for history checks (don't be able to use a formerly used password)
12
- - `:session_limitable` - ensures, that there is only one session usable per account at once
13
- - `:expirable` - expires a user account after x days of inactivity (default 90 days)
14
- - `:security_questionable` - as accessible substitution for captchas (security question with captcha fallback)
15
- - `:paranoid_verification` - admin can generate verification code that user needs to fill in otherwise he wont be able to use the application.
13
+ - `:password_expirable` - passwords will expire after a configured time (and
14
+ will need to be changed by the user). You will most likely want to use
15
+ `:password_expirable` together with the `:password_archivable` module to
16
+ [prevent the current expired password from being reused](https://github.com/phatworx/devise_security_extension/issues/175)
17
+ immediately as the new password.
18
+ - `:secure_validatable` - better way to validate a model (email, stronger
19
+ password validation). Don't use with Devise `:validatable` module!
20
+ - `:password_archivable` - save used passwords in an `old_passwords` table for
21
+ history checks (prevent reusing passwords)
22
+ - `:session_limitable` - ensures, that there is only one session usable per
23
+ account at once
24
+ - `:expirable` - expires a user account after x days of inactivity (default 90
25
+ days)
26
+ - `:security_questionable` - as accessible substitution for captchas (security
27
+ question with captcha fallback)
28
+ - `:paranoid_verification` - admin can generate verification code that user
29
+ needs to fill in otherwise he won't be able to use the application.
16
30
 
17
31
  Configuration and database schema for each module below.
18
32
 
19
33
  ## Additional features
20
34
 
21
- - **captcha support** for `sign_up`, `sign_in`, `recover` and `unlock` (to make automated mass creation and brute forcing of accounts harder)
35
+ **captcha support** for `sign_up`, `sign_in`, `recover` and `unlock` (to make
36
+ automated mass creation and brute forcing of accounts harder)
22
37
 
23
38
  ## Getting started
24
39
 
25
- Devise Security works with Devise on Rails 4.2 onwards. You can add it to your Gemfile after you successfully set up Devise (see [Devise documentation](https://github.com/plataformatec/devise)) with:
40
+ Devise Security works with Devise on Rails >= 5.2. You can add it to your
41
+ Gemfile after you successfully set up Devise (see
42
+ [Devise documentation](https://github.com/heartcombo/devise)) with:
26
43
 
27
44
  ```ruby
28
45
  gem 'devise-security'
@@ -36,7 +53,10 @@ After you installed Devise Security you need to run the generator:
36
53
  rails generate devise_security:install
37
54
  ```
38
55
 
39
- The generator adds optional configurations to `config/initializers/devise-security.rb`. Enable the modules you wish to use in the initializer you are ready to add Devise Security modules on top of Devise modules to any of your Devise models:
56
+ The generator adds optional configurations to
57
+ `config/initializers/devise_security.rb`. Enable the modules you wish to use in
58
+ the initializer you are ready to add Devise Security modules on top of Devise
59
+ modules to any of your Devise models:
40
60
 
41
61
  ```ruby
42
62
  devise :password_expirable, :secure_validatable, :password_archivable, :session_limitable, :expirable
@@ -44,13 +64,16 @@ devise :password_expirable, :secure_validatable, :password_archivable, :session_
44
64
 
45
65
  ### E-mail Validation
46
66
 
47
- for `:secure_validatable` you need to have a way to validate an e-mail. There are multiple libraries that support this, and even a way built into Ruby!
67
+ For `:secure_validatable` you need to have a way to validate an e-mail. There
68
+ are multiple libraries that support this, and even a way built into Ruby!
48
69
 
49
- [Ruby Constant](http://yogodoshi.com/ruby-already-has-its-own-regular-expression-to-validate-emails/)
50
- * Note: This method would require a `email_validation` method to be defined in order to hook into the `validates` method defined here.
51
- [email_address](https://github.com/afair/email_address) gem
52
- [valid_email2](https://github.com/micke/valid_email2) gem
53
- [rails_email_validator](https://github.com/phatworx/rails_email_validator) gem (deprecated)
70
+ - (Recommended) Ruby built-in `URI::MailTo::EMAIL_REGEXP` constant
71
+ > Note: This method would require a `email_validation` method to be defined in
72
+ > order to hook into the `validates` method defined here.
73
+ - [email_address](https://github.com/afair/email_address) gem
74
+ - [valid_email2](https://github.com/micke/valid_email2) gem
75
+ - [rails_email_validator](https://github.com/phatworx/rails_email_validator) gem
76
+ (deprecated)
54
77
 
55
78
  ## Configuration
56
79
 
@@ -61,11 +84,13 @@ Devise.setup do |config|
61
84
 
62
85
  # Password expires after a configurable time (in seconds).
63
86
  # Or expire passwords on demand by setting this configuration to `true`
64
- # Use `user.need_password_change!` to expire a password.
87
+ # Use `user.need_change_password!` to expire a password.
65
88
  # Setting the configuration to `false` will completely disable expiration checks.
66
89
  # config.expire_password_after = 3.months | true | false
67
90
 
68
91
  # Need 1 char each of: A-Z, a-z, 0-9, and a punctuation mark or symbol
92
+ # You may use "digits" in place of "digit" and "symbols" in place of
93
+ # "symbol" based on your preference
69
94
  # config.password_complexity = { digit: 1, lower: 1, symbol: 1, upper: 1 }
70
95
 
71
96
  # Number of old passwords in archive
@@ -101,65 +126,79 @@ Devise.setup do |config|
101
126
  # ==> Configuration for :expirable
102
127
  # Time period for account expiry from last_activity_at
103
128
  # config.expire_after = 90.days
129
+
130
+ # Allow passwords to be equal to email (false, true)
131
+ # config.allow_passwords_equal_to_email = false
132
+
133
+ # paranoid_verification will regenerate verification code after failed attempt
134
+ # config.paranoid_code_regenerate_after_attempt = 10
104
135
  end
105
136
  ```
106
137
 
107
138
  ## Other ORMs
108
139
 
109
- Devise-security supports [Mongoid](https://rubygems.org/gems/mongoid) as an alternative ORM to active_record. To use this ORM, add this to your `Gemfile`.
140
+ Devise-security supports [Mongoid](https://rubygems.org/gems/mongoid) as an
141
+ alternative ORM to active_record. To use this ORM, add this to your `Gemfile`.
110
142
 
111
- gem 'mongoid'
143
+ ```ruby
144
+ gem 'mongoid'
145
+ ```
112
146
 
113
147
  And then ensure that the environment variable `DEVISE_ORM=mongoid` is set.
114
148
 
115
149
  For local development you will need to have MongoDB installed locally.
116
150
 
117
- brew install mongodb
151
+ ```bash
152
+ brew install mongodb
153
+ ```
118
154
 
119
155
  ### Rails App setup example with Mongoid
120
156
 
121
157
  ```ruby
122
158
  # inside config/application.rb
123
- require File.expand_path('../boot', __FILE__)
124
- #...
125
- DEVISE_ORM=:mongoid
159
+ require File.expand_path('../boot', __FILE__)
160
+ #...
161
+ DEVISE_ORM=:mongoid
126
162
 
127
163
  # Require the gems listed in Gemfile, including any gems
128
164
  # you've limited to :test, :development, or :production.
129
- Bundler.require(*Rails.groups)
165
+ Bundler.require(*Rails.groups)
130
166
 
131
- module MyApp
167
+ module MyApp
132
168
  class Application < Rails::Application
133
169
  #...
134
170
  end
135
- end
171
+ end
136
172
  ```
137
173
 
138
174
  ## Captcha-Support
139
175
 
140
- The captcha support depends on [EasyCaptcha](https://github.com/phatworx/easy_captcha). See further documentation there.
176
+ The captcha support depends on
177
+ [EasyCaptcha](https://github.com/phatworx/easy_captcha). See further
178
+ documentation there.
141
179
 
142
180
  ### Installation
143
181
 
144
182
  1. Add EasyCaptcha to your `Gemfile` with
145
183
 
146
- ```ruby
147
- gem 'easy_captcha'
148
- ```
184
+ ```ruby
185
+ gem 'easy_captcha'
186
+ ```
149
187
 
150
- 1. Run the initializer
188
+ 2. Run the initializer
151
189
 
152
- ```ruby
153
- rails generate easy_captcha:install
154
- ```
190
+ ```ruby
191
+ rails generate easy_captcha:install
192
+ ```
155
193
 
156
- 1. Enable captcha - see "Configuration" of Devise Security above.
157
- 1. Add the captcha in the generated devise views for each controller you have activated
194
+ 3. Enable captcha - see "Configuration" of Devise Security above.
195
+ 4. Add the captcha in the generated devise views for each controller you have
196
+ activated.
158
197
 
159
- ```erb
160
- <p><%= captcha_tag %></p>
161
- <p><%= text_field_tag :captcha %></p>
162
- ```
198
+ ```erb
199
+ <p><%= captcha_tag %></p>
200
+ <p><%= text_field_tag :captcha %></p>
201
+ ```
163
202
 
164
203
  ## Schema
165
204
 
@@ -174,7 +213,8 @@ end
174
213
  add_index :the_resources, :password_changed_at
175
214
  ```
176
215
 
177
- Note: setting `password_changed_at` to `nil` will require the user to change their password.
216
+ Note: setting `password_changed_at` to `nil` will require the user to change
217
+ their password.
178
218
 
179
219
  ### Password archivable
180
220
 
@@ -195,10 +235,24 @@ add_index :old_passwords, [:password_archivable_type, :password_archivable_id],
195
235
  create_table :the_resources do |t|
196
236
  # other devise fields
197
237
 
198
- t.string :unique_session_id, limit: 20
238
+ t.string :unique_session_id
199
239
  end
200
240
  ```
201
241
 
242
+ #### Bypassing session limitable
243
+
244
+ Sometimes it's useful to impersonate a user without authentication (e.g.
245
+ [administrator impersonating a user](https://github.com/heartcombo/devise/wiki/How-To:-Sign-in-as-another-user-if-you-are-an-admin)),
246
+ in this case the `session_limitable` strategy will log out the user, and if the
247
+ user logs in while the administrator is still logged in, the administrator will
248
+ be logged out.
249
+
250
+ For such cases the following can be used:
251
+
252
+ ```ruby
253
+ sign_in(User.find(params[:id]), scope: :user, skip_session_limitable: true)
254
+ ```
255
+
202
256
  ### Expirable
203
257
 
204
258
  ```ruby
@@ -271,13 +325,13 @@ end
271
325
 
272
326
  ## Requirements
273
327
 
274
- * Devise (<https://github.com/plataformatec/devise>)
275
- * Rails 4.2 onwards (<http://github.com/rails/rails>)
276
- * recommendations:
277
- - `autocomplete-off` (<http://github.com/phatworx/autocomplete-off>)
278
- - `easy_captcha` (<http://github.com/phatworx/easy_captcha>)
279
- - `mongodb` (<https://www.mongodb.com/>)
280
- - `rvm` (<https://rvm.io/>)
328
+ - Devise (<https://github.com/heartcombo/devise>)
329
+ - Rails 5.2 onwards (<http://github.com/rails/rails>)
330
+ - recommendations:
331
+ - `autocomplete-off` (<http://github.com/phatworx/autocomplete-off>)
332
+ - `easy_captcha` (<http://github.com/phatworx/easy_captcha>)
333
+ - `mongodb` (<https://www.mongodb.com/>)
334
+ - `rvm` (<https://rvm.io/>)
281
335
 
282
336
  ## Todo
283
337
 
@@ -295,7 +349,8 @@ end
295
349
  - 0.8 Support for Rails 4 (+ variety of patches)
296
350
  - 0.11 Support for Rails 5. Forked to allow project maintenance and features
297
351
 
298
- See also [Github Releases](https://github.com/devise-security/devise-security/releases)
352
+ See also
353
+ [Github Releases](https://github.com/devise-security/devise-security/releases)
299
354
 
300
355
  ## Maintainers
301
356
 
@@ -305,23 +360,43 @@ See also [Github Releases](https://github.com/devise-security/devise-security/re
305
360
 
306
361
  ## Contributing to devise-security
307
362
 
308
- - Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
309
- - Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
363
+ - Check out the latest master to make sure the feature hasn't been implemented
364
+ or the bug hasn't been fixed yet
365
+ - Check out the issue tracker to make sure someone already hasn't requested it
366
+ and/or contributed it
310
367
  - Fork the project
311
368
  - Start a feature/bugfix branch
312
369
  - Commit and push until you are happy with your contribution
313
- - Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
314
- - Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
370
+ - Make sure to add tests for it. This is important so I don't break it in a
371
+ future version unintentionally.
372
+ - Please try not to mess with the Rakefile, version, or history. If you want to
373
+ have your own version, or is otherwise necessary, that is fine, but please
374
+ isolate to its own commit so I can cherry-pick around it.
315
375
 
316
376
  ## Running tests
317
377
 
318
- Standard tests can be invoked using `rake`. To run the tests against the `mongoid` ORM, use `DEVISE_ORM=mongoid rake` while `mongodb` is running.
378
+ Standard tests can be invoked using `rake`. To run the tests against the
379
+ `mongoid` ORM, use `DEVISE_ORM=mongoid rake` while `mongodb` is running.
380
+
381
+ ## Maintenance Policy
319
382
 
320
- To locally simulate what travis-ci will run when you push code use:
383
+ We are committed to maintaining support for `devise-security` for all normal or
384
+ security maintenance versions of the Ruby language
385
+ [as listed here](https://www.ruby-lang.org/en/downloads/branches/), and for the
386
+ Ruby on Rails framework
387
+ [as per their maintenance policy](https://rubyonrails.org/maintenance/).
321
388
 
322
- $ gem install bundler -v '1.17.3'
323
- $ BUNDLER_VERSION=1.17.3 wwtd
389
+ To avoid introducing bugs caused by backwardly incompatible Ruby
390
+ language features, it is highly recommended that all development work be done
391
+ using the oldest supported Ruby version. The contents of the `.ruby-version`
392
+ file should reflect this.
324
393
 
325
394
  ## Copyright
326
395
 
327
- Copyright (c) 2011-2017 Marco Scholl. See LICENSE.txt for further details.
396
+ Copyright (c) 2017-2023 Dillon Welch & Kevin Olbrich.
397
+
398
+ Copyright (c) 2011-2017 Marco Scholl as the project [`devise_security_extension`](https://github.com/phatworx/devise_security_extension).
399
+
400
+ This repo was created as a fork from [b2ee978a](https://github.com/phatworx/devise_security_extension/commit/b2ee978af7d49f0fb0e7271c6ac074dfb4d39353).
401
+
402
+ See LICENSE.txt for further details.
@@ -1,15 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Devise::ParanoidVerificationCodeController < DeviseController
4
+ before_action :verify_requested_format!
4
5
  skip_before_action :handle_paranoid_verification
5
- prepend_before_action :authenticate_scope!, only: [:show, :update]
6
+ before_action :skip_paranoid_verification, only: %i[show update]
7
+ prepend_before_action :authenticate_scope!, only: %i[show update]
6
8
 
7
9
  def show
8
- if !resource.nil? && resource.need_paranoid_verification?
9
- respond_with(resource)
10
- else
11
- redirect_to :root
12
- end
10
+ respond_with(resource)
13
11
  end
14
12
 
15
13
  def update
@@ -17,20 +15,36 @@ class Devise::ParanoidVerificationCodeController < DeviseController
17
15
  warden.session(scope)['paranoid_verify'] = false
18
16
  set_flash_message :notice, :updated
19
17
  bypass_sign_in resource, scope: scope
20
- redirect_to stored_location_for(scope) || :root
18
+ respond_with({}, location: after_paranoid_verification_code_update_path_for(resource))
21
19
  else
22
20
  respond_with(resource, action: :show)
23
21
  end
24
22
  end
25
23
 
24
+ # Allows you to customize where the user is redirected to after the update action
25
+ # successfully completes.
26
+ #
27
+ # Defaults to the request's original path, and then `root` if that is `nil`.
28
+ #
29
+ # @param resource [ActiveModel::Model] Devise `resource` model for logged in user.
30
+ #
31
+ # @return [String, Symbol] The path that the user will be redirected to.
32
+ def after_paranoid_verification_code_update_path_for(_resource)
33
+ stored_location_for(scope) || :root
34
+ end
35
+
26
36
  private
27
37
 
38
+ def skip_paranoid_verification
39
+ return if !resource.nil? && resource.need_paranoid_verification?
40
+
41
+ redirect_to :root
42
+ end
43
+
28
44
  def resource_params
29
- if params.respond_to?(:permit)
30
- params.require(resource_name).permit(:paranoid_verification_code)
31
- else
32
- params[scope].slice(:paranoid_verification_code)
33
- end
45
+ permitted_params = %i[paranoid_verification_code]
46
+
47
+ params.require(resource_name).permit(*permitted_params)
34
48
  end
35
49
 
36
50
  def scope
@@ -1,42 +1,64 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Devise::PasswordExpiredController < DeviseController
4
+ before_action :verify_requested_format!
4
5
  skip_before_action :handle_password_change
5
- before_action :skip_password_change, only: [:show, :update]
6
- prepend_before_action :authenticate_scope!, only: [:show, :update]
6
+ before_action :skip_password_change, only: %i[show update]
7
+ prepend_before_action :authenticate_scope!, only: %i[show update]
7
8
 
8
9
  def show
9
10
  respond_with(resource)
10
11
  end
11
12
 
13
+ # Update the password stored on the `resource`.
14
+ # @note if a common data format like :json or :xml are requested
15
+ # this will respond with a 204 No Content and set the Location header.
16
+ # Useful for dealing with APIs when JS clients would otherwise automatically
17
+ # follow the redirect, which can be problematic.
18
+ # @see https://stackoverflow.com/questions/228225/prevent-redirection-of-xmlhttprequest
19
+ # @see https://github.com/axios/axios/issues/932#issuecomment-307390761
20
+ # @see https://github.com/devise-security/devise-security/pull/111
12
21
  def update
13
22
  resource.extend(Devise::Models::DatabaseAuthenticatablePatch)
14
- if resource.update_with_password(resource_params)
23
+ resource.update_with_password(resource_params)
24
+
25
+ yield resource if block_given?
26
+
27
+ if resource.errors.empty?
15
28
  warden.session(scope)['password_expired'] = false
16
29
  set_flash_message :notice, :updated
17
30
  bypass_sign_in resource, scope: scope
18
- redirect_to stored_location_for(scope) || :root
31
+ respond_with({}, location: after_password_expired_update_path_for(resource))
19
32
  else
20
33
  clean_up_passwords(resource)
21
34
  respond_with(resource, action: :show)
22
35
  end
23
36
  end
24
37
 
38
+ # Allows you to customize where the user is sent to after the update action
39
+ # successfully completes.
40
+ #
41
+ # Defaults to the request's original path, and then `root` if that is `nil`.
42
+ #
43
+ # @param resource [ActiveModel::Model] Devise `resource` model for logged in user.
44
+ #
45
+ # @return [String, Symbol] The path that the user will be sent to.
46
+ def after_password_expired_update_path_for(_resource)
47
+ stored_location_for(scope) || :root
48
+ end
49
+
25
50
  private
26
51
 
27
52
  def skip_password_change
28
53
  return if !resource.nil? && resource.need_change_password?
54
+
29
55
  redirect_to :root
30
56
  end
31
57
 
32
58
  def resource_params
33
- permitted_params = [:current_password, :password, :password_confirmation]
59
+ permitted_params = %i[current_password password password_confirmation]
34
60
 
35
- if params.respond_to?(:permit)
36
- params.require(resource_name).permit(*permitted_params)
37
- else
38
- params[scope].slice(*permitted_params)
39
- end
61
+ params.require(resource_name).permit(*permitted_params)
40
62
  end
41
63
 
42
64
  def scope
@@ -1,10 +1,10 @@
1
- <h2>Submit verification code</h2>
1
+ <h2>t('.submit_verification_code')</h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: [resource_name, :paranoid_verification_code], html: { method: :put }) do |f| %>
4
4
  <%= render partial: 'devise/shared/error_messages' %>
5
5
 
6
- <p><%= f.label :paranoid_verification_code, 'Verification code' %><br />
6
+ <p><%= f.label :paranoid_verification_code, t('.verification_code') %><br />
7
7
  <%= f.text_field :paranoid_verification_code, value: '' %></p>
8
8
 
9
- <p><%= f.submit 'Submit' %></p>
9
+ <p><%= f.submit t('.submit') %></p>
10
10
  <% end %>
@@ -1,16 +1,16 @@
1
- <h2>Renew your password</h2>
1
+ <h2><%= t('.renew_your_password') %></h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: [resource_name, :password_expired], html: { method: :put }) do |f| %>
4
4
  <%= render partial: 'devise/shared/error_messages' %>
5
5
 
6
- <p><%= f.label :current_password, 'Current password' %><br />
6
+ <p><%= f.label :current_password, t('.current_password') %><br />
7
7
  <%= f.password_field :current_password %></p>
8
8
 
9
- <p><%= f.label :password, 'New password' %><br />
9
+ <p><%= f.label :password, t('.new_password') %><br />
10
10
  <%= f.password_field :password %></p>
11
11
 
12
- <p><%= f.label :password_confirmation, 'Confirm new password' %><br />
12
+ <p><%= f.label :password_confirmation, t('.new_password_confirmation') %><br />
13
13
  <%= f.password_field :password_confirmation %></p>
14
14
 
15
- <p><%= f.submit 'Change my password' %></p>
15
+ <p><%= f.submit t('.change_my_password') %></p>
16
16
  <% end %>
@@ -0,0 +1,42 @@
1
+ bg:
2
+ errors:
3
+ messages:
4
+ taken_in_past: 'е използвана и преди.'
5
+ equal_to_current_password: 'трябва да е различна от настоящата парола.'
6
+ equal_to_email: 'трябва да е различна от e-mail адреса.'
7
+ password_complexity:
8
+ digit:
9
+ one: трябва да съдържа поне една цифра
10
+ other: трябва да съдържа %{count} цифри
11
+ lower:
12
+ one: трябва да съдържа поне една малка буква
13
+ other: трябва да съдържа поне %{count} малки букви
14
+ symbol:
15
+ one: трябва да съдържа поне един пунктоационен знак или символ
16
+ other: трябва да съдържа поне %{count} пунктоационни знака или символи
17
+ upper:
18
+ one: трябва да съдържа поне една главна буква
19
+ other: трябва да съдържа поне %{count} главни букви
20
+ devise:
21
+ invalid_captcha: 'Кодът е грешен.'
22
+ invalid_security_question: 'Отговора на тайния въпрос е грешен.'
23
+ paranoid_verify:
24
+ code_required: 'Моля въведете кода, който нашия екип по поддръжката Ви е предоставил'
25
+ paranoid_verification_code:
26
+ updated: Кодът за потвърждение е приет
27
+ show:
28
+ submit_verification_code: Изпрати код за потвърждение
29
+ verification_code: Код за потвърждение
30
+ submit: Изпрати
31
+ password_expired:
32
+ updated: 'Вашата нова парола е запазена.'
33
+ change_required: 'Вашата парола е изтекла. Моля подновете паролата си.'
34
+ show:
35
+ renew_your_password: Подновете паролата си
36
+ current_password: Настояща парола
37
+ new_password: Нова парола
38
+ new_password_confirmation: Потвърждение на нова парола
39
+ change_my_password: Промени паролата ми
40
+ failure:
41
+ session_limited: 'Вашето потребителско име и парола са използвани в друг браузър. Моля влезте отново за да продължите в този браузър.'
42
+ expired: 'Вашия акаунт е затворен поради неактивност. Моля свържете се с администратор.'
@@ -0,0 +1,50 @@
1
+ by:
2
+ errors:
3
+ messages:
4
+ taken_in_past: 'ужо раней выкарыстоўваўся.'
5
+ equal_to_current_password: 'павінен адрознівацца ад сучаснага пароля.'
6
+ equal_to_email: 'павінна адрознівацца ад электроннай пошты.'
7
+ password_complexity:
8
+ digit:
9
+ one: 'павінен утрымліваць хоць адну лічбу'
10
+ few: 'павінен утрымліваць хоць %{count} лічбы'
11
+ many: 'павінен утрымліваць хоць %{count} лічбы'
12
+ other: 'павінен утрымліваць хоць %{count} лічбы'
13
+ lower:
14
+ one: 'павінен утрымліваць хоць адну маленькую літару'
15
+ few: 'павінен утрымліваць хоць %{count} малыx літары'
16
+ many: 'павінен утрымліваць хоць %{count} малыx літары'
17
+ other: 'павінен утрымліваць хоць %{count} малыx літары'
18
+ symbol:
19
+ one: 'павінен утрымліваць хоць адзін знак пунктуацыі або сімвал'
20
+ few: 'павінен утрымліваць хоць %{count} знака пунктуацыі або сімвала'
21
+ many: 'павінен утрымліваць хоць %{count} знака пунктуацыі або сімвала'
22
+ other: 'павінен утрымліваць хоць %{count} знака пунктуацыі або сімвала'
23
+ upper:
24
+ one: 'павінен утрымліваць хоць адну вялікую літару'
25
+ few: 'павінен утрымліваць хоць %{count} вялікіx літары'
26
+ many: 'павінен утрымліваць хоць %{count} вялікіx літары'
27
+ other: 'павінен утрымліваць хоць %{count} вялікіx літары'
28
+ devise:
29
+ invalid_captcha: 'Уведзены няправільны код капчы.'
30
+ invalid_security_question: 'Адказ на сакрэтнае пытанне быў няправільны.'
31
+ paranoid_verify:
32
+ code_required: 'Калі ласка, увядзіце код, атрыманы ад нашай каманды падтрымкі'
33
+ paranoid_verification_code:
34
+ updated: Код спраўджання прыняты
35
+ show:
36
+ submit_verification_code: 'Увод кода пацверджання'
37
+ verification_code: 'Код пацверджання'
38
+ submit: 'Адправіць'
39
+ password_expired:
40
+ updated: 'Ваш новы пароль захаваны.'
41
+ change_required: 'Ваш пароль састарэў. Калі ласка, усталюйце новы.'
42
+ show:
43
+ renew_your_password: 'Змена пароля'
44
+ current_password: 'Сучасны пароль'
45
+ new_password: 'Новы пароль'
46
+ new_password_confirmation: 'Пацвердзіце новы пароль'
47
+ change_my_password: 'Змяніць пароль'
48
+ failure:
49
+ session_limited: 'Вашы параметры ўваходу выкарыстоўваюцца ў іншым браўзэры. Калі ласка, аўтарызуйцеся зноў, каб працягнуць у гэтым браўзэры.'
50
+ expired: 'Ваш уліковы запіс састарэў з-за неактыўнасці. Калі ласка, звяжыцеся з адміністратарам.'