sorcery 0.5.21 → 0.5.30

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sorcery might be problematic. Click here for more details.

Files changed (54) hide show
  1. data/README.rdoc +1 -1
  2. data/VERSION +1 -1
  3. data/lib/sorcery/controller.rb +5 -3
  4. data/lib/sorcery/controller/submodules/activity_logging.rb +10 -6
  5. data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -3
  6. data/lib/sorcery/controller/submodules/http_basic_auth.rb +10 -5
  7. data/lib/sorcery/controller/submodules/remember_me.rb +13 -4
  8. data/lib/sorcery/controller/submodules/session_timeout.rb +3 -1
  9. data/lib/sorcery/crypto_providers/aes256.rb +8 -5
  10. data/lib/sorcery/crypto_providers/bcrypt.rb +12 -6
  11. data/lib/sorcery/crypto_providers/sha256.rb +2 -1
  12. data/lib/sorcery/crypto_providers/sha512.rb +2 -1
  13. data/lib/sorcery/initializers/initializer.rb +125 -36
  14. data/lib/sorcery/model.rb +28 -15
  15. data/lib/sorcery/model/adapters/active_record.rb +2 -2
  16. data/lib/sorcery/model/adapters/mongoid.rb +2 -2
  17. data/lib/sorcery/model/submodules/activity_logging.rb +7 -6
  18. data/lib/sorcery/model/submodules/brute_force_protection.rb +10 -6
  19. data/lib/sorcery/model/submodules/external.rb +4 -2
  20. data/lib/sorcery/model/submodules/remember_me.rb +4 -3
  21. data/lib/sorcery/model/submodules/reset_password.rb +16 -8
  22. data/lib/sorcery/model/submodules/user_activation.rb +23 -10
  23. data/lib/sorcery/model/temporary_token.rb +3 -2
  24. data/lib/sorcery/test_helpers/internal.rb +2 -1
  25. data/lib/sorcery/test_helpers/internal/rails.rb +5 -1
  26. data/sorcery.gemspec +16 -2
  27. data/spec/Gemfile.lock +1 -1
  28. data/spec/rails3/Gemfile.lock +1 -1
  29. data/spec/rails3/spec/user_activation_spec.rb +2 -168
  30. data/spec/rails3/spec/user_activity_logging_spec.rb +2 -30
  31. data/spec/rails3/spec/user_brute_force_protection_spec.rb +2 -35
  32. data/spec/rails3/spec/user_oauth_spec.rb +2 -26
  33. data/spec/rails3/spec/user_remember_me_spec.rb +2 -45
  34. data/spec/rails3/spec/user_reset_password_spec.rb +3 -168
  35. data/spec/rails3/spec/user_spec.rb +3 -283
  36. data/spec/rails3_mongoid/Gemfile.lock +1 -1
  37. data/spec/rails3_mongoid/app/models/authentication.rb +3 -3
  38. data/spec/rails3_mongoid/spec/user_activation_spec.rb +2 -171
  39. data/spec/rails3_mongoid/spec/user_activity_logging_spec.rb +2 -25
  40. data/spec/rails3_mongoid/spec/user_brute_force_protection_spec.rb +2 -35
  41. data/spec/rails3_mongoid/spec/user_oauth_spec.rb +2 -28
  42. data/spec/rails3_mongoid/spec/user_remember_me_spec.rb +2 -45
  43. data/spec/rails3_mongoid/spec/user_reset_password_spec.rb +2 -176
  44. data/spec/rails3_mongoid/spec/user_spec.rb +3 -285
  45. data/spec/shared_examples/user_activation_shared_examples.rb +173 -0
  46. data/spec/shared_examples/user_activity_logging_shared_examples.rb +27 -0
  47. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +37 -0
  48. data/spec/shared_examples/user_oauth_shared_examples.rb +30 -0
  49. data/spec/shared_examples/user_remember_me_shared_examples.rb +47 -0
  50. data/spec/shared_examples/user_reset_password_shared_examples.rb +177 -0
  51. data/spec/shared_examples/user_shared_examples.rb +292 -0
  52. data/spec/sinatra/Gemfile.lock +1 -1
  53. data/spec/sinatra_modular/Gemfile.lock +1 -1
  54. metadata +16 -2
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../app/mailers/sorcery_mailer')
3
+ require File.expand_path(File.dirname(__FILE__) + '/../../shared_examples/user_shared_examples')
3
4
 
4
5
  describe "User with no submodules (core)" do
5
6
  before(:all) do
@@ -13,296 +14,13 @@ describe "User with no submodules (core)" do
13
14
  end
14
15
 
15
16
  # ----------------- PLUGIN CONFIGURATION -----------------------
16
- describe User, "loaded plugin configuration" do
17
- after(:each) do
18
- User.sorcery_config.reset!
19
- end
20
-
21
- it "should enable configuration option 'username_attribute_name'" do
22
- sorcery_model_property_set(:username_attribute_name, :email)
23
- User.sorcery_config.username_attribute_name.should equal(:email)
24
- end
25
-
26
- it "should enable configuration option 'password_attribute_name'" do
27
- sorcery_model_property_set(:password_attribute_name, :mypassword)
28
- User.sorcery_config.password_attribute_name.should equal(:mypassword)
29
- end
30
-
31
- it "should enable configuration option 'email_attribute_name'" do
32
- sorcery_model_property_set(:email_attribute_name, :my_email)
33
- User.sorcery_config.email_attribute_name.should equal(:my_email)
34
- end
35
-
36
- it "should enable configuration option 'crypted_password_attribute_name'" do
37
- sorcery_model_property_set(:crypted_password_attribute_name, :password)
38
- User.sorcery_config.crypted_password_attribute_name.should equal(:password)
39
- end
40
-
41
- it "should enable configuration option 'salt_attribute_name'" do
42
- sorcery_model_property_set(:salt_attribute_name, :my_salt)
43
- User.sorcery_config.salt_attribute_name.should equal(:my_salt)
44
- end
45
-
46
- it "should enable configuration option 'encryption_algorithm'" do
47
- sorcery_model_property_set(:encryption_algorithm, :none)
48
- User.sorcery_config.encryption_algorithm.should equal(:none)
49
- end
50
-
51
- it "should enable configuration option 'encryption_key'" do
52
- sorcery_model_property_set(:encryption_key, 'asdadas424234242')
53
- User.sorcery_config.encryption_key.should == 'asdadas424234242'
54
- end
55
-
56
- it "should enable configuration option 'custom_encryption_provider'" do
57
- sorcery_model_property_set(:encryption_algorithm, :custom)
58
- sorcery_model_property_set(:custom_encryption_provider, Array)
59
- User.sorcery_config.custom_encryption_provider.should equal(Array)
60
- end
61
-
62
- it "should enable configuration option 'salt_join_token'" do
63
- salt_join_token = "--%%*&-"
64
- sorcery_model_property_set(:salt_join_token, salt_join_token)
65
- User.sorcery_config.salt_join_token.should equal(salt_join_token)
66
- end
67
-
68
- it "should enable configuration option 'stretches'" do
69
- stretches = 15
70
- sorcery_model_property_set(:stretches, stretches)
71
- User.sorcery_config.stretches.should equal(stretches)
72
- end
73
-
74
- end
75
-
76
- # ----------------- PLUGIN ACTIVATED -----------------------
77
- describe User, "when activated with sorcery" do
78
- before(:all) do
79
- sorcery_reload!()
80
- end
81
-
82
- before(:each) do
83
- User.delete_all
84
- end
85
-
86
- it "should respond to class method authenticate" do
87
- User.should respond_to(:authenticate)
88
- end
89
-
90
- it "authenticate should return true if credentials are good" do
91
- create_new_user
92
- User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
93
- end
94
-
95
- it "authenticate should return false if credentials are bad" do
96
- create_new_user
97
- User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'wrong!').should be_false
98
- end
99
-
100
- specify { User.should respond_to(:encrypt) }
101
-
102
- it "subclass should inherit config if defined so" do
103
- sorcery_reload!([],{:subclasses_inherit_config => true})
104
- class Admin < User
105
- end
106
- Admin.sorcery_config.should_not be_nil
107
- Admin.sorcery_config.should == User.sorcery_config
108
- end
109
-
110
- it "subclass should not inherit config if not defined so" do
111
- sorcery_reload!([],{:subclasses_inherit_config => false})
112
- class Admin2 < User
113
- end
114
- Admin2.sorcery_config.should be_nil
115
- end
116
- end
117
-
118
- # ----------------- REGISTRATION -----------------------
119
- describe User, "registration" do
120
-
121
- before(:all) do
122
- sorcery_reload!()
123
- end
124
-
125
- before(:each) do
126
- User.delete_all
127
- end
128
-
129
- it "by default, encryption_provider should not be nil" do
130
- User.sorcery_config.encryption_provider.should_not be_nil
131
- end
132
-
133
- it "should encrypt password when a new user is saved" do
134
- create_new_user
135
- User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true
136
- end
137
-
138
- it "should clear the virtual password field if the encryption process worked" do
139
- create_new_user
140
- @user.password.should be_nil
141
- end
142
-
143
- it "should not clear the virtual password field if save failed due to validity" do
144
- create_new_user
145
- User.class_eval do
146
- validates_format_of :email, :with => /^(.)+@(.)+$/, :if => Proc.new {|r| r.email}, :message => "is invalid"
147
- end
148
- @user.password = 'blupush'
149
- @user.email = 'asd'
150
- @user.save
151
- @user.password.should_not be_nil
152
- end
153
-
154
- it "should not clear the virtual password field if save failed due to exception" do
155
- create_new_user
156
- @user.password = '4blupush'
157
- @user.username = nil
158
- User.class_eval do
159
- validates_presence_of :username
160
- end
161
- begin
162
- @user.save! # triggers validation exception since username field is required.
163
- rescue
164
- end
165
- @user.password.should_not be_nil
166
- end
167
-
168
- it "should not encrypt the password twice when a user is updated" do
169
- create_new_user
170
- @user.email = "blup@bla.com"
171
- @user.save!
172
- User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true
173
- end
174
-
175
- it "should replace the crypted_password in case a new password is set" do
176
- create_new_user
177
- @user.password = 'new_secret'
178
- @user.save!
179
- User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_false
180
- end
181
-
182
- end
183
-
184
- # ----------------- PASSWORD ENCRYPTION -----------------------
185
- describe User, "special encryption cases" do
186
- before(:all) do
187
-
188
- @text = "Some Text!"
189
- end
190
-
191
- before(:each) do
192
- User.delete_all
193
- sorcery_reload!()
194
- end
195
-
196
- after(:each) do
197
- User.sorcery_config.reset!
198
- end
199
-
200
- it "should work with no password encryption" do
201
- sorcery_model_property_set(:encryption_algorithm, :none)
202
- create_new_user
203
- User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
204
- end
205
-
206
- it "should work with custom password encryption" do
207
- class MyCrypto
208
- def self.encrypt(*tokens)
209
- tokens.flatten.compact.join('').gsub(/e/,'A')
210
- end
211
-
212
- def self.matches?(crypted,*tokens)
213
- crypted == encrypt(*tokens)
214
- end
215
- end
216
- sorcery_model_property_set(:encryption_algorithm, :custom)
217
- sorcery_model_property_set(:custom_encryption_provider, MyCrypto)
218
- create_new_user
219
- User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
220
- end
221
-
222
- it "if encryption algo is aes256, it should set key to crypto provider" do
223
- sorcery_model_property_set(:encryption_algorithm, :aes256)
224
- sorcery_model_property_set(:encryption_key, nil)
225
- expect{User.encrypt(@text)}.to raise_error(ArgumentError)
226
- sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343")
227
- expect{User.encrypt(@text)}.to_not raise_error(ArgumentError)
228
- end
229
-
230
- it "if encryption algo is aes256, it should set key to crypto provider, even if attributes are set in reverse" do
231
- sorcery_model_property_set(:encryption_key, nil)
232
- sorcery_model_property_set(:encryption_algorithm, :none)
233
- sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343")
234
- sorcery_model_property_set(:encryption_algorithm, :aes256)
235
- expect{User.encrypt(@text)}.to_not raise_error(ArgumentError)
236
- end
237
-
238
- it "if encryption algo is md5 it should work" do
239
- sorcery_model_property_set(:encryption_algorithm, :md5)
240
- User.encrypt(@text).should == Sorcery::CryptoProviders::MD5.encrypt(@text)
241
- end
242
-
243
- it "if encryption algo is sha1 it should work" do
244
- sorcery_model_property_set(:encryption_algorithm, :sha1)
245
- User.encrypt(@text).should == Sorcery::CryptoProviders::SHA1.encrypt(@text)
246
- end
247
-
248
- it "if encryption algo is sha256 it should work" do
249
- sorcery_model_property_set(:encryption_algorithm, :sha256)
250
- User.encrypt(@text).should == Sorcery::CryptoProviders::SHA256.encrypt(@text)
251
- end
252
-
253
- it "if encryption algo is sha512 it should work" do
254
- sorcery_model_property_set(:encryption_algorithm, :sha512)
255
- User.encrypt(@text).should == Sorcery::CryptoProviders::SHA512.encrypt(@text)
256
- end
257
17
 
258
- it "salt should be random for each user and saved in db" do
259
- sorcery_model_property_set(:salt_attribute_name, :salt)
260
- create_new_user
261
- @user.salt.should_not be_nil
262
- end
263
-
264
- it "if salt is set should use it to encrypt" do
265
- sorcery_model_property_set(:salt_attribute_name, :salt)
266
- sorcery_model_property_set(:encryption_algorithm, :sha512)
267
- create_new_user
268
- @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
269
- @user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
270
- end
271
-
272
- it "if salt_join_token is set should use it to encrypt" do
273
- sorcery_model_property_set(:salt_attribute_name, :salt)
274
- sorcery_model_property_set(:salt_join_token, "-@=>")
275
- sorcery_model_property_set(:encryption_algorithm, :sha512)
276
- create_new_user
277
- @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
278
- Sorcery::CryptoProviders::SHA512.join_token = ""
279
- @user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
280
- Sorcery::CryptoProviders::SHA512.join_token = User.sorcery_config.salt_join_token
281
- @user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
282
- end
283
-
284
- end
18
+ it_should_behave_like "rails_3_core_model"
285
19
 
286
20
  describe User, "external users" do
287
21
 
288
- before(:each) do
289
- User.delete_all
290
- end
291
-
292
- it "should respond to 'external?'" do
293
- create_new_user
294
- @user.should respond_to(:external?)
295
- end
22
+ it_should_behave_like "external_user"
296
23
 
297
- it "external? should be false for regular users" do
298
- create_new_user
299
- @user.external?.should be_false
300
- end
301
-
302
- it "external? should be true for external users" do
303
- create_new_external_user(:twitter)
304
- @user.external?.should be_true
305
- end
306
24
  end
307
25
 
308
26
  describe User, "when inherited" do
@@ -0,0 +1,173 @@
1
+ shared_examples_for "rails_3_activation_model" do
2
+ # ----------------- PLUGIN CONFIGURATION -----------------------
3
+ describe User, "loaded plugin configuration" do
4
+ before(:all) do
5
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
6
+ end
7
+
8
+ after(:each) do
9
+ User.sorcery_config.reset!
10
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
11
+ end
12
+
13
+ it "should enable configuration option 'activation_state_attribute_name'" do
14
+ sorcery_model_property_set(:activation_state_attribute_name, :status)
15
+ User.sorcery_config.activation_state_attribute_name.should equal(:status)
16
+ end
17
+
18
+ it "should enable configuration option 'activation_token_attribute_name'" do
19
+ sorcery_model_property_set(:activation_token_attribute_name, :code)
20
+ User.sorcery_config.activation_token_attribute_name.should equal(:code)
21
+ end
22
+
23
+ it "should enable configuration option 'user_activation_mailer'" do
24
+ sorcery_model_property_set(:user_activation_mailer, TestMailer)
25
+ User.sorcery_config.user_activation_mailer.should equal(TestMailer)
26
+ end
27
+
28
+ it "should enable configuration option 'activation_needed_email_method_name'" do
29
+ sorcery_model_property_set(:activation_needed_email_method_name, :my_activation_email)
30
+ User.sorcery_config.activation_needed_email_method_name.should equal(:my_activation_email)
31
+ end
32
+
33
+ it "should enable configuration option 'activation_success_email_method_name'" do
34
+ sorcery_model_property_set(:activation_success_email_method_name, :my_activation_email)
35
+ User.sorcery_config.activation_success_email_method_name.should equal(:my_activation_email)
36
+ end
37
+
38
+ it "if mailer is nil on activation, throw exception!" do
39
+ expect{sorcery_reload!([:user_activation])}.to raise_error(ArgumentError)
40
+ end
41
+ end
42
+
43
+ # ----------------- ACTIVATION PROCESS -----------------------
44
+ describe User, "activation process" do
45
+ before(:all) do
46
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
47
+ end
48
+
49
+ before(:each) do
50
+ create_new_user
51
+ end
52
+
53
+ it "should initialize user state to 'pending'" do
54
+ @user.activation_state.should == "pending"
55
+ end
56
+
57
+ specify { @user.should respond_to(:activate!) }
58
+
59
+ it "should clear activation code and change state to 'active' on activation" do
60
+ activation_token = @user.activation_token
61
+ @user.activate!
62
+ @user2 = User.find(@user.id) # go to db to make sure it was saved and not just in memory
63
+ @user2.activation_token.should be_nil
64
+ @user2.activation_state.should == "active"
65
+ User.find_by_activation_token(activation_token).should be_nil
66
+ end
67
+
68
+ it "should send the user an activation email" do
69
+ old_size = ActionMailer::Base.deliveries.size
70
+ create_new_user
71
+ ActionMailer::Base.deliveries.size.should == old_size + 1
72
+ end
73
+
74
+ it "subsequent saves do not send activation email" do
75
+ old_size = ActionMailer::Base.deliveries.size
76
+ @user.username = "Shauli"
77
+ @user.save!
78
+ ActionMailer::Base.deliveries.size.should == old_size
79
+ end
80
+
81
+ it "should send the user an activation success email on successful activation" do
82
+ old_size = ActionMailer::Base.deliveries.size
83
+ @user.activate!
84
+ ActionMailer::Base.deliveries.size.should == old_size + 1
85
+ end
86
+
87
+ it "subsequent saves do not send activation success email" do
88
+ @user.activate!
89
+ old_size = ActionMailer::Base.deliveries.size
90
+ @user.username = "Shauli"
91
+ @user.save!
92
+ ActionMailer::Base.deliveries.size.should == old_size
93
+ end
94
+
95
+ it "activation needed email is optional" do
96
+ sorcery_model_property_set(:activation_needed_email_method_name, nil)
97
+ old_size = ActionMailer::Base.deliveries.size
98
+ create_new_user
99
+ ActionMailer::Base.deliveries.size.should == old_size
100
+ end
101
+
102
+ it "activation success email is optional" do
103
+ sorcery_model_property_set(:activation_success_email_method_name, nil)
104
+ old_size = ActionMailer::Base.deliveries.size
105
+ @user.activate!
106
+ ActionMailer::Base.deliveries.size.should == old_size
107
+ end
108
+ end
109
+
110
+ describe User, "prevent non-active login feature" do
111
+ before(:all) do
112
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
113
+ end
114
+
115
+ before(:each) do
116
+ User.delete_all
117
+ create_new_user
118
+ end
119
+
120
+ it "should not allow a non-active user to authenticate" do
121
+ User.authenticate(@user.username,'secret').should be_false
122
+ end
123
+
124
+ it "should allow a non-active user to authenticate if configured so" do
125
+ sorcery_model_property_set(:prevent_non_active_users_to_login, false)
126
+ User.authenticate(@user.username,'secret').should be_true
127
+ end
128
+ end
129
+
130
+ describe User, "load_from_activation_token" do
131
+ before(:all) do
132
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
133
+ end
134
+
135
+ after(:each) do
136
+ Timecop.return
137
+ end
138
+
139
+ it "load_from_activation_token should return user when token is found" do
140
+ create_new_user
141
+ User.load_from_activation_token(@user.activation_token).should == @user
142
+ end
143
+
144
+ it "load_from_activation_token should NOT return user when token is NOT found" do
145
+ create_new_user
146
+ User.load_from_activation_token("a").should == nil
147
+ end
148
+
149
+ it "load_from_activation_token should return user when token is found and not expired" do
150
+ sorcery_model_property_set(:activation_token_expiration_period, 500)
151
+ create_new_user
152
+ User.load_from_activation_token(@user.activation_token).should == @user
153
+ end
154
+
155
+ it "load_from_activation_token should NOT return user when token is found and expired" do
156
+ sorcery_model_property_set(:activation_token_expiration_period, 0.1)
157
+ create_new_user
158
+ Timecop.travel(Time.now+0.5)
159
+ User.load_from_activation_token(@user.activation_token).should == nil
160
+ end
161
+
162
+ it "load_from_activation_token should return nil if token is blank" do
163
+ User.load_from_activation_token(nil).should == nil
164
+ User.load_from_activation_token("").should == nil
165
+ end
166
+
167
+ it "load_from_activation_token should always be valid if expiration period is nil" do
168
+ sorcery_model_property_set(:activation_token_expiration_period, nil)
169
+ create_new_user
170
+ User.load_from_activation_token(@user.activation_token).should == @user
171
+ end
172
+ end
173
+ end