devise 1.1.3 → 1.2.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 (157) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.rdoc +94 -0
  4. data/Gemfile +24 -13
  5. data/Gemfile.lock +119 -75
  6. data/MIT-LICENSE +1 -1
  7. data/README.rdoc +144 -101
  8. data/Rakefile +3 -24
  9. data/app/controllers/devise/confirmations_controller.rb +1 -1
  10. data/app/controllers/devise/omniauth_callbacks_controller.rb +26 -0
  11. data/app/controllers/devise/passwords_controller.rb +1 -1
  12. data/app/controllers/devise/registrations_controller.rb +60 -7
  13. data/app/controllers/devise/sessions_controller.rb +6 -4
  14. data/app/controllers/devise/unlocks_controller.rb +1 -1
  15. data/app/helpers/devise_helper.rb +10 -2
  16. data/app/mailers/devise/mailer.rb +27 -10
  17. data/app/views/devise/confirmations/new.html.erb +1 -1
  18. data/app/views/devise/passwords/edit.html.erb +2 -2
  19. data/app/views/devise/passwords/new.html.erb +1 -1
  20. data/app/views/devise/registrations/edit.html.erb +1 -1
  21. data/app/views/devise/registrations/new.html.erb +1 -1
  22. data/app/views/devise/sessions/new.html.erb +1 -1
  23. data/app/views/devise/shared/_links.erb +6 -0
  24. data/app/views/devise/unlocks/new.html.erb +1 -1
  25. data/config/locales/en.yml +11 -2
  26. data/devise.gemspec +25 -0
  27. data/lib/devise/controllers/helpers.rb +119 -116
  28. data/lib/devise/controllers/internal_helpers.rb +29 -8
  29. data/lib/devise/controllers/rememberable.rb +52 -0
  30. data/lib/devise/controllers/scoped_views.rb +4 -6
  31. data/lib/devise/controllers/url_helpers.rb +3 -5
  32. data/lib/devise/encryptors/authlogic_sha512.rb +1 -1
  33. data/lib/devise/encryptors/base.rb +1 -1
  34. data/lib/devise/encryptors/restful_authentication_sha1.rb +4 -4
  35. data/lib/devise/failure_app.rb +46 -10
  36. data/lib/devise/hooks/activatable.rb +2 -2
  37. data/lib/devise/hooks/forgetable.rb +1 -3
  38. data/lib/devise/hooks/rememberable.rb +5 -42
  39. data/lib/devise/hooks/timeoutable.rb +1 -1
  40. data/lib/devise/mapping.rb +18 -7
  41. data/lib/devise/models/authenticatable.rb +73 -31
  42. data/lib/devise/models/confirmable.rb +16 -20
  43. data/lib/devise/models/database_authenticatable.rb +27 -37
  44. data/lib/devise/models/encryptable.rb +72 -0
  45. data/lib/devise/models/lockable.rb +27 -21
  46. data/lib/devise/models/omniauthable.rb +23 -0
  47. data/lib/devise/models/recoverable.rb +13 -3
  48. data/lib/devise/models/registerable.rb +13 -0
  49. data/lib/devise/models/rememberable.rb +39 -34
  50. data/lib/devise/models/timeoutable.rb +20 -3
  51. data/lib/devise/models/token_authenticatable.rb +22 -10
  52. data/lib/devise/models/validatable.rb +16 -4
  53. data/lib/devise/models.rb +4 -16
  54. data/lib/devise/modules.rb +15 -8
  55. data/lib/devise/omniauth/config.rb +18 -0
  56. data/lib/devise/omniauth/url_helpers.rb +33 -0
  57. data/lib/devise/omniauth.rb +32 -0
  58. data/lib/devise/orm/active_record.rb +2 -0
  59. data/lib/devise/orm/mongoid.rb +4 -2
  60. data/lib/devise/rails/routes.rb +67 -20
  61. data/lib/devise/rails/warden_compat.rb +101 -15
  62. data/lib/devise/rails.rb +33 -44
  63. data/lib/devise/schema.rb +16 -16
  64. data/lib/devise/strategies/authenticatable.rb +48 -7
  65. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  66. data/lib/devise/strategies/rememberable.rb +6 -5
  67. data/lib/devise/strategies/token_authenticatable.rb +6 -2
  68. data/lib/devise/test_helpers.rb +13 -3
  69. data/lib/devise/version.rb +1 -1
  70. data/lib/devise.rb +162 -50
  71. data/lib/generators/active_record/devise_generator.rb +2 -2
  72. data/lib/generators/active_record/templates/migration.rb +2 -0
  73. data/lib/generators/devise/devise_generator.rb +3 -1
  74. data/lib/generators/devise/orm_helpers.rb +1 -1
  75. data/lib/generators/devise/views_generator.rb +8 -45
  76. data/lib/generators/mongoid/devise_generator.rb +2 -2
  77. data/lib/generators/templates/devise.rb +82 -39
  78. data/test/controllers/helpers_test.rb +78 -72
  79. data/test/controllers/internal_helpers_test.rb +29 -8
  80. data/test/controllers/url_helpers_test.rb +2 -1
  81. data/test/devise_test.rb +10 -0
  82. data/test/failure_app_test.rb +86 -22
  83. data/test/generators/active_record_generator_test.rb +24 -0
  84. data/test/generators/devise_generator_test.rb +33 -0
  85. data/test/generators/install_generator_test.rb +13 -0
  86. data/test/generators/mongoid_generator_test.rb +22 -0
  87. data/test/generators/views_generator_test.rb +35 -0
  88. data/test/indifferent_hash.rb +33 -0
  89. data/test/integration/authenticatable_test.rb +165 -62
  90. data/test/integration/database_authenticatable_test.rb +22 -0
  91. data/test/integration/http_authenticatable_test.rb +12 -2
  92. data/test/integration/omniauthable_test.rb +138 -0
  93. data/test/integration/recoverable_test.rb +39 -20
  94. data/test/integration/registerable_test.rb +60 -4
  95. data/test/integration/rememberable_test.rb +72 -29
  96. data/test/integration/timeoutable_test.rb +10 -1
  97. data/test/integration/token_authenticatable_test.rb +55 -6
  98. data/test/mailers/confirmation_instructions_test.rb +4 -0
  99. data/test/mailers/reset_password_instructions_test.rb +4 -0
  100. data/test/mailers/unlock_instructions_test.rb +4 -0
  101. data/test/mapping_test.rb +37 -3
  102. data/test/models/confirmable_test.rb +32 -15
  103. data/test/models/database_authenticatable_test.rb +14 -71
  104. data/test/models/encryptable_test.rb +65 -0
  105. data/test/models/lockable_test.rb +48 -11
  106. data/test/models/recoverable_test.rb +28 -2
  107. data/test/models/rememberable_test.rb +186 -125
  108. data/test/models/token_authenticatable_test.rb +19 -1
  109. data/test/models_test.rb +12 -5
  110. data/test/omniauth/url_helpers_test.rb +54 -0
  111. data/test/orm/mongoid.rb +3 -2
  112. data/test/rails_app/Rakefile +10 -0
  113. data/test/rails_app/app/active_record/admin.rb +4 -1
  114. data/test/rails_app/app/active_record/user.rb +5 -4
  115. data/test/rails_app/app/controllers/{sessions_controller.rb → admins/sessions_controller.rb} +1 -1
  116. data/test/rails_app/app/controllers/application_controller.rb +0 -1
  117. data/test/rails_app/app/controllers/home_controller.rb +9 -0
  118. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +14 -0
  119. data/test/rails_app/app/mongoid/admin.rb +4 -1
  120. data/test/rails_app/app/mongoid/shim.rb +16 -3
  121. data/test/rails_app/app/mongoid/user.rb +5 -5
  122. data/test/rails_app/app/views/admins/index.html.erb +1 -0
  123. data/test/rails_app/app/views/admins/sessions/new.html.erb +2 -0
  124. data/test/rails_app/app/views/home/index.html.erb +1 -0
  125. data/test/rails_app/app/views/home/private.html.erb +1 -0
  126. data/test/rails_app/app/views/layouts/application.html.erb +24 -0
  127. data/test/rails_app/app/views/users/index.html.erb +1 -0
  128. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +1 -0
  129. data/test/rails_app/app/views/users/sessions/new.html.erb +1 -0
  130. data/test/rails_app/config/application.rb +5 -0
  131. data/test/rails_app/config/boot.rb +2 -2
  132. data/test/rails_app/config/database.yml +18 -0
  133. data/test/rails_app/config/initializers/devise.rb +71 -31
  134. data/test/rails_app/config/routes.rb +14 -6
  135. data/test/rails_app/config.ru +4 -0
  136. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +21 -17
  137. data/test/rails_app/db/schema.rb +17 -51
  138. data/test/rails_app/lib/shared_admin.rb +9 -0
  139. data/test/rails_app/lib/shared_user.rb +23 -0
  140. data/test/rails_app/public/404.html +26 -0
  141. data/test/rails_app/public/422.html +26 -0
  142. data/test/rails_app/public/500.html +26 -0
  143. data/test/rails_app/public/favicon.ico +0 -0
  144. data/test/rails_app/script/rails +10 -0
  145. data/test/routes_test.rb +42 -9
  146. data/test/schema_test.rb +33 -0
  147. data/test/support/integration.rb +4 -4
  148. data/test/support/locale/en.yml +4 -0
  149. data/test/support/webrat/integrations/rails.rb +11 -19
  150. data/test/test_helper.rb +8 -2
  151. data/test/test_helpers_test.rb +64 -2
  152. metadata +106 -30
  153. data/TODO +0 -3
  154. data/lib/devise/encryptors/bcrypt.rb +0 -19
  155. data/lib/generators/devise_install_generator.rb +0 -4
  156. data/lib/generators/devise_views_generator.rb +0 -4
  157. data/test/support/test_silencer.rb +0 -5
@@ -7,12 +7,23 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
7
7
  sign_in_as_new_user_with_token
8
8
 
9
9
  assert_response :success
10
- assert_template 'users/index'
10
+ assert_current_url "/users?secret_token=#{VALID_AUTHENTICATION_TOKEN}"
11
11
  assert_contain 'Welcome'
12
12
  assert warden.authenticated?(:user)
13
13
  end
14
14
  end
15
15
 
16
+ test 'authenticate with valid authentication token key but does not store if stateless' do
17
+ swap Devise, :token_authentication_key => :secret_token, :stateless_token => true do
18
+ sign_in_as_new_user_with_token
19
+ assert warden.authenticated?(:user)
20
+
21
+ get users_path
22
+ assert_redirected_to new_user_session_path
23
+ assert_not warden.authenticated?(:user)
24
+ end
25
+ end
26
+
16
27
  test 'authenticate with valid authentication token key and value through http' do
17
28
  swap Devise, :token_authentication_key => :secret_token do
18
29
  sign_in_as_new_user_with_token(:http_auth => true)
@@ -65,15 +76,42 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
65
76
  end
66
77
  end
67
78
 
79
+ test 'authenticate with valid authentication token key and do not store if stateless and timeoutable are enabled' do
80
+ swap Devise, :token_authentication_key => :secret_token, :stateless_token => true, :timeout_in => (0.1).second do
81
+ user = sign_in_as_new_user_with_token
82
+ assert warden.authenticated?(:user)
83
+
84
+ # Expiring does not work because we are setting the session value when accessing it
85
+ sleep 0.3
86
+
87
+ get_users_path_as_existing_user(user)
88
+ assert warden.authenticated?(:user)
89
+ end
90
+ end
91
+
92
+ test 'should not be subject to injection' do
93
+ swap Devise, :token_authentication_key => :secret_token do
94
+ user1 = create_user_with_authentication_token()
95
+
96
+ # Clean up user cache
97
+ @user = nil
98
+
99
+ user2 = create_user_with_authentication_token(:email => "another@test.com")
100
+ user2.update_attribute(:authentication_token, "ANOTHERTOKEN")
101
+
102
+ assert_not_equal user1, user2
103
+ visit users_path(Devise.token_authentication_key.to_s + '[$ne]' => user1.authentication_token)
104
+ assert_nil warden.user(:user)
105
+ end
106
+ end
107
+
68
108
  private
69
109
 
70
110
  def sign_in_as_new_user_with_token(options = {})
71
- options[:auth_token_key] ||= Devise.token_authentication_key
72
- options[:auth_token] ||= VALID_AUTHENTICATION_TOKEN
111
+ user = options.delete(:user) || create_user_with_authentication_token(options)
73
112
 
74
- user = create_user(options)
75
- user.authentication_token = VALID_AUTHENTICATION_TOKEN
76
- user.save
113
+ options[:auth_token_key] ||= Devise.token_authentication_key
114
+ options[:auth_token] ||= user.authentication_token
77
115
 
78
116
  if options[:http_auth]
79
117
  header = "Basic #{ActiveSupport::Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
@@ -85,4 +123,15 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
85
123
  user
86
124
  end
87
125
 
126
+ def create_user_with_authentication_token(options={})
127
+ user = create_user(options)
128
+ user.authentication_token = VALID_AUTHENTICATION_TOKEN
129
+ user.save
130
+ user
131
+ end
132
+
133
+ def get_users_path_as_existing_user(user)
134
+ sign_in_as_new_user_with_token(:user => user)
135
+ end
136
+
88
137
  end
@@ -35,6 +35,10 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
35
35
  assert_equal ['test@example.com'], mail.from
36
36
  end
37
37
 
38
+ test 'setup reply to as copy from sender' do
39
+ assert_equal ['test@example.com'], mail.reply_to
40
+ end
41
+
38
42
  test 'setup subject from I18n' do
39
43
  store_translations :en, :devise => { :mailer => { :confirmation_instructions => { :subject => 'Account Confirmation' } } } do
40
44
  assert_equal 'Account Confirmation', mail.subject
@@ -38,6 +38,10 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
38
38
  assert_equal ['test@example.com'], mail.from
39
39
  end
40
40
 
41
+ test 'setup reply to as copy from sender' do
42
+ assert_equal ['test@example.com'], mail.reply_to
43
+ end
44
+
41
45
  test 'setup subject from I18n' do
42
46
  store_translations :en, :devise => { :mailer => { :reset_password_instructions => { :subject => 'Reset instructions' } } } do
43
47
  assert_equal 'Reset instructions', mail.subject
@@ -38,6 +38,10 @@ class UnlockInstructionsTest < ActionMailer::TestCase
38
38
  assert_equal ['test@example.com'], mail.from
39
39
  end
40
40
 
41
+ test 'setup reply to as copy from sender' do
42
+ assert_equal ['test@example.com'], mail.reply_to
43
+ end
44
+
41
45
  test 'setup subject from I18n' do
42
46
  store_translations :en, :devise => { :mailer => { :unlock_instructions => { :subject => 'Yo unlock instructions' } } } do
43
47
  assert_equal 'Yo unlock instructions', mail.subject
data/test/mapping_test.rb CHANGED
@@ -12,22 +12,42 @@ class MappingTest < ActiveSupport::TestCase
12
12
  mapping = Devise.mappings[:user]
13
13
  assert_equal User, mapping.to
14
14
  assert_equal User.devise_modules, mapping.modules
15
- assert_equal :users, mapping.plural
15
+ assert_equal "users", mapping.scoped_path
16
16
  assert_equal :user, mapping.singular
17
17
  assert_equal "users", mapping.path
18
+ assert_equal "/users", mapping.fullpath
19
+ end
20
+
21
+ test 'store options with namespace' do
22
+ mapping = Devise.mappings[:publisher_account]
23
+ assert_equal Admin, mapping.to
24
+ assert_equal "publisher/accounts", mapping.scoped_path
25
+ assert_equal :publisher_account, mapping.singular
26
+ assert_equal "accounts", mapping.path
27
+ assert_equal "/publisher/accounts", mapping.fullpath
18
28
  end
19
29
 
20
30
  test 'allows path to be given' do
21
31
  assert_equal "admin_area", Devise.mappings[:admin].path
22
32
  end
23
33
 
34
+ test 'sign_out_via defaults to :get' do
35
+ assert_equal :get, Devise.mappings[:user].sign_out_via
36
+ end
37
+
38
+ test 'allows custom sign_out_via to be given' do
39
+ assert_equal :delete, Devise.mappings[:sign_out_via_delete].sign_out_via
40
+ assert_equal :post, Devise.mappings[:sign_out_via_post].sign_out_via
41
+ assert_equal [:delete, :post], Devise.mappings[:sign_out_via_delete_or_post].sign_out_via
42
+ end
43
+
24
44
  test 'allows custom singular to be given' do
25
45
  assert_equal "accounts", Devise.mappings[:manager].path
26
46
  end
27
47
 
28
48
  test 'has strategies depending on the model declaration' do
29
49
  assert_equal [:rememberable, :token_authenticatable, :database_authenticatable], Devise.mappings[:user].strategies
30
- assert_equal [:database_authenticatable], Devise.mappings[:admin].strategies
50
+ assert_equal [:rememberable, :database_authenticatable], Devise.mappings[:admin].strategies
31
51
  end
32
52
 
33
53
  test 'find scope for a given object' do
@@ -80,6 +100,20 @@ class MappingTest < ActiveSupport::TestCase
80
100
  assert mapping.recoverable?
81
101
  assert mapping.lockable?
82
102
  assert_not mapping.confirmable?
83
- assert_not mapping.rememberable?
103
+ assert_not mapping.omniauthable?
84
104
  end
105
+
106
+ test 'find mapping by path' do
107
+ assert_raise RuntimeError do
108
+ Devise::Mapping.find_by_path!('/accounts/facebook/callback')
109
+ end
110
+
111
+ assert_nothing_raised do
112
+ Devise::Mapping.find_by_path!('/:locale/accounts/login')
113
+ end
114
+
115
+ assert_nothing_raised do
116
+ Devise::Mapping.find_by_path!('/accounts/facebook/callback', :path)
117
+ end
118
+ end
85
119
  end
@@ -48,10 +48,10 @@ class ConfirmableTest < ActiveSupport::TestCase
48
48
  assert_blank user.errors[:email]
49
49
 
50
50
  assert_not user.confirm!
51
- assert_equal "was already confirmed", user.errors[:email].join
51
+ assert_equal "was already confirmed, please try signing in", user.errors[:email].join
52
52
  end
53
53
 
54
- test 'should find and confirm an user automatically' do
54
+ test 'should find and confirm a user automatically' do
55
55
  user = create_user
56
56
  confirmed_user = User.confirm_by_token(user.confirmation_token)
57
57
  assert_equal confirmed_user, user
@@ -76,7 +76,7 @@ class ConfirmableTest < ActiveSupport::TestCase
76
76
  user.save
77
77
  confirmed_user = User.confirm_by_token(user.confirmation_token)
78
78
  assert confirmed_user.confirmed?
79
- assert_equal "was already confirmed", confirmed_user.errors[:email].join
79
+ assert_equal "was already confirmed, please try signing in", confirmed_user.errors[:email].join
80
80
  end
81
81
 
82
82
  test 'should send confirmation instructions by email' do
@@ -127,7 +127,7 @@ class ConfirmableTest < ActiveSupport::TestCase
127
127
  User.send_confirmation_instructions(:email => user.email)
128
128
  end
129
129
  end
130
-
130
+
131
131
  test 'should always have confirmation token when email is sent' do
132
132
  user = new_user
133
133
  user.instance_eval { def confirmation_required?; false end }
@@ -160,17 +160,17 @@ class ConfirmableTest < ActiveSupport::TestCase
160
160
  user.confirm!
161
161
  assert_not user.resend_confirmation_token
162
162
  assert user.confirmed?
163
- assert_equal 'was already confirmed', user.errors[:email].join
163
+ assert_equal 'was already confirmed, please try signing in', user.errors[:email].join
164
164
  end
165
165
 
166
166
  test 'confirm time should fallback to devise confirm in default configuration' do
167
167
  swap Devise, :confirm_within => 1.day do
168
168
  user = new_user
169
169
  user.confirmation_sent_at = 2.days.ago
170
- assert_not user.active?
170
+ assert_not user.active_for_authentication?
171
171
 
172
172
  Devise.confirm_within = 3.days
173
- assert user.active?
173
+ assert user.active_for_authentication?
174
174
  end
175
175
  end
176
176
 
@@ -180,42 +180,59 @@ class ConfirmableTest < ActiveSupport::TestCase
180
180
  user = create_user
181
181
 
182
182
  user.confirmation_sent_at = 4.days.ago
183
- assert user.active?
183
+ assert user.active_for_authentication?
184
184
 
185
185
  user.confirmation_sent_at = 5.days.ago
186
- assert_not user.active?
186
+ assert_not user.active_for_authentication?
187
187
  end
188
188
  end
189
189
 
190
190
  test 'should be active when already confirmed' do
191
191
  user = create_user
192
192
  assert_not user.confirmed?
193
- assert_not user.active?
193
+ assert_not user.active_for_authentication?
194
194
 
195
195
  user.confirm!
196
196
  assert user.confirmed?
197
- assert user.active?
197
+ assert user.active_for_authentication?
198
198
  end
199
199
 
200
200
  test 'should not be active when confirm in is zero' do
201
201
  Devise.confirm_within = 0.days
202
202
  user = create_user
203
203
  user.confirmation_sent_at = Date.today
204
- assert_not user.active?
204
+ assert_not user.active_for_authentication?
205
205
  end
206
206
 
207
207
  test 'should not be active without confirmation' do
208
208
  user = create_user
209
209
  user.confirmation_sent_at = nil
210
210
  user.save
211
- assert_not user.reload.active?
211
+ assert_not user.reload.active_for_authentication?
212
212
  end
213
-
213
+
214
214
  test 'should be active without confirmation when confirmation is not required' do
215
215
  user = create_user
216
216
  user.instance_eval { def confirmation_required?; false end }
217
217
  user.confirmation_sent_at = nil
218
218
  user.save
219
- assert user.reload.active?
219
+ assert user.reload.active_for_authentication?
220
+ end
221
+
222
+ test 'should find a user to send email instructions for the user confirm it\'s email by authentication_keys' do
223
+ swap Devise, :authentication_keys => [:username, :email] do
224
+ user = create_user
225
+ confirm_user = User.send_confirmation_instructions(:email => user.email, :username => user.username)
226
+ assert_equal confirm_user, user
227
+ end
228
+ end
229
+
230
+ test 'should require all confirmation_keys' do
231
+ swap Devise, :confirmation_keys => [:username, :email] do
232
+ user = create_user
233
+ confirm_user = User.send_confirmation_instructions(:email => user.email)
234
+ assert_not confirm_user.persisted?
235
+ assert_equal "can't be blank", confirm_user.errors[:username].join
236
+ end
220
237
  end
221
238
  end
@@ -2,53 +2,31 @@ require 'test_helper'
2
2
  require 'digest/sha1'
3
3
 
4
4
  class DatabaseAuthenticatableTest < ActiveSupport::TestCase
5
-
6
- def encrypt_password(user, pepper=User.pepper, stretches=User.stretches, encryptor=User.encryptor_class)
7
- encryptor.digest('123456', stretches, user.password_salt, pepper)
8
- end
9
-
10
- def swap_with_encryptor(klass, encryptor, options={})
11
- klass.instance_variable_set(:@encryptor_class, nil)
12
-
13
- swap klass, options.merge(:encryptor => encryptor) do
14
- begin
15
- yield
16
- ensure
17
- klass.instance_variable_set(:@encryptor_class, nil)
18
- end
19
- end
5
+ test 'should downcase case insensitive keys when saving' do
6
+ # case_insensitive_keys is set to :email by default.
7
+ email = 'Foo@Bar.com'
8
+ user = new_user(:email => email)
9
+
10
+ assert_equal email, user.email
11
+ user.save!
12
+ assert_equal email.downcase, user.email
20
13
  end
21
-
14
+
22
15
  test 'should respond to password and password confirmation' do
23
16
  user = new_user
24
17
  assert user.respond_to?(:password)
25
18
  assert user.respond_to?(:password_confirmation)
26
19
  end
27
20
 
28
- test 'should generate encrypted password and salt while setting password' do
21
+ test 'should generate encrypted password while setting password' do
29
22
  user = new_user
30
- assert_present user.password_salt
31
23
  assert_present user.encrypted_password
32
24
  end
33
25
 
34
- test 'should not change password salt when updating' do
35
- user = create_user
36
- salt = user.password_salt
37
- user.expects(:password_salt=).never
38
- user.save!
39
- assert_equal salt, user.password_salt
40
- end
41
-
42
- test 'should generate a base64 hash using SecureRandom for password salt' do
43
- swap_with_encryptor User, :sha1 do
44
- ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
45
- assert_equal 'friendly_token', new_user.password_salt
46
- end
47
- end
48
-
49
- test 'should not generate salt if password is blank' do
50
- assert_blank new_user(:password => nil).password_salt
51
- assert_blank new_user(:password => '').password_salt
26
+ test 'allow authenticatable_salt to work even with nil encrypted password' do
27
+ user = User.new
28
+ user.encrypted_password = nil
29
+ assert_nil user.authenticatable_salt
52
30
  end
53
31
 
54
32
  test 'should not generate encrypted password if password is blank' do
@@ -64,47 +42,12 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
64
42
  assert_not_equal encrypted_password, user.encrypted_password
65
43
  end
66
44
 
67
- test 'should fallback to sha1 as default encryption' do
68
- user = new_user
69
- assert_equal encrypt_password(user), user.encrypted_password
70
- end
71
-
72
- test 'should fallback to devise pepper default configuration' do
73
- begin
74
- Devise.pepper = ''
75
- user = new_user
76
- assert_equal encrypt_password(user), user.encrypted_password
77
- assert_not_equal encrypt_password(user, 'another_pepper'), user.encrypted_password
78
-
79
- Devise.pepper = 'new_pepper'
80
- user = new_user
81
- assert_equal encrypt_password(user, 'new_pepper'), user.encrypted_password
82
- assert_not_equal encrypt_password(user, 'another_pepper'), user.encrypted_password
83
- ensure
84
- Devise.pepper = nil
85
- end
86
- end
87
-
88
- test 'should respect encryptor configuration' do
89
- swap_with_encryptor User, :sha512 do
90
- user = create_user
91
- assert_equal user.encrypted_password, encrypt_password(user, User.pepper, User.stretches, ::Devise::Encryptors::Sha512)
92
- end
93
- end
94
-
95
45
  test 'should test for a valid password' do
96
46
  user = create_user
97
47
  assert user.valid_password?('123456')
98
48
  assert_not user.valid_password?('654321')
99
49
  end
100
50
 
101
- test 'should not validate password when salt is nil' do
102
- admin = create_admin
103
- admin.password_salt = nil
104
- admin.save
105
- assert_not admin.valid_password?('123456')
106
- end
107
-
108
51
  test 'should respond to current password' do
109
52
  assert new_user.respond_to?(:current_password)
110
53
  end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ class EncryptableTest < ActiveSupport::TestCase
4
+ def encrypt_password(admin, pepper=Admin.pepper, stretches=Admin.stretches, encryptor=Admin.encryptor_class)
5
+ encryptor.digest('123456', stretches, admin.password_salt, pepper)
6
+ end
7
+
8
+ def swap_with_encryptor(klass, encryptor, options={})
9
+ klass.instance_variable_set(:@encryptor_class, nil)
10
+
11
+ swap klass, options.merge(:encryptor => encryptor) do
12
+ begin
13
+ yield
14
+ ensure
15
+ klass.instance_variable_set(:@encryptor_class, nil)
16
+ end
17
+ end
18
+ end
19
+
20
+ test 'should generate salt while setting password' do
21
+ assert_present create_admin.password_salt
22
+ end
23
+
24
+ test 'should not change password salt when updating' do
25
+ admin = create_admin
26
+ salt = admin.password_salt
27
+ admin.expects(:password_salt=).never
28
+ admin.save!
29
+ assert_equal salt, admin.password_salt
30
+ end
31
+
32
+ test 'should generate a base64 hash using SecureRandom for password salt' do
33
+ swap_with_encryptor Admin, :sha1 do
34
+ ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
35
+ assert_equal 'friendly_token', create_admin.password_salt
36
+ end
37
+ end
38
+
39
+ test 'should not generate salt if password is blank' do
40
+ assert_blank create_admin(:password => nil).password_salt
41
+ assert_blank create_admin(:password => '').password_salt
42
+ end
43
+
44
+ test 'should encrypt password again if password has changed' do
45
+ admin = create_admin
46
+ encrypted_password = admin.encrypted_password
47
+ admin.password = admin.password_confirmation = 'new_password'
48
+ admin.save!
49
+ assert_not_equal encrypted_password, admin.encrypted_password
50
+ end
51
+
52
+ test 'should respect encryptor configuration' do
53
+ swap_with_encryptor Admin, :sha512 do
54
+ admin = create_admin
55
+ assert_equal admin.encrypted_password, encrypt_password(admin, Admin.pepper, Admin.stretches, ::Devise::Encryptors::Sha512)
56
+ end
57
+ end
58
+
59
+ test 'should not validate password when salt is nil' do
60
+ admin = create_admin
61
+ admin.password_salt = nil
62
+ admin.save
63
+ assert_not admin.valid_password?('123456')
64
+ end
65
+ end
@@ -47,15 +47,15 @@ class LockableTest < ActiveSupport::TestCase
47
47
  assert user.access_locked?
48
48
  end
49
49
 
50
- test "active? should be the opposite of locked?" do
50
+ test "active_for_authentication? should be the opposite of locked?" do
51
51
  user = create_user
52
52
  user.confirm!
53
- assert user.active?
53
+ assert user.active_for_authentication?
54
54
  user.lock_access!
55
- assert_not user.active?
55
+ assert_not user.active_for_authentication?
56
56
  end
57
57
 
58
- test "should unlock an user by cleaning locked_at, falied_attempts and unlock_token" do
58
+ test "should unlock a user by cleaning locked_at, falied_attempts and unlock_token" do
59
59
  user = create_user
60
60
  user.lock_access!
61
61
  assert_not_nil user.reload.locked_at
@@ -67,12 +67,6 @@ class LockableTest < ActiveSupport::TestCase
67
67
  assert_equal 0, user.reload.failed_attempts
68
68
  end
69
69
 
70
- test 'should not unlock an unlocked user' do
71
- user = create_user
72
- assert_not user.unlock_access!
73
- assert_match "was not locked", user.errors[:email].join
74
- end
75
-
76
70
  test "new user should not be locked and should have zero failed_attempts" do
77
71
  assert_not new_user.access_locked?
78
72
  assert_equal 0, create_user.failed_attempts
@@ -141,7 +135,7 @@ class LockableTest < ActiveSupport::TestCase
141
135
  end
142
136
  end
143
137
 
144
- test 'should find and unlock an user automatically' do
138
+ test 'should find and unlock a user automatically' do
145
139
  user = create_user
146
140
  user.lock_access!
147
141
  locked_user = User.unlock_access_by_token(user.unlock_token)
@@ -178,6 +172,23 @@ class LockableTest < ActiveSupport::TestCase
178
172
  assert_equal 'not found', unlock_user.errors[:email].join
179
173
  end
180
174
 
175
+ test 'should find a user to send unlock instructions by authentication_keys' do
176
+ swap Devise, :authentication_keys => [:username, :email] do
177
+ user = create_user
178
+ unlock_user = User.send_unlock_instructions(:email => user.email, :username => user.username)
179
+ assert_equal unlock_user, user
180
+ end
181
+ end
182
+
183
+ test 'should require all unlock_keys' do
184
+ swap Devise, :unlock_keys => [:username, :email] do
185
+ user = create_user
186
+ unlock_user = User.send_unlock_instructions(:email => user.email)
187
+ assert_not unlock_user.persisted?
188
+ assert_equal "can't be blank", unlock_user.errors[:username].join
189
+ end
190
+ end
191
+
181
192
  test 'should not be able to send instructions if the user is not locked' do
182
193
  user = create_user
183
194
  assert_not user.resend_unlock_token
@@ -185,4 +196,30 @@ class LockableTest < ActiveSupport::TestCase
185
196
  assert_equal 'was not locked', user.errors[:email].join
186
197
  end
187
198
 
199
+ test 'should unlock account if lock has expired and increase attempts on failure' do
200
+ swap Devise, :unlock_in => 1.minute do
201
+ user = create_user
202
+ user.confirm!
203
+
204
+ user.failed_attempts = 2
205
+ user.locked_at = 2.minutes.ago
206
+
207
+ user.valid_for_authentication? { false }
208
+ assert_equal 1, user.failed_attempts
209
+ end
210
+ end
211
+
212
+ test 'should unlock account if lock has expired on success' do
213
+ swap Devise, :unlock_in => 1.minute do
214
+ user = create_user
215
+ user.confirm!
216
+
217
+ user.failed_attempts = 2
218
+ user.locked_at = 2.minutes.ago
219
+
220
+ user.valid_for_authentication? { true }
221
+ assert_equal 0, user.failed_attempts
222
+ assert_nil user.locked_at
223
+ end
224
+ end
188
225
  end
@@ -86,6 +86,23 @@ class RecoverableTest < ActiveSupport::TestCase
86
86
  assert_equal "not found", reset_password_user.errors[:email].join
87
87
  end
88
88
 
89
+ test 'should find a user to send instructions by authentication_keys' do
90
+ swap Devise, :authentication_keys => [:username, :email] do
91
+ user = create_user
92
+ reset_password_user = User.send_reset_password_instructions(:email => user.email, :username => user.username)
93
+ assert_equal reset_password_user, user
94
+ end
95
+ end
96
+
97
+ test 'should require all reset_password_keys' do
98
+ swap Devise, :reset_password_keys => [:username, :email] do
99
+ user = create_user
100
+ reset_password_user = User.send_reset_password_instructions(:email => user.email)
101
+ assert_not reset_password_user.persisted?
102
+ assert_equal "can't be blank", reset_password_user.errors[:username].join
103
+ end
104
+ end
105
+
89
106
  test 'should reset reset_password_token before send the reset instructions email' do
90
107
  user = create_user
91
108
  token = user.reset_password_token
@@ -108,18 +125,27 @@ class RecoverableTest < ActiveSupport::TestCase
108
125
  assert_equal reset_password_user, user
109
126
  end
110
127
 
111
- test 'should a new record with errors if no reset_password_token is found' do
128
+ test 'should return a new record with errors if no reset_password_token is found' do
112
129
  reset_password_user = User.reset_password_by_token(:reset_password_token => 'invalid_token')
113
130
  assert_not reset_password_user.persisted?
114
131
  assert_equal "is invalid", reset_password_user.errors[:reset_password_token].join
115
132
  end
116
133
 
117
- test 'should a new record with errors if reset_password_token is blank' do
134
+ test 'should return a new record with errors if reset_password_token is blank' do
118
135
  reset_password_user = User.reset_password_by_token(:reset_password_token => '')
119
136
  assert_not reset_password_user.persisted?
120
137
  assert_match "can't be blank", reset_password_user.errors[:reset_password_token].join
121
138
  end
122
139
 
140
+ test 'should return a new record with errors if password is blank' do
141
+ user = create_user
142
+ user.send :generate_reset_password_token!
143
+
144
+ reset_password_user = User.reset_password_by_token(:reset_password_token => user.reset_password_token, :password => '')
145
+ assert_not reset_password_user.errors.empty?
146
+ assert_match "can't be blank", reset_password_user.errors[:password].join
147
+ end
148
+
123
149
  test 'should reset successfully user password given the new password and confirmation' do
124
150
  user = create_user
125
151
  old_password = user.password