devise-security 0.15.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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +3 -1
  3. data/README.md +43 -24
  4. data/app/controllers/devise/paranoid_verification_code_controller.rb +26 -12
  5. data/app/controllers/devise/password_expired_controller.rb +23 -10
  6. data/config/locales/bg.yml +42 -0
  7. data/config/locales/by.yml +2 -0
  8. data/config/locales/cs.yml +6 -0
  9. data/config/locales/de.yml +4 -0
  10. data/config/locales/en.yml +3 -1
  11. data/config/locales/es.yml +13 -0
  12. data/config/locales/fa.yml +2 -0
  13. data/config/locales/fr.yml +15 -2
  14. data/config/locales/hi.yml +22 -20
  15. data/config/locales/it.yml +2 -0
  16. data/config/locales/ja.yml +13 -0
  17. data/config/locales/nl.yml +2 -0
  18. data/config/locales/pt.yml +2 -0
  19. data/config/locales/ru.yml +2 -0
  20. data/config/locales/tr.yml +26 -1
  21. data/config/locales/uk.yml +2 -0
  22. data/config/locales/zh_CN.yml +2 -0
  23. data/config/locales/zh_TW.yml +2 -0
  24. data/lib/devise-security/controllers/helpers.rb +25 -13
  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 +10 -6
  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 +62 -11
  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 +15 -6
  42. data/lib/generators/devise_security/install_generator.rb +4 -6
  43. data/{test/tmp/config/initializers/devise-security.rb → lib/generators/templates/devise_security.rb} +9 -1
  44. data/test/controllers/test_paranoid_verification_code_controller.rb +133 -0
  45. data/test/controllers/test_password_expired_controller.rb +122 -99
  46. data/test/controllers/test_security_question_controller.rb +19 -37
  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 +4 -13
  82. data/test/dummy/config/initializers/devise.rb +1 -5
  83. data/test/dummy/config/initializers/migration_class.rb +1 -8
  84. data/test/dummy/config/locales/en.yml +10 -0
  85. data/test/dummy/config/mongoid.yml +1 -1
  86. data/test/dummy/config/routes.rb +3 -1
  87. data/test/dummy/config.ru +1 -1
  88. data/test/dummy/db/migrate/20120508165529_create_tables.rb +5 -5
  89. data/test/dummy/lib/shared_expirable_columns.rb +1 -0
  90. data/test/dummy/lib/shared_security_questions_fields.rb +1 -0
  91. data/test/dummy/lib/shared_user.rb +17 -6
  92. data/test/dummy/lib/shared_user_without_omniauth.rb +12 -3
  93. data/test/dummy/lib/shared_verification_fields.rb +1 -0
  94. data/test/dummy/log/test.log +44592 -1151
  95. data/test/i18n_test.rb +22 -0
  96. data/test/integration/test_paranoid_verification_code_workflow.rb +53 -0
  97. data/test/integration/test_password_expirable_workflow.rb +2 -6
  98. data/test/integration/test_session_limitable_workflow.rb +5 -3
  99. data/test/orm/active_record.rb +7 -7
  100. data/test/orm/mongoid.rb +2 -1
  101. data/test/support/integration_helpers.rb +10 -22
  102. data/test/support/mongoid.yml +1 -1
  103. data/test/test_compatibility.rb +2 -0
  104. data/test/test_complexity_validator.rb +247 -37
  105. data/test/test_database_authenticatable_patch.rb +146 -0
  106. data/test/test_helper.rb +11 -12
  107. data/test/test_install_generator.rb +2 -2
  108. data/test/test_paranoid_verification.rb +8 -9
  109. data/test/test_password_archivable.rb +34 -11
  110. data/test/test_password_expirable.rb +27 -27
  111. data/test/test_secure_validatable.rb +284 -50
  112. data/test/test_secure_validatable_overrides.rb +185 -0
  113. data/test/test_session_limitable.rb +9 -9
  114. data/{lib/generators/templates/devise-security.rb → test/tmp/config/initializers/devise_security.rb} +9 -1
  115. data/test/tmp/config/locales/devise.security_extension.by.yml +50 -0
  116. data/test/tmp/config/locales/devise.security_extension.cs.yml +46 -0
  117. data/test/tmp/config/locales/devise.security_extension.de.yml +4 -0
  118. data/test/tmp/config/locales/devise.security_extension.en.yml +3 -1
  119. data/test/tmp/config/locales/devise.security_extension.es.yml +22 -9
  120. data/test/tmp/config/locales/devise.security_extension.fa.yml +2 -0
  121. data/test/tmp/config/locales/devise.security_extension.fr.yml +15 -2
  122. data/test/tmp/config/locales/devise.security_extension.hi.yml +43 -0
  123. data/test/tmp/config/locales/devise.security_extension.it.yml +2 -0
  124. data/test/tmp/config/locales/devise.security_extension.ja.yml +13 -0
  125. data/test/tmp/config/locales/devise.security_extension.nl.yml +2 -0
  126. data/test/tmp/config/locales/devise.security_extension.pt.yml +2 -0
  127. data/test/tmp/config/locales/devise.security_extension.ru.yml +2 -0
  128. data/test/tmp/config/locales/devise.security_extension.tr.yml +26 -1
  129. data/test/tmp/config/locales/devise.security_extension.uk.yml +2 -0
  130. data/test/tmp/config/locales/devise.security_extension.zh_CN.yml +2 -0
  131. data/test/tmp/config/locales/devise.security_extension.zh_TW.yml +42 -0
  132. metadata +65 -45
  133. data/lib/devise-security/orm/active_record.rb +0 -20
  134. data/lib/devise-security/patches/confirmations_controller_captcha.rb +0 -23
  135. data/lib/devise-security/patches/confirmations_controller_security_question.rb +0 -26
  136. data/lib/devise-security/patches/passwords_controller_captcha.rb +0 -22
  137. data/lib/devise-security/patches/passwords_controller_security_question.rb +0 -25
  138. data/lib/devise-security/patches/registrations_controller_captcha.rb +0 -35
  139. data/lib/devise-security/patches/sessions_controller_captcha.rb +0 -26
  140. data/lib/devise-security/patches/unlocks_controller_captcha.rb +0 -22
  141. data/lib/devise-security/patches/unlocks_controller_security_question.rb +0 -25
  142. data/lib/devise-security/schema.rb +0 -66
  143. data/test/dummy/app/controllers/foos_controller.rb +0 -0
  144. data/test/dummy/app/models/secure_user.rb +0 -9
  145. data/test/dummy/lib/shared_user_without_email.rb +0 -28
@@ -1,85 +1,319 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'test_helper'
4
- require 'rails_email_validator'
5
4
 
6
5
  class TestSecureValidatable < ActiveSupport::TestCase
7
6
  class User < ApplicationRecord
8
- devise :database_authenticatable, :password_archivable,
9
- :paranoid_verification, :password_expirable, :secure_validatable
7
+ devise :database_authenticatable, :secure_validatable
10
8
  include ::Mongoid::Mappings if DEVISE_ORM == :mongoid
11
9
  end
12
10
 
13
- test 'email cannot be blank' do
14
- msg = "Email can't be blank"
15
- user = User.create password: 'passWord1', password_confirmation: 'passWord1'
11
+ class EmailNotRequiredUser < User
12
+ protected
16
13
 
17
- assert_equal(false, user.valid?)
18
- assert_equal([msg], user.errors.full_messages)
19
- assert_raises(ORMInvalidRecordException) do
20
- user.save!
14
+ def email_required?
15
+ false
21
16
  end
22
17
  end
23
18
 
19
+ test 'email cannot be blank upon creation' do
20
+ user = User.new(
21
+ password: 'Password1!', password_confirmation: 'Password1!'
22
+ )
23
+
24
+ assert user.invalid?
25
+ assert_equal(["Email can't be blank"], user.errors.full_messages)
26
+ end
27
+
28
+ test 'email can be blank upon creation if email not required' do
29
+ user = EmailNotRequiredUser.new(
30
+ password: 'Password1!', password_confirmation: 'Password1!'
31
+ )
32
+
33
+ assert user.valid?
34
+ end
35
+
36
+ test 'email cannot be updated to be blank' do
37
+ user = User.new(
38
+ email: 'bob@microsoft.com',
39
+ password: 'Password1!',
40
+ password_confirmation: 'Password1!'
41
+ )
42
+
43
+ assert user.valid?
44
+
45
+ user.email = nil
46
+
47
+ assert user.invalid?
48
+ assert_equal(["Email can't be blank"], user.errors.full_messages)
49
+ end
50
+
51
+ test 'email can be updated to be blank if email not required' do
52
+ user = EmailNotRequiredUser.new(
53
+ email: 'bob@microsoft.com',
54
+ password: 'Password1!',
55
+ password_confirmation: 'Password1!'
56
+ )
57
+
58
+ assert user.valid?
59
+
60
+ user.email = nil
61
+
62
+ assert user.valid?
63
+ end
64
+
24
65
  test 'email must be valid' do
25
- msg = 'Email is invalid'
26
- user = User.create email: 'bob', password: 'passWord1', password_confirmation: 'passWord1'
27
- assert_equal(false, user.valid?)
28
- assert_equal([msg], user.errors.full_messages)
29
- assert_raises(ORMInvalidRecordException) do
30
- user.save!
31
- end
66
+ user = User.new(
67
+ email: 'bob', password: 'Password1!', password_confirmation: 'Password1!'
68
+ )
69
+
70
+ assert user.invalid?
71
+ assert_equal(['Email is invalid'], user.errors.full_messages)
32
72
  end
33
73
 
34
74
  test 'validate both email and password' do
35
- msgs = ['Email is invalid', 'Password must contain at least one upper-case letter']
36
- user = User.create email: 'bob@@foo.tv', password: 'password1', password_confirmation: 'password1'
37
- assert_equal(false, user.valid?)
75
+ user = User.new(
76
+ email: 'bob',
77
+ password: 'password1!',
78
+ password_confirmation: 'password1!'
79
+ )
80
+
81
+ assert user.invalid?
82
+ assert_equal(
83
+ [
84
+ 'Email is invalid',
85
+ 'Password must contain at least one upper-case letter'
86
+ ],
87
+ user.errors.full_messages
88
+ )
89
+ end
90
+
91
+ test 'password cannot be blank upon creation' do
92
+ user = User.new(email: 'bob@microsoft.com')
93
+
94
+ msgs = ["Password can't be blank"]
95
+
96
+ msgs << "Encrypted password can't be blank" if DEVISE_ORM == :mongoid
97
+
98
+ assert user.invalid?
38
99
  assert_equal(msgs, user.errors.full_messages)
39
- assert_raises(ORMInvalidRecordException) { user.save! }
100
+ end
101
+
102
+ test 'password cannot be updated to be blank' do
103
+ user = User.new(
104
+ email: 'bob@microsoft.com',
105
+ password: 'Password1!',
106
+ password_confirmation: 'Password1!'
107
+ )
108
+
109
+ assert user.valid?
110
+
111
+ user.password = nil
112
+ user.password_confirmation = nil
113
+
114
+ assert user.invalid?
115
+ assert_equal(["Password can't be blank"], user.errors.full_messages)
116
+ end
117
+
118
+ test 'password_confirmation must match password' do
119
+ user = User.new(
120
+ email: 'bob@microsoft.com',
121
+ password: 'Password1!',
122
+ password_confirmation: 'not the same password'
123
+ )
124
+
125
+ assert user.invalid?
126
+ assert_equal(
127
+ ["Password confirmation doesn't match Password"],
128
+ user.errors.full_messages
129
+ )
130
+ end
131
+
132
+ test 'password_confirmation cannot be blank' do
133
+ user = User.new(
134
+ email: 'bob@microsoft.com',
135
+ password: 'Password1!',
136
+ password_confirmation: ''
137
+ )
138
+
139
+ assert user.invalid?
140
+ assert_equal(
141
+ ["Password confirmation doesn't match Password"],
142
+ user.errors.full_messages
143
+ )
144
+ end
145
+
146
+ test 'password_confirmation can be skipped' do
147
+ user = User.new(
148
+ email: 'bob@microsoft.com',
149
+ password: 'Password1!',
150
+ password_confirmation: nil
151
+ )
152
+
153
+ assert user.valid?
40
154
  end
41
155
 
42
156
  test 'password must have capital letter' do
43
- msgs = ['Password must contain at least one upper-case letter']
44
- user = User.create email: 'bob@microsoft.com', password: 'password1', password_confirmation: 'password1'
45
- assert_equal(false, user.valid?)
46
- assert_equal(msgs, user.errors.full_messages)
47
- assert_raises(ORMInvalidRecordException) { user.save! }
157
+ user = User.new(
158
+ email: 'bob@microsoft.com',
159
+ password: 'password1',
160
+ password_confirmation: 'password1'
161
+ )
162
+
163
+ assert user.invalid?
164
+ assert_equal(
165
+ ['Password must contain at least one upper-case letter'],
166
+ user.errors.full_messages
167
+ )
48
168
  end
49
169
 
50
170
  test 'password must have lowercase letter' do
51
- msg = 'Password must contain at least one lower-case letter'
52
- user = User.create email: 'bob@microsoft.com', password: 'PASSWORD1', password_confirmation: 'PASSWORD1'
53
- assert_equal(false, user.valid?)
54
- assert_equal([msg], user.errors.full_messages)
55
- assert_raises(ORMInvalidRecordException) { user.save! }
171
+ user = User.new(
172
+ email: 'bob@microsoft.com',
173
+ password: 'PASSWORD1',
174
+ password_confirmation: 'PASSWORD1'
175
+ )
176
+
177
+ assert user.invalid?
178
+ assert_equal(
179
+ ['Password must contain at least one lower-case letter'],
180
+ user.errors.full_messages
181
+ )
56
182
  end
57
183
 
58
184
  test 'password must have number' do
59
- msg = 'Password must contain at least one digit'
60
- user = User.create email: 'bob@microsoft.com', password: 'PASSword', password_confirmation: 'PASSword'
61
- assert_equal(false, user.valid?)
62
- assert_equal([msg], user.errors.full_messages)
63
- assert_raises(ORMInvalidRecordException) { user.save! }
185
+ user = User.new(
186
+ email: 'bob@microsoft.com',
187
+ password: 'PASSword',
188
+ password_confirmation: 'PASSword'
189
+ )
190
+
191
+ assert user.invalid?
192
+ assert_equal(
193
+ ['Password must contain at least one digit'],
194
+ user.errors.full_messages
195
+ )
64
196
  end
65
197
 
66
- test 'password must have minimum length' do
67
- msg = 'Password is too short (minimum is 7 characters)'
68
- user = User.create email: 'bob@microsoft.com', password: 'Pa3zZ', password_confirmation: 'Pa3zZ'
69
- assert_equal(false, user.valid?)
70
- assert_equal([msg], user.errors.full_messages)
71
- assert_raises(ORMInvalidRecordException) { user.save! }
198
+ test 'password must meet minimum length' do
199
+ user = User.new(
200
+ email: 'bob@microsoft.com',
201
+ password: 'Pa3zZ',
202
+ password_confirmation: 'Pa3zZ'
203
+ )
204
+
205
+ assert user.invalid?
206
+ assert_equal(
207
+ ['Password is too short (minimum is 7 characters)'],
208
+ user.errors.full_messages
209
+ )
72
210
  end
73
211
 
74
- test 'duplicate email validation message is added only once' do
212
+ test "new user can't use existing user's email" do
75
213
  options = {
76
- email: 'test@example.org',
77
- password: 'Test12345',
78
- password_confirmation: 'Test12345',
214
+ email: 'bob@microsoft.com',
215
+ password: 'Password1!',
216
+ password_confirmation: 'Password1!'
79
217
  }
80
- SecureUser.create!(options)
81
- user = SecureUser.new(options)
82
- refute user.valid?
83
- assert_equal DEVISE_ORM == :active_record ? ['Email has already been taken'] : ['Email is already taken'], user.errors.full_messages
218
+ User.create!(options)
219
+ user = User.new(options)
220
+
221
+ assert user.invalid?
222
+ assert_equal(['Email has already been taken'], user.errors.full_messages)
223
+ end
224
+
225
+ test "new user can't use existing user's email with different casing" do
226
+ options = {
227
+ email: 'bob@microsoft.com',
228
+ password: 'Password1!',
229
+ password_confirmation: 'Password1!'
230
+ }
231
+ User.create!(options)
232
+ options[:email] = 'BOB@MICROSOFT.COM'
233
+ user = User.new(options)
234
+
235
+ assert user.invalid?
236
+ assert_equal(['Email has already been taken'], user.errors.full_messages)
237
+ end
238
+
239
+ test 'password cannot equal email for new user' do
240
+ user = User.new(
241
+ email: 'Bob1@microsoft.com',
242
+ password: 'Bob1@microsoft.com',
243
+ password_confirmation: 'Bob1@microsoft.com'
244
+ )
245
+
246
+ assert user.invalid?
247
+ assert_equal(
248
+ ['Password must be different than the email.'],
249
+ user.errors.full_messages
250
+ )
251
+ end
252
+
253
+ test 'password cannot equal case sensitive version of email for new user' do
254
+ user = User.new(
255
+ email: 'bob1@microsoft.com',
256
+ password: 'BoB1@microsoft.com',
257
+ password_confirmation: 'BoB1@microsoft.com'
258
+ )
259
+
260
+ assert user.invalid?
261
+ assert_equal(
262
+ ['Password must be different than the email.'],
263
+ user.errors.full_messages
264
+ )
265
+ end
266
+
267
+ test 'password cannot equal email with spaces for new user' do
268
+ user = User.new(
269
+ email: 'Bob1@microsoft.com',
270
+ password: 'Bob1@microsoft.com ',
271
+ password_confirmation: 'Bob1@microsoft.com '
272
+ )
273
+
274
+ assert user.invalid?
275
+ assert_equal(
276
+ ['Password must be different than the email.'],
277
+ user.errors.full_messages
278
+ )
279
+ end
280
+
281
+ test 'password cannot equal case sensitive version of email with spaces '\
282
+ 'for new user' do
283
+ user = User.new(
284
+ email: 'Bob1@microsoft.com',
285
+ password: ' boB1@microsoft.com ',
286
+ password_confirmation: ' boB1@microsoft.com '
287
+ )
288
+
289
+ assert user.invalid?
290
+ assert_equal(
291
+ ['Password must be different than the email.'],
292
+ user.errors.full_messages
293
+ )
294
+ end
295
+
296
+ test 'new password cannot equal current password' do
297
+ user = User.create(
298
+ email: 'bob@microsoft.com',
299
+ password: 'Password1!',
300
+ password_confirmation: 'Password1!'
301
+ )
302
+
303
+ user.password = 'Password1!'
304
+
305
+ assert user.invalid?
306
+ assert_equal(
307
+ ['Password must be different than the current password.'],
308
+ user.errors.full_messages
309
+ )
310
+ end
311
+
312
+ test 'should not be included in objects with invalid API' do
313
+ error = assert_raise RuntimeError do
314
+ class ::Dog; include Devise::Models::SecureValidatable; end
315
+ end
316
+
317
+ assert_equal('Could not use SecureValidatable on Dog', error.message)
84
318
  end
85
319
  end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TestSecureValidatableOverrides < ActiveSupport::TestCase
6
+ class ::CustomClassPasswordValidator < DeviseSecurity::PasswordComplexityValidator
7
+ def patterns
8
+ super.merge(letter: /\p{Alpha}/)
9
+ end
10
+ end
11
+
12
+ class ::CustomInstancePasswordValidator < DeviseSecurity::PasswordComplexityValidator
13
+ # Add a pattern for alphanumeric characters. See
14
+ # [en.yml](file:///./test/dummy/config/locales/en.yml) for translations used in
15
+ # tests.
16
+ def patterns
17
+ super.merge(alnum: /\p{Alnum}/)
18
+ end
19
+ end
20
+
21
+ class User < ApplicationRecord
22
+ devise :database_authenticatable, :secure_validatable
23
+ include ::Mongoid::Mappings if DEVISE_ORM == :mongoid
24
+ end
25
+
26
+ class ClassLevelOverrideUser < User
27
+ self.allow_passwords_equal_to_email = true
28
+ self.email_validation = false
29
+ self.password_complexity = { symbol: 1, letter: 1 }
30
+ self.password_complexity_validator = 'custom_class_password_validator'
31
+ self.password_length = 10..100
32
+ end
33
+
34
+ class InstanceLevelOverrideUser < ClassLevelOverrideUser
35
+ def allow_passwords_equal_to_email
36
+ true
37
+ end
38
+
39
+ def email_validation
40
+ false
41
+ end
42
+
43
+ def password_complexity
44
+ { symbol: 2, alnum: 1 }
45
+ end
46
+
47
+ def password_length
48
+ 11..100
49
+ end
50
+
51
+ def password_complexity_validator
52
+ 'CustomInstancePasswordValidator'
53
+ end
54
+ end
55
+
56
+ test 'email equal to password can be overridden at the class level' do
57
+ user = ClassLevelOverrideUser.new(
58
+ email: 'bob1!@microsoft.com',
59
+ password: 'bob1!@microsoft.com',
60
+ password_confirmation: 'bob1!@microsoft.com'
61
+ )
62
+
63
+ assert user.valid?
64
+ end
65
+
66
+ test 'email equal to password can be overridden at the instance level' do
67
+ user = InstanceLevelOverrideUser.new(
68
+ email: 'bob1!@microsoft.com',
69
+ password: 'bob1!@microsoft.com',
70
+ password_confirmation: 'bob1!@microsoft.com'
71
+ )
72
+
73
+ assert user.valid?
74
+ end
75
+
76
+ test 'email validation can be overridden at the class level' do
77
+ user = ClassLevelOverrideUser.new(
78
+ email: 'bob1!@f.com',
79
+ password: 'Pa3zZ1!!aaaaaa',
80
+ password_confirmation: 'Pa3zZ1!!aaaaaa'
81
+ )
82
+
83
+ assert user.valid?
84
+ end
85
+
86
+ test 'email validation can be overridden at the instance level' do
87
+ user = InstanceLevelOverrideUser.new(
88
+ email: 'bob1!@f.com',
89
+ password: 'Pa3zZ1!!aaaaaa',
90
+ password_confirmation: 'Pa3zZ1!!aaaaaa'
91
+ )
92
+
93
+ assert user.valid?
94
+ end
95
+
96
+ test 'password complexity can be overridden at the class level' do
97
+ user = ClassLevelOverrideUser.new(
98
+ email: 'bob@microsoft.com',
99
+ password: 'PASSwordddd',
100
+ password_confirmation: 'PASSwordddd'
101
+ )
102
+
103
+ assert user.invalid?
104
+ assert_equal(
105
+ ['Password must contain at least one punctuation mark or symbol'],
106
+ user.errors.full_messages
107
+ )
108
+ end
109
+
110
+ test 'password complexity can be overridden at the instance level' do
111
+ user = InstanceLevelOverrideUser.new(
112
+ email: 'bob@microsoft.com',
113
+ password: 'PASSwordddd',
114
+ password_confirmation: 'PASSwordddd'
115
+ )
116
+
117
+ assert user.invalid?
118
+ assert_equal(
119
+ ['Password must contain at least 2 punctuation marks or symbols'],
120
+ user.errors.full_messages
121
+ )
122
+ end
123
+
124
+ test 'password length can be overridden at the class level' do
125
+ user = ClassLevelOverrideUser.new(
126
+ email: 'bob@microsoft.com',
127
+ password: 'Pa3zZ1!',
128
+ password_confirmation: 'Pa3zZ1!'
129
+ )
130
+
131
+ assert user.invalid?
132
+ assert_equal(
133
+ ['Password is too short (minimum is 10 characters)'],
134
+ user.errors.full_messages
135
+ )
136
+ end
137
+
138
+ test 'password length can be overridden at the instance level' do
139
+ user = InstanceLevelOverrideUser.new(
140
+ email: 'bob@microsoft.com',
141
+ password: 'Pa3zZ1!!',
142
+ password_confirmation: 'Pa3zZ1!!'
143
+ )
144
+
145
+ assert user.invalid?
146
+ assert_equal(
147
+ ['Password is too short (minimum is 11 characters)'],
148
+ user.errors.full_messages
149
+ )
150
+ end
151
+
152
+ test 'password validator can be overridden at the instance level' do
153
+ password = '!' * 11 # 11 characters, all symbols
154
+ user = InstanceLevelOverrideUser.new(
155
+ email: 'bob@microsoft.com',
156
+ password: password,
157
+ password_confirmation: password
158
+ )
159
+
160
+ assert user.invalid?
161
+ # This validation error only occurs when the CustomInstancePasswordValidator
162
+ # is used.
163
+ assert_equal(
164
+ ['Password must contain at least one letter or number'],
165
+ user.errors.full_messages
166
+ )
167
+ end
168
+
169
+ test 'password validator can be overridden at the class level' do
170
+ password = '!' * 10 # 10 characters, all symbols
171
+ user = ClassLevelOverrideUser.new(
172
+ email: 'bob@microsoft.com',
173
+ password: password,
174
+ password_confirmation: password
175
+ )
176
+
177
+ assert user.invalid?
178
+ # This validation error only occurs when the CustomClassPasswordValidator
179
+ # is used.
180
+ assert_equal(
181
+ ['Password must contain at least one letter'],
182
+ user.errors.full_messages
183
+ )
184
+ end
185
+ end
@@ -10,15 +10,15 @@ class TestSessionLimitable < ActiveSupport::TestCase
10
10
  end
11
11
 
12
12
  test 'check is not skipped by default' do
13
- user = User.create email: 'bob@microsoft.com', password: 'password1', password_confirmation: 'password1'
14
- assert_equal(false, user.skip_session_limitable?)
13
+ user = User.new(email: 'bob@microsoft.com', password: 'password1', password_confirmation: 'password1')
14
+ assert_not(user.skip_session_limitable?)
15
15
  end
16
16
 
17
17
  test 'default check can be overridden by record instance' do
18
- modified_user = ModifiedUser.create email: 'bob2@microsoft.com', password: 'password1', password_confirmation: 'password1'
19
- assert_equal(true, modified_user.skip_session_limitable?)
18
+ modified_user = ModifiedUser.new(email: 'bob2@microsoft.com', password: 'password1', password_confirmation: 'password1')
19
+ assert(modified_user.skip_session_limitable?)
20
20
  end
21
-
21
+
22
22
  class SessionLimitableUser < User
23
23
  devise :session_limitable
24
24
  include ::Mongoid::Mappings if DEVISE_ORM == :mongoid
@@ -34,7 +34,7 @@ class TestSessionLimitable < ActiveSupport::TestCase
34
34
  assert_nil user.unique_session_id
35
35
  user.update_unique_session_id!('unique_value')
36
36
  user.reload
37
- assert_equal user.unique_session_id, 'unique_value'
37
+ assert_equal('unique_value', user.unique_session_id)
38
38
  end
39
39
 
40
40
  test '#update_unique_session_id!(value) updates invalid record atomically' do
@@ -45,13 +45,13 @@ class TestSessionLimitable < ActiveSupport::TestCase
45
45
  assert_nil user.unique_session_id
46
46
  user.update_unique_session_id!('unique_value')
47
47
  user.reload
48
- assert_equal user.email, 'bob@microsoft.com'
49
- assert_equal user.unique_session_id, 'unique_value'
48
+ assert_equal('bob@microsoft.com', user.email)
49
+ assert_equal('unique_value', user.unique_session_id)
50
50
  end
51
51
 
52
52
  test '#update_unique_session_id!(value) raises an exception on an unpersisted record' do
53
53
  user = User.create
54
- assert !user.persisted?
54
+ assert_not user.persisted?
55
55
  assert_raises(Devise::Models::Compatibility::NotPersistedError) { user.update_unique_session_id!('unique_value') }
56
56
  end
57
57
  end
@@ -7,7 +7,9 @@ Devise.setup do |config|
7
7
  # Should the password expire (e.g 3.months)
8
8
  # config.expire_password_after = false
9
9
 
10
- # Need 1 char of A-Z, a-z and 0-9
10
+ # Need 1 char each of: A-Z, a-z, 0-9, and a punctuation mark or symbol
11
+ # You may use "digits" in place of "digit" and "symbols" in place of
12
+ # "symbol" based on your preference
11
13
  # config.password_complexity = { digit: 1, lower: 1, symbol: 1, upper: 1 }
12
14
 
13
15
  # How many passwords to keep in archive
@@ -41,4 +43,10 @@ Devise.setup do |config|
41
43
 
42
44
  # Time period for account expiry from last_activity_at
43
45
  # config.expire_after = 90.days
46
+
47
+ # Allow password to equal the email
48
+ # config.allow_passwords_equal_to_email = false
49
+
50
+ # paranoid_verification will regenerate verification code after failed attempt
51
+ # config.paranoid_code_regenerate_after_attempt = 10
44
52
  end
@@ -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: 'Ваш уліковы запіс састарэў з-за неактыўнасці. Калі ласка, звяжыцеся з адміністратарам.'