sorcery 0.2.1 → 0.3.0

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 (66) hide show
  1. data/README.rdoc +89 -59
  2. data/VERSION +1 -1
  3. data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +24 -0
  4. data/lib/generators/sorcery_migration/templates/activity_logging.rb +17 -0
  5. data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +11 -0
  6. data/lib/generators/sorcery_migration/templates/core.rb +16 -0
  7. data/lib/generators/sorcery_migration/templates/oauth.rb +14 -0
  8. data/lib/generators/sorcery_migration/templates/remember_me.rb +15 -0
  9. data/lib/generators/sorcery_migration/templates/reset_password.rb +13 -0
  10. data/lib/generators/sorcery_migration/templates/user_activation.rb +17 -0
  11. data/lib/sorcery.rb +8 -0
  12. data/lib/sorcery/controller/adapters/sinatra.rb +97 -0
  13. data/lib/sorcery/controller/submodules/http_basic_auth.rb +10 -6
  14. data/lib/sorcery/controller/submodules/oauth.rb +6 -3
  15. data/lib/sorcery/controller/submodules/oauth/oauth1.rb +11 -4
  16. data/lib/sorcery/controller/submodules/oauth/oauth2.rb +1 -1
  17. data/lib/sorcery/model/submodules/activity_logging.rb +1 -1
  18. data/lib/sorcery/model/submodules/brute_force_protection.rb +0 -4
  19. data/lib/sorcery/sinatra.rb +14 -0
  20. data/lib/sorcery/test_helpers.rb +8 -52
  21. data/lib/sorcery/test_helpers/rails.rb +57 -0
  22. data/lib/sorcery/test_helpers/sinatra.rb +131 -0
  23. data/sorcery.gemspec +77 -3
  24. data/spec/Gemfile +1 -1
  25. data/spec/Gemfile.lock +2 -2
  26. data/spec/rails3/app_root/Gemfile +2 -4
  27. data/spec/rails3/app_root/Gemfile.lock +2 -5
  28. data/spec/rails3/app_root/spec/controller_oauth2_spec.rb +2 -0
  29. data/spec/rails3/app_root/spec/controller_oauth_spec.rb +6 -1
  30. data/spec/rails3/app_root/spec/controller_session_timeout_spec.rb +2 -2
  31. data/spec/rails3/app_root/spec/spec_helper.rb +1 -0
  32. data/spec/sinatra/Gemfile +12 -0
  33. data/spec/sinatra/Gemfile.lock +134 -0
  34. data/spec/sinatra/Rakefile +10 -0
  35. data/spec/sinatra/authentication.rb +3 -0
  36. data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  37. data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  38. data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  39. data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +16 -0
  40. data/spec/sinatra/db/migrate/oauth/20101224223628_create_authentications.rb +14 -0
  41. data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  42. data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  43. data/spec/sinatra/filters.rb +21 -0
  44. data/spec/sinatra/myapp.rb +133 -0
  45. data/spec/sinatra/sorcery_mailer.rb +25 -0
  46. data/spec/sinatra/spec/controller_activity_logging_spec.rb +85 -0
  47. data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +69 -0
  48. data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +53 -0
  49. data/spec/sinatra/spec/controller_oauth2_spec.rb +119 -0
  50. data/spec/sinatra/spec/controller_oauth_spec.rb +121 -0
  51. data/spec/sinatra/spec/controller_remember_me_spec.rb +64 -0
  52. data/spec/sinatra/spec/controller_session_timeout_spec.rb +52 -0
  53. data/spec/sinatra/spec/controller_spec.rb +120 -0
  54. data/spec/sinatra/spec/spec.opts +4 -0
  55. data/spec/sinatra/spec/spec_helper.rb +44 -0
  56. data/spec/sinatra/spec/user_activation_spec.rb +188 -0
  57. data/spec/sinatra/spec/user_activity_logging_spec.rb +36 -0
  58. data/spec/sinatra/spec/user_brute_force_protection_spec.rb +76 -0
  59. data/spec/sinatra/spec/user_oauth_spec.rb +39 -0
  60. data/spec/sinatra/spec/user_remember_me_spec.rb +66 -0
  61. data/spec/sinatra/spec/user_reset_password_spec.rb +178 -0
  62. data/spec/sinatra/spec/user_spec.rb +317 -0
  63. data/spec/sinatra/user.rb +6 -0
  64. data/spec/sinatra/views/test_login.erb +4 -0
  65. data/spec/untitled folder +18 -0
  66. metadata +76 -2
@@ -0,0 +1,64 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Sinatra::Application do
4
+
5
+ # ----------------- REMEMBER ME -----------------------
6
+ describe Sinatra::Application, "with remember me features" do
7
+ before(:all) do
8
+ ActiveRecord::Migrator.migrate("#{APP_ROOT}/db/migrate/remember_me")
9
+ sorcery_reload!([:remember_me])
10
+ end
11
+
12
+ before(:each) do
13
+ create_new_user
14
+ end
15
+
16
+ after(:all) do
17
+ ActiveRecord::Migrator.rollback("#{APP_ROOT}/db/migrate/remember_me")
18
+ end
19
+
20
+ after(:each) do
21
+ session = nil
22
+ clear_cookies
23
+ User.delete_all
24
+ end
25
+
26
+ it "should set cookie on remember_me!" do
27
+ post "/test_login_with_remember", :username => 'gizmo', :password => 'secret'
28
+ cookies["remember_me_token"].should == assigns[:user].remember_me_token
29
+ end
30
+
31
+ it "should clear cookie on forget_me!" do
32
+ cookies["remember_me_token"] == {:value => 'asd54234dsfsd43534', :expires => 3600}
33
+ get '/test_logout'
34
+ cookies["remember_me_token"].should == nil
35
+ end
36
+
37
+ it "login(username,password,remember_me) should login and remember" do
38
+ post '/test_login_with_remember_in_login', :username => 'gizmo', :password => 'secret', :remember => "1"
39
+ cookies["remember_me_token"].should_not be_nil
40
+ cookies["remember_me_token"].should == assigns[:user].remember_me_token
41
+ end
42
+
43
+ it "logout should also forget_me!" do
44
+ session[:user_id] = @user.id
45
+ get '/test_logout_with_remember'
46
+ cookies["remember_me_token"].should == nil
47
+ end
48
+
49
+ it "should login_from_cookie" do
50
+ post "/test_login_with_remember", :username => 'gizmo', :password => 'secret'
51
+ get_sinatra_app(subject).instance_eval do
52
+ @current_user = nil
53
+ end
54
+ session[:user_id] = nil
55
+ get '/test_login_from_cookie'
56
+ assigns[:current_user].should == @user
57
+ end
58
+
59
+ it "should not remember_me! when not asked to" do
60
+ post '/test_login', :username => 'gizmo', :password => 'secret'
61
+ cookies["remember_me_token"].should == nil
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Sinatra::Application do
4
+
5
+ # ----------------- SESSION TIMEOUT -----------------------
6
+ describe Sinatra::Application, "with session timeout features" do
7
+ before(:all) do
8
+ sorcery_reload!([:session_timeout])
9
+ sorcery_controller_property_set(:session_timeout,0.5)
10
+ create_new_user
11
+ end
12
+
13
+ it "should not reset session before session timeout" do
14
+ session[:user_id] = User.first.id
15
+ get "/test_should_be_logged_in"
16
+ last_response.should be_ok
17
+ end
18
+
19
+ it "should reset session after session timeout" do
20
+ get "/test_login", :username => 'gizmo', :password => 'secret'
21
+ session[:user_id].should_not be_nil
22
+ sleep 0.6
23
+ get "/test_should_be_logged_in"
24
+ last_response.should be_a_redirect
25
+ end
26
+
27
+ it "with 'session_timeout_from_last_action' should not logout if there was activity" do
28
+ session[:user_id] = nil
29
+ sorcery_controller_property_set(:session_timeout,2)
30
+ sorcery_controller_property_set(:session_timeout_from_last_action, true)
31
+ get "/test_login", :username => 'gizmo', :password => 'secret'
32
+ sleep 1
33
+ get "/test_should_be_logged_in"
34
+ session[:user_id].should_not be_nil
35
+ sleep 1
36
+ get "/test_should_be_logged_in"
37
+ session[:user_id].should_not be_nil
38
+ last_response.should be_ok
39
+ end
40
+
41
+ it "with 'session_timeout_from_last_action' should logout if there was no activity" do
42
+ sorcery_controller_property_set(:session_timeout,0.5)
43
+ sorcery_controller_property_set(:session_timeout_from_last_action, true)
44
+ get "/test_login", :username => 'gizmo', :password => 'secret'
45
+ sleep 0.6
46
+ get "/test_should_be_logged_in"
47
+ session[:user_id].should be_nil
48
+ last_response.should be_a_redirect
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,120 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Sinatra::Application do
4
+
5
+ # ----------------- PLUGIN CONFIGURATION -----------------------
6
+ describe "plugin configuration" do
7
+ before(:all) do
8
+ sorcery_reload!
9
+ end
10
+
11
+ after(:each) do
12
+ Sorcery::Controller::Config.reset!
13
+ sorcery_reload!
14
+ end
15
+
16
+ it "should enable configuration option 'user_class'" do
17
+ sorcery_controller_property_set(:user_class, TestUser)
18
+ Sorcery::Controller::Config.user_class.should equal(TestUser)
19
+ end
20
+
21
+ it "should enable configuration option 'not_authenticated_action'" do
22
+ sorcery_controller_property_set(:not_authenticated_action, :my_action)
23
+ Sorcery::Controller::Config.not_authenticated_action.should equal(:my_action)
24
+ end
25
+
26
+ end
27
+
28
+ # ----------------- PLUGIN ACTIVATED -----------------------
29
+ describe Sinatra::Application, "when activated with sorcery" do
30
+
31
+ before(:all) do
32
+ User.delete_all
33
+ create_new_user
34
+ end
35
+
36
+ after(:each) do
37
+ Sorcery::Controller::Config.reset!
38
+ sorcery_controller_property_set(:user_class, User)
39
+ end
40
+
41
+ it "should respond to the instance method login" do
42
+ get_sinatra_app(subject).should respond_to(:login)
43
+ end
44
+
45
+ it "should respond to the instance method logout" do
46
+ get_sinatra_app(subject).should respond_to(:logout)
47
+ end
48
+
49
+ it "should respond to the instance method logged_in?" do
50
+ get_sinatra_app(subject).should respond_to(:logged_in?)
51
+ end
52
+
53
+ it "should respond to the instance method current_user" do
54
+ get_sinatra_app(subject).should respond_to(:current_user)
55
+ end
56
+
57
+ it "login(username,password) should return the user when success and set the session with user.id" do
58
+ get "/test_login", :username => 'gizmo', :password => 'secret'
59
+ assigns[:user].should == @user
60
+ session[:user_id].should == @user.id
61
+ end
62
+
63
+ it "login(username,password) should return nil and not set the session when failure" do
64
+ get "/test_login", :username => 'gizmo', :password => 'opensesame!'
65
+ assigns[:user].should be_nil
66
+ session[:user_id].should be_nil
67
+ end
68
+
69
+ it "logout should clear the session" do
70
+ get "/test_logout"
71
+ session[:user_id].should be_nil
72
+ end
73
+
74
+ it "logged_in? should return true if logged in" do
75
+ get "/test_login", :username => 'gizmo', :password => 'secret'
76
+ assigns[:logged_in].should be_true
77
+ end
78
+
79
+ it "logged_in? should return false if not logged in" do
80
+ get "/test_login", :username => 'gizmo', :password => 'opensesame!'
81
+ assigns[:logged_in].should be_false
82
+ end
83
+
84
+ it "current_user should return the user instance if logged in" do
85
+ create_new_user
86
+ get "/test_current_user", :id => @user.id
87
+ assigns[:current_user].should == @user
88
+ end
89
+
90
+ it "current_user should return false if not logged in" do
91
+ get "/test_logout"
92
+ assigns[:current_user].should == false
93
+ end
94
+
95
+ it "should respond to 'require_login'" do
96
+ get_sinatra_app(subject).should respond_to(:require_login)
97
+ end
98
+
99
+ it "should call the configured 'not_authenticated_action' when authenticate before_filter fails" do
100
+ sorcery_controller_property_set(:not_authenticated_action, :test_not_authenticated_action)
101
+ get "/test_logout"
102
+ last_response.body.should == "test_not_authenticated_action"
103
+ end
104
+
105
+ it "require_login before_filter should save the url that the user originally wanted" do
106
+ sorcery_controller_property_set(:not_authenticated_action, :not_authenticated2)
107
+ get "/some_action"
108
+ assigns[:session][:return_to_url].should == "http://example.org/some_action"
109
+ last_response.status.should == 302
110
+ last_response.should redirect_to("http://example.org/")
111
+ end
112
+
113
+ it "on successful login the user should be redirected to the url he originally wanted" do
114
+ post "/test_return_to", :username => 'gizmo', :password => 'secret', :return_to_url => "http://example.org/blabla"
115
+ last_response.should redirect_to("http://example.org/blabla")
116
+ end
117
+
118
+ end
119
+
120
+ end
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'myapp.rb')
2
+ $: << APP_ROOT # for model reloading
3
+
4
+ require 'rack/test'
5
+ require 'rspec'
6
+
7
+ # set test environment
8
+ set :environment, :test
9
+ set :run, false
10
+ set :raise_errors, true
11
+ set :logging, false
12
+
13
+ module RSpecMixinExample
14
+ include Rack::Test::Methods
15
+ def app
16
+ @app ||= Sinatra::Application
17
+ end
18
+ end
19
+
20
+ Rspec.configure do |config|
21
+ config.send(:include, RSpecMixinExample)
22
+ config.send(:include, ::Sorcery::TestHelpers)
23
+ config.send(:include, ::Sorcery::TestHelpers::Sinatra)
24
+ config.before(:suite) do
25
+ ActiveRecord::Migrator.migrate("#{APP_ROOT}/db/migrate/core")
26
+ end
27
+
28
+ config.after(:suite) do
29
+ ActiveRecord::Migrator.rollback("#{APP_ROOT}/db/migrate/core")
30
+ end
31
+
32
+ end
33
+
34
+ # needed when running individual specs
35
+ require File.join(File.dirname(__FILE__), '..','user')
36
+ require File.join(File.dirname(__FILE__), '..','authentication')
37
+
38
+ class TestUser < ActiveRecord::Base
39
+ activate_sorcery!
40
+ end
41
+
42
+ class TestMailer < ActionMailer::Base
43
+
44
+ end
@@ -0,0 +1,188 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../sorcery_mailer')
3
+
4
+ describe "User with activation submodule" do
5
+ before(:all) do
6
+ ActiveRecord::Migrator.migrate("#{APP_ROOT}/db/migrate/activation")
7
+ end
8
+
9
+ after(:all) do
10
+ ActiveRecord::Migrator.rollback("#{APP_ROOT}/db/migrate/activation")
11
+ end
12
+
13
+ # ----------------- PLUGIN CONFIGURATION -----------------------
14
+ describe User, "loaded plugin configuration" do
15
+ before(:all) do
16
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
17
+ end
18
+
19
+ after(:each) do
20
+ User.sorcery_config.reset!
21
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
22
+ end
23
+
24
+ it "should enable configuration option 'activation_state_attribute_name'" do
25
+ sorcery_model_property_set(:activation_state_attribute_name, :status)
26
+ User.sorcery_config.activation_state_attribute_name.should equal(:status)
27
+ end
28
+
29
+ it "should enable configuration option 'activation_token_attribute_name'" do
30
+ sorcery_model_property_set(:activation_token_attribute_name, :code)
31
+ User.sorcery_config.activation_token_attribute_name.should equal(:code)
32
+ end
33
+
34
+ it "should enable configuration option 'user_activation_mailer'" do
35
+ sorcery_model_property_set(:user_activation_mailer, TestMailer)
36
+ User.sorcery_config.user_activation_mailer.should equal(TestMailer)
37
+ end
38
+
39
+ it "should enable configuration option 'activation_needed_email_method_name'" do
40
+ sorcery_model_property_set(:activation_needed_email_method_name, :my_activation_email)
41
+ User.sorcery_config.activation_needed_email_method_name.should equal(:my_activation_email)
42
+ end
43
+
44
+ it "should enable configuration option 'activation_success_email_method_name'" do
45
+ sorcery_model_property_set(:activation_success_email_method_name, :my_activation_email)
46
+ User.sorcery_config.activation_success_email_method_name.should equal(:my_activation_email)
47
+ end
48
+
49
+ it "if mailer is nil on activation, throw exception!" do
50
+ expect{sorcery_reload!([:user_activation])}.to raise_error(ArgumentError)
51
+ end
52
+ end
53
+
54
+ # ----------------- ACTIVATION PROCESS -----------------------
55
+ describe User, "activation process" do
56
+ before(:all) do
57
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
58
+ end
59
+
60
+ it "should generate an activation code on registration" do
61
+ create_new_user
62
+ @user.activation_token.should_not be_nil
63
+ end
64
+
65
+ it "should initialize user state to 'pending'" do
66
+ create_new_user
67
+ @user.activation_state.should == "pending"
68
+ end
69
+
70
+ it "should respond to 'activate!'" do
71
+ create_new_user
72
+ @user.should respond_to(:activate!)
73
+ end
74
+
75
+ it "should clear activation code and change state to 'active' on activation" do
76
+ create_new_user
77
+ activation_token = @user.activation_token
78
+ @user.activate!
79
+ @user2 = User.find(@user.id) # go to db to make sure it was saved and not just in memory
80
+ @user2.activation_token.should be_nil
81
+ @user2.activation_state.should == "active"
82
+ User.find_by_activation_token(activation_token).should be_nil
83
+ end
84
+
85
+ it "should send the user an activation email" do
86
+ old_size = ActionMailer::Base.deliveries.size
87
+ create_new_user
88
+ ActionMailer::Base.deliveries.size.should == old_size + 1
89
+ end
90
+
91
+ it "subsequent saves do not send activation email" do
92
+ create_new_user
93
+ old_size = ActionMailer::Base.deliveries.size
94
+ @user.username = "Shauli"
95
+ @user.save!
96
+ ActionMailer::Base.deliveries.size.should == old_size
97
+ end
98
+
99
+ it "should send the user an activation success email on successful activation" do
100
+ create_new_user
101
+ old_size = ActionMailer::Base.deliveries.size
102
+ @user.activate!
103
+ ActionMailer::Base.deliveries.size.should == old_size + 1
104
+ end
105
+
106
+ it "subsequent saves do not send activation success email" do
107
+ create_new_user
108
+ @user.activate!
109
+ old_size = ActionMailer::Base.deliveries.size
110
+ @user.username = "Shauli"
111
+ @user.save!
112
+ ActionMailer::Base.deliveries.size.should == old_size
113
+ end
114
+
115
+ it "activation needed email is optional" do
116
+ sorcery_model_property_set(:activation_needed_email_method_name, nil)
117
+ old_size = ActionMailer::Base.deliveries.size
118
+ create_new_user
119
+ ActionMailer::Base.deliveries.size.should == old_size
120
+ end
121
+
122
+ it "activation success email is optional" do
123
+ sorcery_model_property_set(:activation_success_email_method_name, nil)
124
+ create_new_user
125
+ old_size = ActionMailer::Base.deliveries.size
126
+ @user.activate!
127
+ ActionMailer::Base.deliveries.size.should == old_size
128
+ end
129
+ end
130
+
131
+ describe User, "prevent non-active login feature" do
132
+ before(:all) do
133
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
134
+ end
135
+
136
+ it "should not allow a non-active user to authenticate" do
137
+ create_new_user
138
+ User.authenticate(@user.username,'secret').should be_false
139
+ end
140
+
141
+ it "should allow a non-active user to authenticate if configured so" do
142
+ create_new_user
143
+ sorcery_model_property_set(:prevent_non_active_users_to_login, false)
144
+ User.authenticate(@user.username,'secret').should be_true
145
+ end
146
+ end
147
+
148
+ describe User, "load_from_activation_token" do
149
+ before(:all) do
150
+ sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
151
+ end
152
+
153
+ it "load_from_activation_token should return user when token is found" do
154
+ create_new_user
155
+ User.load_from_activation_token(@user.activation_token).should == @user
156
+ end
157
+
158
+ it "load_from_activation_token should NOT return user when token is NOT found" do
159
+ create_new_user
160
+ User.load_from_activation_token("a").should == nil
161
+ end
162
+
163
+ it "load_from_activation_token should return user when token is found and not expired" do
164
+ sorcery_model_property_set(:activation_token_expiration_period, 500)
165
+ create_new_user
166
+ User.load_from_activation_token(@user.activation_token).should == @user
167
+ end
168
+
169
+ it "load_from_activation_token should NOT return user when token is found and expired" do
170
+ sorcery_model_property_set(:activation_token_expiration_period, 0.1)
171
+ create_new_user
172
+ sleep 0.5
173
+ User.load_from_activation_token(@user.activation_token).should == nil
174
+ end
175
+
176
+ it "load_from_activation_token should return nil if token is blank" do
177
+ User.load_from_activation_token(nil).should == nil
178
+ User.load_from_activation_token("").should == nil
179
+ end
180
+
181
+ it "load_from_activation_token should always be valid if expiration period is nil" do
182
+ sorcery_model_property_set(:activation_token_expiration_period, nil)
183
+ create_new_user
184
+ User.load_from_activation_token(@user.activation_token).should == @user
185
+ end
186
+ end
187
+
188
+ end