sorcery 0.7.4 → 0.8.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 (70) hide show
  1. data/.travis.yml +3 -0
  2. data/Gemfile +9 -4
  3. data/Gemfile.lock +103 -62
  4. data/README.rdoc +33 -8
  5. data/Rakefile +6 -7
  6. data/VERSION +1 -1
  7. data/lib/generators/sorcery/install_generator.rb +15 -10
  8. data/lib/generators/sorcery/templates/initializer.rb +343 -125
  9. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +2 -0
  10. data/lib/generators/sorcery/templates/migration/reset_password.rb +1 -1
  11. data/lib/sorcery/controller/submodules/activity_logging.rb +3 -3
  12. data/lib/sorcery/controller/submodules/brute_force_protection.rb +1 -2
  13. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +19 -19
  14. data/lib/sorcery/controller/submodules/external/providers/facebook.rb +20 -5
  15. data/lib/sorcery/controller/submodules/external/providers/github.rb +15 -4
  16. data/lib/sorcery/controller/submodules/external/providers/google.rb +90 -0
  17. data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +101 -0
  18. data/lib/sorcery/controller/submodules/external/providers/liveid.rb +91 -0
  19. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +2 -1
  20. data/lib/sorcery/controller/submodules/external/providers/vkontakte.rb +94 -0
  21. data/lib/sorcery/controller/submodules/external.rb +89 -15
  22. data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -1
  23. data/lib/sorcery/controller/submodules/remember_me.rb +11 -2
  24. data/lib/sorcery/controller.rb +14 -6
  25. data/lib/sorcery/crypto_providers/bcrypt.rb +1 -0
  26. data/lib/sorcery/model/adapters/active_record.rb +21 -1
  27. data/lib/sorcery/model/adapters/mongo_mapper.rb +22 -15
  28. data/lib/sorcery/model/adapters/mongoid.rb +20 -3
  29. data/lib/sorcery/model/submodules/activity_logging.rb +4 -4
  30. data/lib/sorcery/model/submodules/brute_force_protection.rb +46 -15
  31. data/lib/sorcery/model/submodules/remember_me.rb +4 -6
  32. data/lib/sorcery/model/submodules/reset_password.rb +18 -12
  33. data/lib/sorcery/model/submodules/user_activation.rb +15 -8
  34. data/lib/sorcery/model.rb +57 -43
  35. data/lib/sorcery/railties/tasks.rake +2 -0
  36. data/lib/sorcery.rb +5 -1
  37. data/sorcery.gemspec +33 -21
  38. data/spec/Gemfile +1 -1
  39. data/spec/Gemfile.lock +22 -21
  40. data/spec/README.md +8 -8
  41. data/spec/rails3/Gemfile +3 -3
  42. data/spec/rails3/Gemfile.lock +55 -33
  43. data/spec/rails3/app/controllers/application_controller.rb +85 -2
  44. data/spec/rails3/app/mailers/sorcery_mailer.rb +7 -0
  45. data/spec/rails3/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
  46. data/spec/rails3/config/environments/in_memory.rb +35 -0
  47. data/spec/rails3/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +2 -0
  48. data/spec/rails3/spec/controller_activity_logging_spec.rb +10 -0
  49. data/spec/rails3/spec/controller_brute_force_protection_spec.rb +23 -1
  50. data/spec/rails3/spec/controller_oauth2_spec.rb +260 -22
  51. data/spec/rails3/spec/controller_oauth_spec.rb +111 -6
  52. data/spec/rails3/spec/controller_spec.rb +37 -2
  53. data/spec/rails3/spec/integration_spec.rb +15 -15
  54. data/spec/rails3/spec/spec_helper.rb +1 -1
  55. data/spec/rails3_mongo_mapper/Gemfile +2 -1
  56. data/spec/rails3_mongo_mapper/Gemfile.lock +40 -42
  57. data/spec/rails3_mongo_mapper/app/controllers/application_controller.rb +14 -0
  58. data/spec/rails3_mongo_mapper/spec/controller_spec.rb +41 -1
  59. data/spec/rails3_mongoid/Gemfile +1 -0
  60. data/spec/rails3_mongoid/Gemfile.lock +30 -27
  61. data/spec/rails3_mongoid/app/controllers/application_controller.rb +19 -0
  62. data/spec/rails3_mongoid/config/mongoid.yml +1 -1
  63. data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +18 -11
  64. data/spec/rails3_mongoid/spec/controller_spec.rb +41 -1
  65. data/spec/shared_examples/controller_oauth2_shared_examples.rb +20 -1
  66. data/spec/shared_examples/controller_oauth_shared_examples.rb +18 -0
  67. data/spec/shared_examples/user_activation_shared_examples.rb +71 -41
  68. data/spec/shared_examples/user_reset_password_shared_examples.rb +80 -27
  69. data/spec/sorcery_crypto_providers_spec.rb +14 -1
  70. metadata +74 -46
@@ -2,26 +2,51 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../../shared_examples/controller_oauth2_shared_examples')
3
3
 
4
4
  def stub_all_oauth2_requests!
5
- @client = OAuth2::Client.new("key","secret", :site => "http://myapi.com")
6
- OAuth2::Client.stub!(:new).and_return(@client)
7
- @acc_token = OAuth2::AccessToken.new(@client, "asd", {})
8
- @webby = @client.web_server
9
- OAuth2::Strategy::WebServer.stub!(:new).and_return(@webby)
10
- @webby.stub!(:get_access_token).and_return(@acc_token)
11
- @acc_token.stub!(:get).and_return({"id"=>"123", "name"=>"Noam Ben Ari", "first_name"=>"Noam", "last_name"=>"Ben Ari", "link"=>"http://www.facebook.com/nbenari1", "hometown"=>{"id"=>"110619208966868", "name"=>"Haifa, Israel"}, "location"=>{"id"=>"106906559341067", "name"=>"Pardes Hanah, Hefa, Israel"}, "bio"=>"I'm a new daddy, and enjoying it!", "gender"=>"male", "email"=>"nbenari@gmail.com", "timezone"=>2, "locale"=>"en_US", "languages"=>[{"id"=>"108405449189952", "name"=>"Hebrew"}, {"id"=>"106059522759137", "name"=>"English"}, {"id"=>"112624162082677", "name"=>"Russian"}], "verified"=>true, "updated_time"=>"2011-02-16T20:59:38+0000"}.to_json)
5
+ auth_code = OAuth2::Strategy::AuthCode.any_instance
6
+ access_token = mock(OAuth2::AccessToken)
7
+ access_token.stub(:token_param=)
8
+ response = mock(OAuth2::Response)
9
+ response.stub(:body).and_return({
10
+ "id"=>"123",
11
+ "name"=>"Noam Ben Ari",
12
+ "first_name"=>"Noam",
13
+ "last_name"=>"Ben Ari",
14
+ "link"=>"http://www.facebook.com/nbenari1",
15
+ "hometown"=>{"id"=>"110619208966868", "name"=>"Haifa, Israel"},
16
+ "location"=>{"id"=>"106906559341067", "name"=>"Pardes Hanah, Hefa, Israel"},
17
+ "bio"=>"I'm a new daddy, and enjoying it!",
18
+ "gender"=>"male",
19
+ "email"=>"nbenari@gmail.com",
20
+ "timezone"=>2,
21
+ "locale"=>"en_US",
22
+ "languages"=>[{"id"=>"108405449189952", "name"=>"Hebrew"}, {"id"=>"106059522759137", "name"=>"English"}, {"id"=>"112624162082677", "name"=>"Russian"}],
23
+ "verified"=>true,
24
+ "updated_time"=>"2011-02-16T20:59:38+0000"}.to_json)
25
+ access_token.stub(:get).and_return(response)
26
+ auth_code.stub(:get_token).and_return(access_token)
27
+ end
28
+
29
+ def set_external_property
30
+ sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid])
31
+ sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
32
+ sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
33
+ sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
34
+ sorcery_controller_external_property_set(:github, :key, "eYVNBjBDi33aa9GkA3w")
35
+ sorcery_controller_external_property_set(:github, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
36
+ sorcery_controller_external_property_set(:github, :callback_url, "http://blabla.com")
37
+ sorcery_controller_external_property_set(:google, :key, "eYVNBjBDi33aa9GkA3w")
38
+ sorcery_controller_external_property_set(:google, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
39
+ sorcery_controller_external_property_set(:google, :callback_url, "http://blabla.com")
40
+ sorcery_controller_external_property_set(:liveid, :key, "eYVNBjBDi33aa9GkA3w")
41
+ sorcery_controller_external_property_set(:liveid, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
42
+ sorcery_controller_external_property_set(:liveid, :callback_url, "http://blabla.com")
12
43
  end
13
44
 
14
45
  describe ApplicationController do
15
46
  before(:all) do
16
47
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
17
48
  sorcery_reload!([:external])
18
- sorcery_controller_property_set(:external_providers, [:facebook, :github])
19
- sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
20
- sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
21
- sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
22
- sorcery_controller_external_property_set(:github, :key, "eYVNBjBDi33aa9GkA3w")
23
- sorcery_controller_external_property_set(:github, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
24
- sorcery_controller_external_property_set(:github, :callback_url, "http://blabla.com")
49
+ set_external_property
25
50
  end
26
51
 
27
52
  after(:all) do
@@ -39,13 +64,30 @@ describe ApplicationController do
39
64
  Authentication.delete_all
40
65
  end
41
66
 
42
- it "login_at redirects correctly" do
43
- create_new_user
44
- get :login_at_test2
45
- response.should be_a_redirect
46
- response.should redirect_to("http://myapi.com/oauth/authorize?client_id=key&redirect_uri=http%3A%2F%2Fblabla.com&scope=email%2Coffline_access&response_type=code")
67
+ context "when callback_url begin with /" do
68
+ before do
69
+ sorcery_controller_external_property_set(:facebook, :callback_url, "/oauth/twitter/callback")
70
+ end
71
+ it "login_at redirects correctly" do
72
+ create_new_user
73
+ get :login_at_test2
74
+ response.should be_a_redirect
75
+ response.should redirect_to("https://graph.facebook.com/oauth/authorize?response_type=code&client_id=#{::Sorcery::Controller::Config.facebook.key}&redirect_uri=http%3A%2F%2Ftest.host%2Foauth%2Ftwitter%2Fcallback&scope=email%2Coffline_access&display=page")
76
+ end
77
+ after do
78
+ sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
79
+ end
47
80
  end
48
81
 
82
+ context "when callback_url begin with http://" do
83
+ it "login_at redirects correctly" do
84
+ create_new_user
85
+ get :login_at_test2
86
+ response.should be_a_redirect
87
+ response.should redirect_to("https://graph.facebook.com/oauth/authorize?response_type=code&client_id=#{::Sorcery::Controller::Config.facebook.key}&redirect_uri=http%3A%2F%2Fblabla.com&scope=email%2Coffline_access&display=page")
88
+ end
89
+ end
90
+
49
91
  it "'login_from' logins if user exists" do
50
92
  sorcery_model_property_set(:authentications_class, Authentication)
51
93
  create_new_external_user(:facebook)
@@ -60,12 +102,20 @@ describe ApplicationController do
60
102
  flash[:alert].should == "Failed!"
61
103
  end
62
104
 
105
+ it "on successful login_from the user should be redirected to the url he originally wanted" do
106
+ sorcery_model_property_set(:authentications_class, Authentication)
107
+ create_new_external_user(:facebook)
108
+ get :test_return_to_with_external2, {}, :return_to_url => "fuu"
109
+ response.should redirect_to("fuu")
110
+ flash[:notice].should == "Success!"
111
+ end
112
+
63
113
  # provider: github
64
114
  it "login_at redirects correctly (github)" do
65
115
  create_new_user
66
116
  get :login_at_test3
67
117
  response.should be_a_redirect
68
- response.should redirect_to("http://myapi.com/oauth/authorize?client_id=key&redirect_uri=http%3A%2F%2Fblabla.com&scope=&response_type=code")
118
+ response.should redirect_to("https://github.com/login/oauth/authorize?response_type=code&client_id=#{::Sorcery::Controller::Config.github.key}&redirect_uri=http%3A%2F%2Fblabla.com&scope&display")
69
119
  end
70
120
 
71
121
  it "'login_from' logins if user exists (github)" do
@@ -82,6 +132,74 @@ describe ApplicationController do
82
132
  flash[:alert].should == "Failed!"
83
133
  end
84
134
 
135
+ it "on successful login_from the user should be redirected to the url he originally wanted (github)" do
136
+ sorcery_model_property_set(:authentications_class, Authentication)
137
+ create_new_external_user(:github)
138
+ get :test_return_to_with_external3, {}, :return_to_url => "fuu"
139
+ response.should redirect_to("fuu")
140
+ flash[:notice].should == "Success!"
141
+ end
142
+
143
+ # provider: google
144
+ it "login_at redirects correctly (google)" do
145
+ create_new_user
146
+ get :login_at_test4
147
+ response.should be_a_redirect
148
+ response.should redirect_to("https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=#{::Sorcery::Controller::Config.google.key}&redirect_uri=http%3A%2F%2Fblabla.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&display")
149
+ end
150
+
151
+ it "'login_from' logins if user exists (google)" do
152
+ sorcery_model_property_set(:authentications_class, Authentication)
153
+ create_new_external_user(:google)
154
+ get :test_login_from4
155
+ flash[:notice].should == "Success!"
156
+ end
157
+
158
+ it "'login_from' fails if user doesn't exist (google)" do
159
+ sorcery_model_property_set(:authentications_class, Authentication)
160
+ create_new_user
161
+ get :test_login_from4
162
+ flash[:alert].should == "Failed!"
163
+ end
164
+
165
+ it "on successful login_from the user should be redirected to the url he originally wanted (google)" do
166
+ sorcery_model_property_set(:authentications_class, Authentication)
167
+ create_new_external_user(:google)
168
+ get :test_return_to_with_external4, {}, :return_to_url => "fuu"
169
+ response.should redirect_to("fuu")
170
+ flash[:notice].should == "Success!"
171
+ end
172
+
173
+ # provider: liveid
174
+ it "login_at redirects correctly (liveid)" do
175
+ create_new_user
176
+ get :login_at_test5
177
+ response.should be_a_redirect
178
+ response.should redirect_to("https://oauth.live.com/authorize?response_type=code&client_id=#{::Sorcery::Controller::Config.liveid.key}&redirect_uri=http%3A%2F%2Fblabla.com&scope=wl.basic+wl.emails+wl.offline_access&display")
179
+ end
180
+
181
+ it "'login_from' logins if user exists (liveid)" do
182
+ sorcery_model_property_set(:authentications_class, Authentication)
183
+ create_new_external_user(:liveid)
184
+ get :test_login_from5
185
+ flash[:notice].should == "Success!"
186
+ end
187
+
188
+ it "'login_from' fails if user doesn't exist (liveid)" do
189
+ sorcery_model_property_set(:authentications_class, Authentication)
190
+ create_new_user
191
+ get :test_login_from5
192
+ flash[:alert].should == "Failed!"
193
+ end
194
+
195
+ it "on successful login_from the user should be redirected to the url he originally wanted (liveid)" do
196
+ sorcery_model_property_set(:authentications_class, Authentication)
197
+ create_new_external_user(:liveid)
198
+ get :test_return_to_with_external5, {}, :return_to_url => "fuu"
199
+ response.should redirect_to("fuu")
200
+ flash[:notice].should == "Success!"
201
+ end
202
+
85
203
  end
86
204
 
87
205
 
@@ -93,13 +211,20 @@ describe ApplicationController do
93
211
  before(:all) do
94
212
  ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
95
213
  sorcery_reload!([:user_activation,:external], :user_activation_mailer => ::SorceryMailer)
96
- sorcery_controller_property_set(:external_providers, [:facebook, :github])
214
+ sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid])
97
215
  sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
98
216
  sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
99
217
  sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
100
218
  sorcery_controller_external_property_set(:github, :key, "eYVNBjBDi33aa9GkA3w")
101
219
  sorcery_controller_external_property_set(:github, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
102
220
  sorcery_controller_external_property_set(:github, :callback_url, "http://blabla.com")
221
+ sorcery_controller_external_property_set(:google, :key, "eYVNBjBDi33aa9GkA3w")
222
+ sorcery_controller_external_property_set(:google, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
223
+ sorcery_controller_external_property_set(:google, :callback_url, "http://blabla.com")
224
+ sorcery_controller_external_property_set(:liveid, :key, "eYVNBjBDi33aa9GkA3w")
225
+ sorcery_controller_external_property_set(:liveid, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
226
+ sorcery_controller_external_property_set(:liveid, :callback_url, "http://blabla.com")
227
+
103
228
  end
104
229
 
105
230
  after(:all) do
@@ -138,5 +263,118 @@ describe ApplicationController do
138
263
  @user.activate!
139
264
  ActionMailer::Base.deliveries.size.should == old_size
140
265
  end
266
+
267
+ # provider: google
268
+ it "should not send activation email to external users (google)" do
269
+ old_size = ActionMailer::Base.deliveries.size
270
+ create_new_external_user(:google)
271
+ ActionMailer::Base.deliveries.size.should == old_size
272
+ end
273
+
274
+ it "should not send external users an activation success email (google)" do
275
+ sorcery_model_property_set(:activation_success_email_method_name, nil)
276
+ create_new_external_user(:google)
277
+ old_size = ActionMailer::Base.deliveries.size
278
+ @user.activate!
279
+ ActionMailer::Base.deliveries.size.should == old_size
280
+ end
281
+
282
+ # provider: liveid
283
+ it "should not send activation email to external users (liveid)" do
284
+ old_size = ActionMailer::Base.deliveries.size
285
+ create_new_external_user(:liveid)
286
+ ActionMailer::Base.deliveries.size.should == old_size
287
+ end
288
+
289
+ it "should not send external users an activation success email (liveid)" do
290
+ sorcery_model_property_set(:activation_success_email_method_name, nil)
291
+ create_new_external_user(:liveid)
292
+ old_size = ActionMailer::Base.deliveries.size
293
+ @user.activate!
294
+ ActionMailer::Base.deliveries.size.should == old_size
295
+ end
141
296
  end
142
- end
297
+
298
+ describe ApplicationController, "OAuth with user activation features" do
299
+ before(:all) do
300
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
301
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
302
+ sorcery_reload!([:activity_logging, :external])
303
+ end
304
+
305
+ after(:all) do
306
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
307
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
308
+ end
309
+
310
+ %w(facebook github google liveid).each.with_index(2) do |provider, index|
311
+ context "when #{provider}" do
312
+ before(:each) do
313
+ User.delete_all
314
+ Authentication.delete_all
315
+ sorcery_controller_property_set(:register_login_time, true)
316
+ stub_all_oauth2_requests!
317
+ sorcery_model_property_set(:authentications_class, Authentication)
318
+ create_new_external_user(provider.to_sym)
319
+ end
320
+
321
+ it "should register login time" do
322
+ now = Time.now.in_time_zone
323
+ get "test_login_from#{index}".to_sym
324
+ User.last.last_login_at.should_not be_nil
325
+ User.last.last_login_at.to_s(:db).should >= now.to_s(:db)
326
+ User.last.last_login_at.to_s(:db).should <= (now+2).to_s(:db)
327
+ end
328
+
329
+ it "should not register login time if configured so" do
330
+ sorcery_controller_property_set(:register_login_time, false)
331
+ now = Time.now.in_time_zone
332
+ get "test_login_from#{index}".to_sym
333
+ User.last.last_login_at.should be_nil
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ describe ApplicationController, "OAuth with session timeout features" do
340
+ before(:all) do
341
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
342
+ sorcery_reload!([:session_timeout, :external])
343
+ end
344
+
345
+ after(:all) do
346
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
347
+ end
348
+
349
+ %w(facebook github google liveid).each.with_index(2) do |provider, index|
350
+ context "when #{provider}" do
351
+ before(:each) do
352
+ User.delete_all
353
+ Authentication.delete_all
354
+ sorcery_model_property_set(:authentications_class, Authentication)
355
+ sorcery_controller_property_set(:session_timeout,0.5)
356
+ stub_all_oauth2_requests!
357
+ create_new_external_user(provider.to_sym)
358
+ end
359
+
360
+ after(:each) do
361
+ Timecop.return
362
+ end
363
+
364
+ it "should not reset session before session timeout" do
365
+ get "test_login_from#{index}".to_sym
366
+ session[:user_id].should_not be_nil
367
+ flash[:notice].should == "Success!"
368
+ end
369
+
370
+ it "should reset session after session timeout" do
371
+ get "test_login_from#{index}".to_sym
372
+ Timecop.travel(Time.now.in_time_zone+0.6)
373
+ get :test_should_be_logged_in
374
+ session[:user_id].should be_nil
375
+ response.should be_a_redirect
376
+ end
377
+ end
378
+ end
379
+ end
380
+ end
@@ -43,11 +43,28 @@ describe ApplicationController do
43
43
  Authentication.delete_all
44
44
  end
45
45
 
46
- it "login_at redirects correctly" do
47
- create_new_user
48
- get :login_at_test
49
- response.should be_a_redirect
50
- response.should redirect_to("http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Fblabla.com&oauth_token=")
46
+ context "when callback_url begin with /" do
47
+ before do
48
+ sorcery_controller_external_property_set(:twitter, :callback_url, "/oauth/twitter/callback")
49
+ end
50
+ it "login_at redirects correctly" do
51
+ create_new_user
52
+ get :login_at_test
53
+ response.should be_a_redirect
54
+ response.should redirect_to("http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Ftest.host%2Foauth%2Ftwitter%2Fcallback&oauth_token=")
55
+ end
56
+ after do
57
+ sorcery_controller_external_property_set(:twitter, :callback_url, "http://blabla.com")
58
+ end
59
+ end
60
+
61
+ context "when callback_url begin with http://" do
62
+ it "login_at redirects correctly" do
63
+ create_new_user
64
+ get :login_at_test
65
+ response.should be_a_redirect
66
+ response.should redirect_to("http://myapi.com/oauth/authorize?oauth_callback=http%3A%2F%2Fblabla.com&oauth_token=")
67
+ end
51
68
  end
52
69
 
53
70
  it "logins if user exists" do
@@ -63,6 +80,15 @@ describe ApplicationController do
63
80
  get :test_login_from, :oauth_verifier => "blablaRERASDFcxvSDFA"
64
81
  flash[:alert].should == "Failed!"
65
82
  end
83
+
84
+ it "on successful 'login_from' the user should be redirected to the url he originally wanted" do
85
+ sorcery_model_property_set(:authentications_class, Authentication)
86
+ create_new_external_user(:twitter)
87
+ get :test_return_to_with_external, {}, :return_to_url => "fuu"
88
+ response.should redirect_to("fuu")
89
+ flash[:notice].should == "Success!"
90
+ end
91
+
66
92
  end
67
93
 
68
94
  describe ApplicationController do
@@ -98,4 +124,83 @@ describe ApplicationController do
98
124
  ActionMailer::Base.deliveries.size.should == old_size
99
125
  end
100
126
  end
101
- end
127
+
128
+ describe ApplicationController, "OAuth with user activation features" do
129
+ before(:all) do
130
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
131
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activity_logging")
132
+ sorcery_reload!([:activity_logging, :external])
133
+ end
134
+
135
+ after(:all) do
136
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
137
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activity_logging")
138
+ end
139
+
140
+ context "when twitter" do
141
+ before(:each) do
142
+ User.delete_all
143
+ Authentication.delete_all
144
+ sorcery_controller_property_set(:register_login_time, true)
145
+ stub_all_oauth_requests!
146
+ sorcery_model_property_set(:authentications_class, Authentication)
147
+ create_new_external_user(:twitter)
148
+ end
149
+
150
+ it "should register login time" do
151
+ now = Time.now.in_time_zone
152
+ get :test_login_from
153
+ User.last.last_login_at.should_not be_nil
154
+ User.last.last_login_at.to_s(:db).should >= now.to_s(:db)
155
+ User.last.last_login_at.to_s(:db).should <= (now+2).to_s(:db)
156
+ end
157
+
158
+ it "should not register login time if configured so" do
159
+ sorcery_controller_property_set(:register_login_time, false)
160
+ now = Time.now.in_time_zone
161
+ get :test_login_from
162
+ User.last.last_login_at.should be_nil
163
+ end
164
+ end
165
+ end
166
+
167
+ describe ApplicationController, "OAuth with session timeout features" do
168
+ before(:all) do
169
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
170
+ sorcery_reload!([:session_timeout, :external])
171
+ end
172
+
173
+ after(:all) do
174
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
175
+ end
176
+
177
+ context "when twitter" do
178
+ before(:each) do
179
+ User.delete_all
180
+ Authentication.delete_all
181
+ sorcery_model_property_set(:authentications_class, Authentication)
182
+ sorcery_controller_property_set(:session_timeout,0.5)
183
+ stub_all_oauth_requests!
184
+ create_new_external_user(:twitter)
185
+ end
186
+
187
+ after(:each) do
188
+ Timecop.return
189
+ end
190
+
191
+ it "should not reset session before session timeout" do
192
+ get :test_login_from
193
+ session[:user_id].should_not be_nil
194
+ flash[:notice].should == "Success!"
195
+ end
196
+
197
+ it "should reset session after session timeout" do
198
+ get :test_login_from
199
+ Timecop.travel(Time.now.in_time_zone+0.6)
200
+ get :test_should_be_logged_in
201
+ session[:user_id].should be_nil
202
+ response.should be_a_redirect
203
+ end
204
+ end
205
+ end
206
+ end
@@ -63,13 +63,41 @@ describe ApplicationController do
63
63
  assigns[:user].should == @user
64
64
  session[:user_id].should == @user.id
65
65
  end
66
-
66
+
67
67
  it "login(username,password) should return nil and not set the session when failure" do
68
68
  get :test_login, :username => 'gizmo', :password => 'opensesame!'
69
69
  assigns[:user].should be_nil
70
70
  session[:user_id].should be_nil
71
71
  end
72
+
73
+ it "login(username,password) should return nil and not set the session when upper case username" do
74
+ get :test_login, :username => 'GIZMO', :password => 'secret'
75
+ assigns[:user].should be_nil
76
+ session[:user_id].should be_nil
77
+ end
72
78
 
79
+ it "login(username,password) should return the user and set the session with user.id when upper case username and config is downcase before authenticating" do
80
+ sorcery_model_property_set(:downcase_username_before_authenticating, true)
81
+ get :test_login, :username => 'GIZMO', :password => 'secret'
82
+ assigns[:user].should == @user
83
+ session[:user_id].should == @user.id
84
+ end
85
+
86
+ it "login(username,password) should return nil and not set the session when user was created with upper case username, config is default, and log in username is lower case" do
87
+ create_new_user({:username => 'GIZMO1', :email => "bla1@bla.com", :password => 'secret1'})
88
+ get :test_login, :username => 'gizmo1', :password => 'secret1'
89
+ assigns[:user].should be_nil
90
+ session[:user_id].should be_nil
91
+ end
92
+
93
+ it "login(username,password) should return the user and set the session with user.id when user was created with upper case username and config is downcase before authenticating" do
94
+ sorcery_model_property_set(:downcase_username_before_authenticating, true)
95
+ create_new_user({:username => 'GIZMO1', :email => "bla1@bla.com", :password => 'secret1'})
96
+ get :test_login, :username => 'gizmo1', :password => 'secret1'
97
+ assigns[:user].should == @user
98
+ session[:user_id].should == @user.id
99
+ end
100
+
73
101
  it "logout should clear the session" do
74
102
  cookies[:remember_me_token] = nil
75
103
  session[:user_id] = @user.id
@@ -113,6 +141,13 @@ describe ApplicationController do
113
141
  response.should redirect_to("http://test.host/")
114
142
  end
115
143
 
144
+ it "require_login before_filter should not save the url that the user originally wanted upon all non-get http methods" do
145
+ [:post, :put, :delete].each do |m|
146
+ self.send(m, :some_action)
147
+ session[:return_to_url].should be_nil
148
+ end
149
+ end
150
+
116
151
  it "on successful login the user should be redirected to the url he originally wanted" do
117
152
  session[:return_to_url] = "http://test.host/some_action"
118
153
  post :test_return_to, :username => 'gizmo', :password => 'secret'
@@ -139,4 +174,4 @@ describe ApplicationController do
139
174
  end
140
175
  end
141
176
 
142
- end
177
+ end
@@ -1,21 +1,21 @@
1
- # require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- #
3
- # describe "the login process", :type => :request do
4
- # before(:all) do
5
- # sorcery_reload!
6
- # create_new_user
7
- # end
8
- #
9
- # after(:all) do
10
- # end
11
- #
12
- # it "handles unverified request" do
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "the login process", :type => :request do
4
+ before(:all) do
5
+ sorcery_reload!
6
+ create_new_user
7
+ end
8
+
9
+ after(:all) do
10
+ end
11
+ end
12
+ # it "handles unverified request", :js => true do
13
13
  # visit root_path
14
- # # save_and_open_page
15
- # fill_in 'Username', :with => 'gizmo'
14
+ # #save_and_open_page
15
+ # fill_in 'Username', :with => 'gizmo1'
16
16
  # fill_in 'Password', :with => 'secret'
17
17
  # # <input name="authenticity_token" type="hidden" value="+8M9lXnjnhAW/mAuzwI9Mmy6hM+00qZJa8VMQUg+NmM=">
18
- # #page.execute_script("$$('hidden').value='mezuza'")
18
+ # page.execute_script("$$('hidden').value='mezuza'")
19
19
  # #save_and_open_page
20
20
  # click_button 'Login'
21
21
  # save_and_open_page
@@ -5,7 +5,7 @@ $: << File.join(File.dirname(__FILE__), '..', '..', 'lib' )
5
5
  ENV["RAILS_ENV"] ||= 'in_memory'
6
6
  require File.expand_path("../../config/environment", __FILE__)
7
7
  require 'rspec/rails'
8
- #require 'capybara/rspec'
8
+ require 'capybara/rspec'
9
9
  require 'timecop'
10
10
  # require 'simplecov'
11
11
  # SimpleCov.root File.join(File.dirname(__FILE__), "..", "..", "rails3" )
@@ -1,8 +1,9 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
+ gem 'bcrypt-ruby', '~> 3.0.0'
3
4
  gem 'rails', '3.0.3'
4
5
  gem "sorcery", '>= 0.1.0', :path => '../../'
5
- gem "mongo_mapper"
6
+ gem "mongo_mapper", '~> 0.11.0'
6
7
  gem "bson_ext", "~> 1.3"
7
8
 
8
9
  group :development, :test do