sorcery 0.6.1 → 0.7.10
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.
- data/.travis.yml +2 -0
- data/Gemfile +2 -23
- data/Gemfile.lock +105 -77
- data/README.rdoc +32 -59
- data/Rakefile +29 -1
- data/VERSION +1 -1
- data/lib/generators/sorcery/USAGE +22 -0
- data/lib/generators/sorcery/install_generator.rb +77 -0
- data/lib/generators/sorcery/templates/initializer.rb +406 -0
- data/lib/generators/sorcery/templates/migration/activity_logging.rb +17 -0
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +13 -0
- data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/core.rb +3 -3
- data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/external.rb +1 -1
- data/lib/generators/sorcery/templates/migration/remember_me.rb +15 -0
- data/lib/generators/sorcery/templates/migration/reset_password.rb +17 -0
- data/lib/generators/sorcery/templates/migration/user_activation.rb +17 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +24 -10
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +3 -2
- data/lib/sorcery/controller/submodules/external/protocols/certs/ca-bundle.crt +5182 -0
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +28 -9
- data/lib/sorcery/controller/submodules/external/providers/facebook.rb +12 -4
- data/lib/sorcery/controller/submodules/external/providers/github.rb +89 -0
- data/lib/sorcery/controller/submodules/external/providers/google.rb +90 -0
- data/lib/sorcery/controller/submodules/external/providers/liveid.rb +91 -0
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +8 -2
- data/lib/sorcery/controller/submodules/external.rb +17 -4
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -1
- data/lib/sorcery/controller/submodules/remember_me.rb +26 -15
- data/lib/sorcery/controller/submodules/session_timeout.rb +4 -4
- data/lib/sorcery/controller.rb +61 -38
- data/lib/sorcery/crypto_providers/aes256.rb +7 -3
- data/lib/sorcery/engine.rb +1 -0
- data/lib/sorcery/model/adapters/active_record.rb +17 -1
- data/lib/sorcery/model/adapters/mongo_mapper.rb +54 -0
- data/lib/sorcery/model/adapters/mongoid.rb +22 -4
- data/lib/sorcery/model/submodules/activity_logging.rb +4 -4
- data/lib/sorcery/model/submodules/brute_force_protection.rb +53 -14
- data/lib/sorcery/model/submodules/remember_me.rb +10 -3
- data/lib/sorcery/model/submodules/reset_password.rb +26 -11
- data/lib/sorcery/model/submodules/user_activation.rb +28 -10
- data/lib/sorcery/model/temporary_token.rb +8 -1
- data/lib/sorcery/model.rb +51 -19
- data/lib/sorcery/test_helpers/internal/rails.rb +1 -1
- data/lib/sorcery/test_helpers/rails.rb +2 -2
- data/lib/sorcery.rb +8 -7
- data/sorcery.gemspec +110 -223
- data/spec/Gemfile +1 -1
- data/spec/Gemfile.lock +26 -26
- data/spec/README.md +31 -0
- data/spec/rails3/Gemfile +5 -3
- data/spec/rails3/Gemfile.lock +74 -48
- data/spec/rails3/app/controllers/application_controller.rb +70 -23
- data/spec/rails3/app/mailers/sorcery_mailer.rb +7 -0
- data/spec/rails3/app/views/application/index.html.erb +17 -0
- data/spec/rails3/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
- data/spec/rails3/config/environments/in_memory.rb +35 -0
- data/spec/rails3/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +2 -0
- data/spec/rails3/spec/controller_activity_logging_spec.rb +33 -3
- data/spec/rails3/spec/controller_brute_force_protection_spec.rb +25 -3
- data/spec/rails3/spec/controller_oauth2_spec.rb +170 -25
- data/spec/rails3/spec/controller_remember_me_spec.rb +37 -6
- data/spec/rails3/spec/controller_session_timeout_spec.rb +4 -4
- data/spec/rails3/spec/controller_spec.rb +60 -2
- data/spec/rails3/spec/integration_spec.rb +23 -0
- data/spec/rails3/spec/spec_helper.rb +6 -5
- data/spec/rails3_mongo_mapper/.gitignore +4 -0
- data/spec/rails3_mongo_mapper/.rspec +1 -0
- data/spec/{sinatra_modular → rails3_mongo_mapper}/Gemfile +6 -5
- data/spec/rails3_mongo_mapper/Gemfile.lock +154 -0
- data/spec/{sinatra → rails3_mongo_mapper}/Rakefile +3 -3
- data/spec/rails3_mongo_mapper/app/controllers/application_controller.rb +108 -0
- data/spec/rails3_mongo_mapper/app/helpers/application_helper.rb +2 -0
- data/spec/rails3_mongo_mapper/app/models/authentication.rb +6 -0
- data/spec/rails3_mongo_mapper/app/models/user.rb +5 -0
- data/spec/rails3_mongo_mapper/app/views/layouts/application.html.erb +14 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_email.html.erb +17 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_email.text.erb +9 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
- data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
- data/spec/rails3_mongo_mapper/config/application.rb +51 -0
- data/spec/rails3_mongo_mapper/config/boot.rb +13 -0
- data/spec/rails3_mongo_mapper/config/environment.rb +5 -0
- data/spec/rails3_mongo_mapper/config/environments/development.rb +30 -0
- data/spec/rails3_mongo_mapper/config/environments/in_memory.rb +0 -0
- data/spec/rails3_mongo_mapper/config/environments/production.rb +49 -0
- data/spec/rails3_mongo_mapper/config/environments/test.rb +35 -0
- data/spec/rails3_mongo_mapper/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails3_mongo_mapper/config/initializers/inflections.rb +10 -0
- data/spec/rails3_mongo_mapper/config/initializers/mime_types.rb +5 -0
- data/spec/rails3_mongo_mapper/config/initializers/mongo.rb +2 -0
- data/spec/rails3_mongo_mapper/config/initializers/secret_token.rb +7 -0
- data/spec/rails3_mongo_mapper/config/initializers/session_store.rb +8 -0
- data/spec/rails3_mongo_mapper/config/locales/en.yml +5 -0
- data/spec/rails3_mongo_mapper/config/routes.rb +59 -0
- data/spec/rails3_mongo_mapper/config.ru +4 -0
- data/spec/rails3_mongo_mapper/db/schema.rb +23 -0
- data/spec/rails3_mongo_mapper/db/seeds.rb +7 -0
- data/spec/rails3_mongo_mapper/lib/tasks/.gitkeep +0 -0
- data/spec/rails3_mongo_mapper/public/404.html +26 -0
- data/spec/rails3_mongo_mapper/public/422.html +26 -0
- data/spec/rails3_mongo_mapper/public/500.html +26 -0
- data/spec/rails3_mongo_mapper/public/favicon.ico +0 -0
- data/spec/rails3_mongo_mapper/public/images/rails.png +0 -0
- data/spec/rails3_mongo_mapper/public/javascripts/application.js +2 -0
- data/spec/rails3_mongo_mapper/public/javascripts/controls.js +965 -0
- data/spec/rails3_mongo_mapper/public/javascripts/dragdrop.js +974 -0
- data/spec/rails3_mongo_mapper/public/javascripts/effects.js +1123 -0
- data/spec/rails3_mongo_mapper/public/javascripts/prototype.js +6001 -0
- data/spec/rails3_mongo_mapper/public/javascripts/rails.js +175 -0
- data/spec/rails3_mongo_mapper/public/robots.txt +5 -0
- data/spec/rails3_mongo_mapper/public/stylesheets/.gitkeep +0 -0
- data/spec/rails3_mongo_mapper/script/rails +6 -0
- data/spec/rails3_mongo_mapper/spec/controller_spec.rb +163 -0
- data/spec/rails3_mongo_mapper/spec/spec_helper.orig.rb +27 -0
- data/spec/rails3_mongo_mapper/spec/spec_helper.rb +55 -0
- data/spec/rails3_mongo_mapper/spec/user_activation_spec.rb +9 -0
- data/spec/rails3_mongo_mapper/spec/user_activity_logging_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_brute_force_protection_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_oauth_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_remember_me_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_reset_password_spec.rb +8 -0
- data/spec/rails3_mongo_mapper/spec/user_spec.rb +37 -0
- data/spec/rails3_mongo_mapper/vendor/plugins/.gitkeep +0 -0
- data/spec/rails3_mongoid/Gemfile +2 -1
- data/spec/rails3_mongoid/Gemfile.lock +46 -45
- data/spec/rails3_mongoid/app/controllers/application_controller.rb +5 -0
- data/spec/rails3_mongoid/config/mongoid.yml +1 -1
- data/spec/rails3_mongoid/script/rails +0 -0
- data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +105 -0
- data/spec/rails3_mongoid/spec/controller_spec.rb +174 -0
- data/spec/rails3_mongoid/spec/user_spec.rb +1 -0
- data/spec/shared_examples/user_activation_shared_examples.rb +72 -42
- data/spec/shared_examples/user_remember_me_shared_examples.rb +2 -1
- data/spec/shared_examples/user_reset_password_shared_examples.rb +81 -28
- data/spec/shared_examples/user_shared_examples.rb +36 -8
- data/spec/sorcery_crypto_providers_spec.rb +5 -1
- metadata +239 -346
- data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +0 -24
- data/lib/generators/sorcery_migration/templates/activity_logging.rb +0 -17
- data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +0 -11
- data/lib/generators/sorcery_migration/templates/remember_me.rb +0 -15
- data/lib/generators/sorcery_migration/templates/reset_password.rb +0 -13
- data/lib/generators/sorcery_migration/templates/user_activation.rb +0 -17
- data/lib/sorcery/controller/adapters/sinatra.rb +0 -104
- data/lib/sorcery/initializers/initializer.rb +0 -178
- data/lib/sorcery/sinatra.rb +0 -4
- data/lib/sorcery/test_helpers/internal/sinatra.rb +0 -74
- data/lib/sorcery/test_helpers/internal/sinatra_modular.rb +0 -74
- data/lib/sorcery/test_helpers/sinatra.rb +0 -88
- data/spec/rails3/Rakefile.unused +0 -7
- data/spec/rails3/public/index.html +0 -239
- data/spec/sinatra/Gemfile +0 -15
- data/spec/sinatra/Gemfile.lock +0 -117
- data/spec/sinatra/authentication.rb +0 -3
- data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
- data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -17
- data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -11
- data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +0 -16
- data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +0 -14
- data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
- data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -13
- data/spec/sinatra/filters.rb +0 -27
- data/spec/sinatra/modular.rb +0 -157
- data/spec/sinatra/myapp.rb +0 -133
- data/spec/sinatra/spec/controller_activity_logging_spec.rb +0 -85
- data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +0 -70
- data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +0 -53
- data/spec/sinatra/spec/controller_oauth2_spec.rb +0 -99
- data/spec/sinatra/spec/controller_oauth_spec.rb +0 -100
- data/spec/sinatra/spec/controller_remember_me_spec.rb +0 -64
- data/spec/sinatra/spec/controller_session_timeout_spec.rb +0 -57
- data/spec/sinatra/spec/controller_spec.rb +0 -120
- data/spec/sinatra/spec/spec_helper.rb +0 -45
- data/spec/sinatra/user.rb +0 -6
- data/spec/sinatra/views/test_login.erb +0 -4
- data/spec/sinatra_modular/Gemfile.lock +0 -117
- data/spec/sinatra_modular/Rakefile +0 -11
- data/spec/sinatra_modular/authentication.rb +0 -3
- data/spec/sinatra_modular/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
- data/spec/sinatra_modular/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -17
- data/spec/sinatra_modular/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -11
- data/spec/sinatra_modular/db/migrate/core/20101224223620_create_users.rb +0 -16
- data/spec/sinatra_modular/db/migrate/external/20101224223628_create_authentications.rb +0 -14
- data/spec/sinatra_modular/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
- data/spec/sinatra_modular/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -13
- data/spec/sinatra_modular/filters.rb +0 -27
- data/spec/sinatra_modular/modular.rb +0 -157
- data/spec/sinatra_modular/myapp.rb +0 -133
- data/spec/sinatra_modular/sorcery_mailer.rb +0 -25
- data/spec/sinatra_modular/spec_modular/controller_activity_logging_spec.rb +0 -85
- data/spec/sinatra_modular/spec_modular/controller_brute_force_protection_spec.rb +0 -70
- data/spec/sinatra_modular/spec_modular/controller_http_basic_auth_spec.rb +0 -53
- data/spec/sinatra_modular/spec_modular/controller_oauth2_spec.rb +0 -99
- data/spec/sinatra_modular/spec_modular/controller_oauth_spec.rb +0 -100
- data/spec/sinatra_modular/spec_modular/controller_remember_me_spec.rb +0 -64
- data/spec/sinatra_modular/spec_modular/controller_session_timeout_spec.rb +0 -57
- data/spec/sinatra_modular/spec_modular/controller_spec.rb +0 -116
- data/spec/sinatra_modular/spec_modular/spec.opts +0 -2
- data/spec/sinatra_modular/spec_modular/spec_helper.rb +0 -51
- data/spec/sinatra_modular/user.rb +0 -6
- data/spec/sinatra_modular/views/test_login.erb +0 -4
- /data/spec/{sinatra → rails3_mongo_mapper/app/mailers}/sorcery_mailer.rb +0 -0
- /data/spec/{sinatra → rails3_mongo_mapper}/spec/spec.opts +0 -0
|
@@ -2,91 +2,192 @@ 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
|
-
|
|
6
|
-
OAuth2::
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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)
|
|
12
27
|
end
|
|
13
28
|
|
|
14
29
|
describe ApplicationController do
|
|
15
30
|
before(:all) do
|
|
16
31
|
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
|
|
17
32
|
sorcery_reload!([:external])
|
|
18
|
-
sorcery_controller_property_set(:external_providers, [:facebook])
|
|
33
|
+
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid])
|
|
19
34
|
sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
|
|
20
35
|
sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
21
36
|
sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
|
|
37
|
+
sorcery_controller_external_property_set(:github, :key, "eYVNBjBDi33aa9GkA3w")
|
|
38
|
+
sorcery_controller_external_property_set(:github, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
39
|
+
sorcery_controller_external_property_set(:github, :callback_url, "http://blabla.com")
|
|
40
|
+
sorcery_controller_external_property_set(:google, :key, "eYVNBjBDi33aa9GkA3w")
|
|
41
|
+
sorcery_controller_external_property_set(:google, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
42
|
+
sorcery_controller_external_property_set(:google, :callback_url, "http://blabla.com")
|
|
43
|
+
sorcery_controller_external_property_set(:liveid, :key, "eYVNBjBDi33aa9GkA3w")
|
|
44
|
+
sorcery_controller_external_property_set(:liveid, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
45
|
+
sorcery_controller_external_property_set(:liveid, :callback_url, "http://blabla.com")
|
|
22
46
|
end
|
|
23
|
-
|
|
47
|
+
|
|
24
48
|
after(:all) do
|
|
25
49
|
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
|
|
26
50
|
end
|
|
27
51
|
# ----------------- OAuth -----------------------
|
|
28
52
|
describe ApplicationController, "with OAuth features" do
|
|
29
|
-
|
|
53
|
+
|
|
30
54
|
before(:each) do
|
|
31
55
|
stub_all_oauth2_requests!
|
|
32
56
|
end
|
|
33
|
-
|
|
57
|
+
|
|
34
58
|
after(:each) do
|
|
35
59
|
User.delete_all
|
|
36
60
|
Authentication.delete_all
|
|
37
61
|
end
|
|
38
|
-
|
|
62
|
+
|
|
39
63
|
it "login_at redirects correctly" do
|
|
40
64
|
create_new_user
|
|
41
65
|
get :login_at_test2
|
|
42
66
|
response.should be_a_redirect
|
|
43
|
-
|
|
44
|
-
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
|
+
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")
|
|
45
68
|
end
|
|
46
|
-
|
|
69
|
+
|
|
47
70
|
it "'login_from' logins if user exists" do
|
|
48
71
|
sorcery_model_property_set(:authentications_class, Authentication)
|
|
49
72
|
create_new_external_user(:facebook)
|
|
50
73
|
get :test_login_from2
|
|
51
74
|
flash[:notice].should == "Success!"
|
|
52
75
|
end
|
|
53
|
-
|
|
76
|
+
|
|
54
77
|
it "'login_from' fails if user doesn't exist" do
|
|
55
78
|
sorcery_model_property_set(:authentications_class, Authentication)
|
|
56
79
|
create_new_user
|
|
57
80
|
get :test_login_from2
|
|
58
81
|
flash[:alert].should == "Failed!"
|
|
59
82
|
end
|
|
83
|
+
|
|
84
|
+
# provider: github
|
|
85
|
+
it "login_at redirects correctly (github)" do
|
|
86
|
+
create_new_user
|
|
87
|
+
get :login_at_test3
|
|
88
|
+
response.should be_a_redirect
|
|
89
|
+
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=")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "'login_from' logins if user exists (github)" do
|
|
93
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
94
|
+
create_new_external_user(:github)
|
|
95
|
+
get :test_login_from3
|
|
96
|
+
flash[:notice].should == "Success!"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "'login_from' fails if user doesn't exist (github)" do
|
|
100
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
101
|
+
create_new_user
|
|
102
|
+
get :test_login_from3
|
|
103
|
+
flash[:alert].should == "Failed!"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# provider: google
|
|
107
|
+
it "login_at redirects correctly (google)" do
|
|
108
|
+
create_new_user
|
|
109
|
+
get :login_at_test4
|
|
110
|
+
response.should be_a_redirect
|
|
111
|
+
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%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&display=")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "'login_from' logins if user exists (google)" do
|
|
115
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
116
|
+
create_new_external_user(:google)
|
|
117
|
+
get :test_login_from4
|
|
118
|
+
flash[:notice].should == "Success!"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "'login_from' fails if user doesn't exist (google)" do
|
|
122
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
123
|
+
create_new_user
|
|
124
|
+
get :test_login_from4
|
|
125
|
+
flash[:alert].should == "Failed!"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# provider: liveid
|
|
129
|
+
it "login_at redirects correctly (liveid)" do
|
|
130
|
+
create_new_user
|
|
131
|
+
get :login_at_test5
|
|
132
|
+
response.should be_a_redirect
|
|
133
|
+
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%20wl.emails%20wl.offline_access&display=")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "'login_from' logins if user exists (liveid)" do
|
|
137
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
138
|
+
create_new_external_user(:liveid)
|
|
139
|
+
get :test_login_from5
|
|
140
|
+
flash[:notice].should == "Success!"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "'login_from' fails if user doesn't exist (liveid)" do
|
|
144
|
+
sorcery_model_property_set(:authentications_class, Authentication)
|
|
145
|
+
create_new_user
|
|
146
|
+
get :test_login_from5
|
|
147
|
+
flash[:alert].should == "Failed!"
|
|
148
|
+
end
|
|
149
|
+
|
|
60
150
|
end
|
|
61
|
-
|
|
151
|
+
|
|
152
|
+
|
|
62
153
|
describe ApplicationController do
|
|
63
154
|
it_behaves_like "oauth2_controller"
|
|
64
155
|
end
|
|
65
|
-
|
|
156
|
+
|
|
66
157
|
describe ApplicationController, "OAuth with User Activation features" do
|
|
67
158
|
before(:all) do
|
|
68
159
|
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/activation")
|
|
69
160
|
sorcery_reload!([:user_activation,:external], :user_activation_mailer => ::SorceryMailer)
|
|
70
|
-
sorcery_controller_property_set(:external_providers, [:facebook])
|
|
161
|
+
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid])
|
|
71
162
|
sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
|
|
72
163
|
sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
73
164
|
sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
|
|
165
|
+
sorcery_controller_external_property_set(:github, :key, "eYVNBjBDi33aa9GkA3w")
|
|
166
|
+
sorcery_controller_external_property_set(:github, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
167
|
+
sorcery_controller_external_property_set(:github, :callback_url, "http://blabla.com")
|
|
168
|
+
sorcery_controller_external_property_set(:google, :key, "eYVNBjBDi33aa9GkA3w")
|
|
169
|
+
sorcery_controller_external_property_set(:google, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
170
|
+
sorcery_controller_external_property_set(:google, :callback_url, "http://blabla.com")
|
|
171
|
+
sorcery_controller_external_property_set(:liveid, :key, "eYVNBjBDi33aa9GkA3w")
|
|
172
|
+
sorcery_controller_external_property_set(:liveid, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
|
|
173
|
+
sorcery_controller_external_property_set(:liveid, :callback_url, "http://blabla.com")
|
|
174
|
+
|
|
74
175
|
end
|
|
75
|
-
|
|
176
|
+
|
|
76
177
|
after(:all) do
|
|
77
178
|
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
|
|
78
179
|
end
|
|
79
|
-
|
|
180
|
+
|
|
80
181
|
after(:each) do
|
|
81
182
|
User.delete_all
|
|
82
183
|
end
|
|
83
|
-
|
|
184
|
+
|
|
84
185
|
it "should not send activation email to external users" do
|
|
85
186
|
old_size = ActionMailer::Base.deliveries.size
|
|
86
187
|
create_new_external_user(:facebook)
|
|
87
188
|
ActionMailer::Base.deliveries.size.should == old_size
|
|
88
189
|
end
|
|
89
|
-
|
|
190
|
+
|
|
90
191
|
it "should not send external users an activation success email" do
|
|
91
192
|
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
92
193
|
create_new_external_user(:facebook)
|
|
@@ -94,6 +195,50 @@ describe ApplicationController do
|
|
|
94
195
|
@user.activate!
|
|
95
196
|
ActionMailer::Base.deliveries.size.should == old_size
|
|
96
197
|
end
|
|
198
|
+
|
|
199
|
+
# provider: github
|
|
200
|
+
it "should not send activation email to external users (github)" do
|
|
201
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
202
|
+
create_new_external_user(:github)
|
|
203
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "should not send external users an activation success email (github)" do
|
|
207
|
+
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
208
|
+
create_new_external_user(:github)
|
|
209
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
210
|
+
@user.activate!
|
|
211
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# provider: google
|
|
215
|
+
it "should not send activation email to external users (google)" do
|
|
216
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
217
|
+
create_new_external_user(:google)
|
|
218
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "should not send external users an activation success email (google)" do
|
|
222
|
+
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
223
|
+
create_new_external_user(:google)
|
|
224
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
225
|
+
@user.activate!
|
|
226
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# provider: liveid
|
|
230
|
+
it "should not send activation email to external users (liveid)" do
|
|
231
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
232
|
+
create_new_external_user(:liveid)
|
|
233
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it "should not send external users an activation success email (liveid)" do
|
|
237
|
+
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
238
|
+
create_new_external_user(:liveid)
|
|
239
|
+
old_size = ActionMailer::Base.deliveries.size
|
|
240
|
+
@user.activate!
|
|
241
|
+
ActionMailer::Base.deliveries.size.should == old_size
|
|
242
|
+
end
|
|
97
243
|
end
|
|
98
|
-
|
|
99
|
-
end
|
|
244
|
+
end
|
|
@@ -4,6 +4,7 @@ describe ApplicationController do
|
|
|
4
4
|
|
|
5
5
|
# ----------------- REMEMBER ME -----------------------
|
|
6
6
|
describe ApplicationController, "with remember me features" do
|
|
7
|
+
|
|
7
8
|
before(:all) do
|
|
8
9
|
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/remember_me")
|
|
9
10
|
sorcery_reload!([:remember_me])
|
|
@@ -25,25 +26,29 @@ describe ApplicationController do
|
|
|
25
26
|
|
|
26
27
|
it "should set cookie on remember_me!" do
|
|
27
28
|
post :test_login_with_remember, :username => 'gizmo', :password => 'secret'
|
|
28
|
-
cookies
|
|
29
|
+
@request.cookies.merge!(cookies)
|
|
30
|
+
cookies = ActionDispatch::Cookies::CookieJar.build(@request)
|
|
31
|
+
cookies.signed["remember_me_token"].should == assigns[:current_user].remember_me_token
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
it "should clear cookie on forget_me!" do
|
|
32
35
|
cookies["remember_me_token"] == {:value => 'asd54234dsfsd43534', :expires => 3600}
|
|
33
36
|
get :test_logout
|
|
34
|
-
cookies["remember_me_token"].should
|
|
37
|
+
cookies["remember_me_token"].should be_nil
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
it "login(username,password,remember_me) should login and remember" do
|
|
38
41
|
post :test_login_with_remember_in_login, :username => 'gizmo', :password => 'secret', :remember => "1"
|
|
39
|
-
cookies
|
|
40
|
-
cookies
|
|
42
|
+
@request.cookies.merge!(cookies)
|
|
43
|
+
cookies = ActionDispatch::Cookies::CookieJar.build(@request)
|
|
44
|
+
cookies.signed["remember_me_token"].should_not be_nil
|
|
45
|
+
cookies.signed["remember_me_token"].should == assigns[:user].remember_me_token
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
it "logout should also forget_me!" do
|
|
44
49
|
session[:user_id] = @user.id
|
|
45
50
|
get :test_logout_with_remember
|
|
46
|
-
cookies["remember_me_token"].should
|
|
51
|
+
cookies["remember_me_token"].should be_nil
|
|
47
52
|
end
|
|
48
53
|
|
|
49
54
|
it "should login_from_cookie" do
|
|
@@ -57,9 +62,35 @@ describe ApplicationController do
|
|
|
57
62
|
assigns[:current_user].should == @user
|
|
58
63
|
end
|
|
59
64
|
|
|
65
|
+
it "should not remember_me! when not asked to, even if third parameter is used" do
|
|
66
|
+
post :test_login_with_remember_in_login, :username => 'gizmo', :password => 'secret', :remember => "0"
|
|
67
|
+
cookies["remember_me_token"].should be_nil
|
|
68
|
+
end
|
|
69
|
+
|
|
60
70
|
it "should not remember_me! when not asked to" do
|
|
61
71
|
post :test_login, :username => 'gizmo', :password => 'secret'
|
|
62
|
-
cookies["remember_me_token"].should
|
|
72
|
+
cookies["remember_me_token"].should be_nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# --- login_user(user) ---
|
|
76
|
+
specify { should respond_to(:auto_login) }
|
|
77
|
+
|
|
78
|
+
it "auto_login(user) should login a user instance without remembering" do
|
|
79
|
+
create_new_user
|
|
80
|
+
session[:user_id] = nil
|
|
81
|
+
subject.auto_login(@user)
|
|
82
|
+
get :test_login_from_cookie
|
|
83
|
+
assigns[:current_user].should == @user
|
|
84
|
+
cookies["remember_me_token"].should be_nil
|
|
63
85
|
end
|
|
86
|
+
|
|
87
|
+
it "auto_login(user, true) should login a user instance with remembering" do
|
|
88
|
+
create_new_user
|
|
89
|
+
session[:user_id] = nil
|
|
90
|
+
subject.auto_login(@user, true)
|
|
91
|
+
get :test_login_from_cookie
|
|
92
|
+
assigns[:current_user].should == @user
|
|
93
|
+
cookies["remember_me_token"].should_not be_nil
|
|
94
|
+
end
|
|
64
95
|
end
|
|
65
96
|
end
|
|
@@ -23,7 +23,7 @@ describe ApplicationController do
|
|
|
23
23
|
|
|
24
24
|
it "should reset session after session timeout" do
|
|
25
25
|
login_user
|
|
26
|
-
Timecop.travel(Time.now+0.6)
|
|
26
|
+
Timecop.travel(Time.now.in_time_zone+0.6)
|
|
27
27
|
get :test_should_be_logged_in
|
|
28
28
|
session[:user_id].should be_nil
|
|
29
29
|
response.should be_a_redirect
|
|
@@ -33,10 +33,10 @@ describe ApplicationController do
|
|
|
33
33
|
it "should not logout if there was activity" do
|
|
34
34
|
sorcery_controller_property_set(:session_timeout_from_last_action, true)
|
|
35
35
|
get :test_login, :username => 'gizmo', :password => 'secret'
|
|
36
|
-
Timecop.travel(Time.now+0.3)
|
|
36
|
+
Timecop.travel(Time.now.in_time_zone+0.3)
|
|
37
37
|
get :test_should_be_logged_in
|
|
38
38
|
session[:user_id].should_not be_nil
|
|
39
|
-
Timecop.travel(Time.now+0.3)
|
|
39
|
+
Timecop.travel(Time.now.in_time_zone+0.3)
|
|
40
40
|
get :test_should_be_logged_in
|
|
41
41
|
session[:user_id].should_not be_nil
|
|
42
42
|
response.should be_a_success
|
|
@@ -45,7 +45,7 @@ describe ApplicationController do
|
|
|
45
45
|
it "with 'session_timeout_from_last_action' should logout if there was no activity" do
|
|
46
46
|
sorcery_controller_property_set(:session_timeout_from_last_action, true)
|
|
47
47
|
get :test_login, :username => 'gizmo', :password => 'secret'
|
|
48
|
-
Timecop.travel(Time.now+0.6)
|
|
48
|
+
Timecop.travel(Time.now.in_time_zone+0.6)
|
|
49
49
|
get :test_should_be_logged_in
|
|
50
50
|
session[:user_id].should be_nil
|
|
51
51
|
response.should be_a_redirect
|
|
@@ -28,13 +28,20 @@ describe ApplicationController do
|
|
|
28
28
|
# ----------------- PLUGIN ACTIVATED -----------------------
|
|
29
29
|
describe ApplicationController, "when activated with sorcery" do
|
|
30
30
|
before(:all) do
|
|
31
|
+
sorcery_reload!
|
|
31
32
|
User.delete_all
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
before(:each) do
|
|
32
36
|
create_new_user
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
after(:each) do
|
|
36
40
|
Sorcery::Controller::Config.reset!
|
|
41
|
+
sorcery_reload!
|
|
42
|
+
User.delete_all
|
|
37
43
|
sorcery_controller_property_set(:user_class, User)
|
|
44
|
+
sorcery_model_property_set(:username_attribute_names, [:username, :email])
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
specify { should respond_to(:login) }
|
|
@@ -50,13 +57,47 @@ describe ApplicationController do
|
|
|
50
57
|
assigns[:user].should == @user
|
|
51
58
|
session[:user_id].should == @user.id
|
|
52
59
|
end
|
|
53
|
-
|
|
60
|
+
|
|
61
|
+
it "login(email,password) should return the user when success and set the session with user.id" do
|
|
62
|
+
get :test_login, :username => 'bla@bla.com', :password => 'secret'
|
|
63
|
+
assigns[:user].should == @user
|
|
64
|
+
session[:user_id].should == @user.id
|
|
65
|
+
end
|
|
66
|
+
|
|
54
67
|
it "login(username,password) should return nil and not set the session when failure" do
|
|
55
68
|
get :test_login, :username => 'gizmo', :password => 'opensesame!'
|
|
56
69
|
assigns[:user].should be_nil
|
|
57
70
|
session[:user_id].should be_nil
|
|
58
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
|
|
59
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
|
+
|
|
60
101
|
it "logout should clear the session" do
|
|
61
102
|
cookies[:remember_me_token] = nil
|
|
62
103
|
session[:user_id] = @user.id
|
|
@@ -107,6 +148,23 @@ describe ApplicationController do
|
|
|
107
148
|
flash[:notice].should == "haha!"
|
|
108
149
|
end
|
|
109
150
|
|
|
151
|
+
|
|
152
|
+
# --- auto_login(user) ---
|
|
153
|
+
specify { should respond_to(:auto_login) }
|
|
154
|
+
|
|
155
|
+
it "auto_login(user) should login a user instance" do
|
|
156
|
+
session[:user_id] = nil
|
|
157
|
+
subject.auto_login(@user)
|
|
158
|
+
subject.logged_in?.should be_true
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "auto_login(user) should work even if current_user was already set to false" do
|
|
162
|
+
get :test_logout
|
|
163
|
+
session[:user_id].should be_nil
|
|
164
|
+
subject.current_user.should be_false
|
|
165
|
+
get :test_auto_login
|
|
166
|
+
assigns[:result].should == User.find(:first)
|
|
167
|
+
end
|
|
110
168
|
end
|
|
111
169
|
|
|
112
|
-
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
# visit root_path
|
|
14
|
+
# #save_and_open_page
|
|
15
|
+
# fill_in 'Username', :with => 'gizmo1'
|
|
16
|
+
# fill_in 'Password', :with => 'secret'
|
|
17
|
+
# # <input name="authenticity_token" type="hidden" value="+8M9lXnjnhAW/mAuzwI9Mmy6hM+00qZJa8VMQUg+NmM=">
|
|
18
|
+
# page.execute_script("$$('hidden').value='mezuza'")
|
|
19
|
+
# #save_and_open_page
|
|
20
|
+
# click_button 'Login'
|
|
21
|
+
# save_and_open_page
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
$: << File.join(File.dirname(__FILE__), '..', '..', 'lib' )
|
|
2
2
|
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
|
3
|
+
|
|
3
4
|
# Set the default environment to sqlite3's in_memory database
|
|
4
|
-
ENV[
|
|
5
|
-
require File.expand_path("../../config/environment", __FILE__)
|
|
6
|
-
require 'rspec/rails'
|
|
5
|
+
ENV["RAILS_ENV"] ||= 'in_memory'
|
|
6
|
+
require File.expand_path("../../config/environment", __FILE__)
|
|
7
|
+
require 'rspec/rails'
|
|
8
|
+
require 'capybara/rspec'
|
|
7
9
|
require 'timecop'
|
|
8
10
|
# require 'simplecov'
|
|
9
11
|
# SimpleCov.root File.join(File.dirname(__FILE__), "..", "..", "rails3" )
|
|
@@ -22,8 +24,6 @@ require 'timecop'
|
|
|
22
24
|
# in spec/support/ and its subdirectories.
|
|
23
25
|
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
27
|
RSpec.configure do |config|
|
|
28
28
|
config.include RSpec::Rails::ControllerExampleGroup, :example_group => { :file_path => /controller(.)*_spec.rb$/ }
|
|
29
29
|
# == Mock Framework
|
|
@@ -43,6 +43,7 @@ RSpec.configure do |config|
|
|
|
43
43
|
# instead of true.
|
|
44
44
|
config.use_transactional_fixtures = true
|
|
45
45
|
|
|
46
|
+
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
|
46
47
|
config.before(:suite) do
|
|
47
48
|
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/core")
|
|
48
49
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--colour
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
source 'http://rubygems.org'
|
|
2
2
|
|
|
3
|
-
gem '
|
|
4
|
-
gem '
|
|
5
|
-
gem 'activerecord', '>= 3.0.3'
|
|
6
|
-
gem 'actionmailer', '>= 3.0.3'
|
|
3
|
+
gem 'bcrypt-ruby', '~> 3.0.0'
|
|
4
|
+
gem 'rails', '3.0.3'
|
|
7
5
|
gem "sorcery", '>= 0.1.0', :path => '../../'
|
|
6
|
+
gem "mongo_mapper", '~> 0.11.0'
|
|
7
|
+
gem "bson_ext", "~> 1.3"
|
|
8
8
|
|
|
9
9
|
group :development, :test do
|
|
10
|
-
gem "rake"
|
|
11
10
|
gem "rspec", "~> 2.5.0"
|
|
11
|
+
gem 'rspec-rails', "~> 2.5.0"
|
|
12
12
|
gem 'ruby-debug19'
|
|
13
13
|
gem 'simplecov', '>= 0.3.8', :require => false # Will install simplecov-html as a dependency
|
|
14
14
|
gem 'timecop'
|
|
15
|
+
gem 'pry'
|
|
15
16
|
end
|