sorcery 0.1.4 → 0.3.1
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/Gemfile +4 -2
- data/Gemfile.lock +16 -13
- data/README.rdoc +149 -78
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +24 -0
- data/lib/generators/sorcery_migration/templates/activity_logging.rb +17 -0
- data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +11 -0
- data/lib/generators/sorcery_migration/templates/core.rb +16 -0
- data/lib/generators/sorcery_migration/templates/external.rb +14 -0
- data/lib/generators/sorcery_migration/templates/remember_me.rb +15 -0
- data/lib/generators/sorcery_migration/templates/reset_password.rb +13 -0
- data/lib/generators/sorcery_migration/templates/user_activation.rb +17 -0
- data/lib/sorcery/controller/adapters/sinatra.rb +97 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +20 -7
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +9 -2
- data/lib/sorcery/controller/submodules/email.rb +44 -0
- data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +35 -0
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +26 -0
- data/lib/sorcery/controller/submodules/external/providers/facebook.rb +82 -0
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +86 -0
- data/lib/sorcery/controller/submodules/external.rb +83 -0
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +18 -9
- data/lib/sorcery/controller/submodules/oauth.rb +95 -0
- data/lib/sorcery/controller/submodules/remember_me.rb +14 -5
- data/lib/sorcery/controller/submodules/session_timeout.rb +6 -1
- data/lib/sorcery/controller.rb +30 -16
- data/lib/sorcery/engine.rb +9 -2
- data/lib/sorcery/model/submodules/activity_logging.rb +13 -8
- data/lib/sorcery/model/submodules/brute_force_protection.rb +11 -8
- data/lib/sorcery/model/submodules/external.rb +53 -0
- data/lib/sorcery/model/submodules/remember_me.rb +5 -3
- data/lib/sorcery/model/submodules/reset_password.rb +16 -13
- data/lib/sorcery/model/submodules/user_activation.rb +38 -19
- data/lib/sorcery/model/temporary_token.rb +22 -0
- data/lib/sorcery/model.rb +17 -7
- data/lib/sorcery/sinatra.rb +14 -0
- data/lib/sorcery/test_helpers/rails.rb +57 -0
- data/lib/sorcery/test_helpers/sinatra.rb +131 -0
- data/lib/sorcery/test_helpers.rb +40 -0
- data/lib/sorcery.rb +22 -0
- data/sorcery.gemspec +146 -41
- data/spec/Gemfile +3 -2
- data/spec/Gemfile.lock +15 -2
- data/spec/rails3/app_root/.rspec +1 -0
- data/spec/rails3/{Gemfile → app_root/Gemfile} +4 -4
- data/spec/rails3/{Gemfile.lock → app_root/Gemfile.lock} +23 -3
- data/spec/rails3/app_root/app/controllers/application_controller.rb +42 -1
- data/spec/rails3/app_root/app/models/authentication.rb +3 -0
- data/spec/rails3/app_root/app/models/user.rb +4 -1
- data/spec/rails3/app_root/config/application.rb +1 -3
- data/spec/rails3/app_root/config/routes.rb +1 -10
- data/spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb +6 -4
- data/spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb +4 -4
- data/spec/rails3/app_root/db/migrate/external/20101224223628_create_authentications.rb +14 -0
- data/spec/rails3/{controller_activity_logging_spec.rb → app_root/spec/controller_activity_logging_spec.rb} +13 -13
- data/spec/rails3/{controller_brute_force_protection_spec.rb → app_root/spec/controller_brute_force_protection_spec.rb} +16 -6
- data/spec/rails3/{controller_http_basic_auth_spec.rb → app_root/spec/controller_http_basic_auth_spec.rb} +3 -3
- data/spec/rails3/app_root/spec/controller_oauth2_spec.rb +119 -0
- data/spec/rails3/app_root/spec/controller_oauth_spec.rb +122 -0
- data/spec/rails3/{controller_remember_me_spec.rb → app_root/spec/controller_remember_me_spec.rb} +4 -4
- data/spec/rails3/{controller_session_timeout_spec.rb → app_root/spec/controller_session_timeout_spec.rb} +6 -6
- data/spec/rails3/{controller_spec.rb → app_root/spec/controller_spec.rb} +20 -13
- data/spec/rails3/app_root/spec/spec_helper.orig.rb +27 -0
- data/spec/rails3/app_root/spec/spec_helper.rb +62 -0
- data/spec/rails3/{user_activation_spec.rb → app_root/spec/user_activation_spec.rb} +60 -20
- data/spec/rails3/{user_activity_logging_spec.rb → app_root/spec/user_activity_logging_spec.rb} +4 -4
- data/spec/rails3/{user_brute_force_protection_spec.rb → app_root/spec/user_brute_force_protection_spec.rb} +7 -7
- data/spec/rails3/app_root/spec/user_oauth_spec.rb +39 -0
- data/spec/rails3/{user_remember_me_spec.rb → app_root/spec/user_remember_me_spec.rb} +4 -4
- data/spec/rails3/{user_reset_password_spec.rb → app_root/spec/user_reset_password_spec.rb} +21 -41
- data/spec/rails3/app_root/spec/user_spec.rb +317 -0
- data/spec/sinatra/Gemfile +12 -0
- data/spec/sinatra/Gemfile.lock +134 -0
- data/spec/sinatra/Rakefile +10 -0
- data/spec/sinatra/authentication.rb +3 -0
- data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
- data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
- data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
- data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +16 -0
- data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +14 -0
- data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
- data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
- data/spec/sinatra/filters.rb +21 -0
- data/spec/sinatra/myapp.rb +133 -0
- data/spec/sinatra/sorcery_mailer.rb +25 -0
- data/spec/sinatra/spec/controller_activity_logging_spec.rb +85 -0
- data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +69 -0
- data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +53 -0
- data/spec/sinatra/spec/controller_oauth2_spec.rb +119 -0
- data/spec/sinatra/spec/controller_oauth_spec.rb +121 -0
- data/spec/sinatra/spec/controller_remember_me_spec.rb +64 -0
- data/spec/sinatra/spec/controller_session_timeout_spec.rb +52 -0
- data/spec/sinatra/spec/controller_spec.rb +120 -0
- data/spec/sinatra/spec/spec.opts +4 -0
- data/spec/sinatra/spec/spec_helper.rb +44 -0
- data/spec/sinatra/spec/user_activation_spec.rb +188 -0
- data/spec/sinatra/spec/user_activity_logging_spec.rb +36 -0
- data/spec/sinatra/spec/user_brute_force_protection_spec.rb +76 -0
- data/spec/sinatra/spec/user_oauth_spec.rb +39 -0
- data/spec/sinatra/spec/user_remember_me_spec.rb +66 -0
- data/spec/sinatra/spec/user_reset_password_spec.rb +178 -0
- data/spec/{rails3 → sinatra/spec}/user_spec.rb +68 -38
- data/spec/sinatra/user.rb +6 -0
- data/spec/sinatra/views/test_login.erb +4 -0
- data/spec/untitled folder +18 -0
- metadata +203 -58
- data/spec/rails3/app_root/test/fixtures/users.yml +0 -9
- data/spec/rails3/app_root/test/performance/browsing_test.rb +0 -9
- data/spec/rails3/app_root/test/test_helper.rb +0 -13
- data/spec/rails3/app_root/test/unit/user_test.rb +0 -8
- data/spec/rails3/spec_helper.rb +0 -135
- /data/spec/rails3/{Rakefile → app_root/Rakefile} +0 -0
|
@@ -13,7 +13,7 @@ describe "User with reset_password submodule" do
|
|
|
13
13
|
describe User, "loaded plugin configuration" do
|
|
14
14
|
|
|
15
15
|
before(:all) do
|
|
16
|
-
|
|
16
|
+
sorcery_reload!([:reset_password], :reset_password_mailer => ::SorceryMailer)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
after(:each) do
|
|
@@ -25,11 +25,6 @@ describe "User with reset_password submodule" do
|
|
|
25
25
|
@user.should respond_to(:deliver_reset_password_instructions!)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
it "should respond to 'reset_password_token_valid?'" do
|
|
29
|
-
create_new_user
|
|
30
|
-
@user.should respond_to(:reset_password_token_valid?)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
28
|
it "should respond to 'reset_password!" do
|
|
34
29
|
create_new_user
|
|
35
30
|
@user.should respond_to(:reset_password!)
|
|
@@ -41,32 +36,32 @@ describe "User with reset_password submodule" do
|
|
|
41
36
|
end
|
|
42
37
|
|
|
43
38
|
it "should allow configuration option 'reset_password_token_attribute_name'" do
|
|
44
|
-
|
|
39
|
+
sorcery_model_property_set(:reset_password_token_attribute_name, :my_code)
|
|
45
40
|
User.sorcery_config.reset_password_token_attribute_name.should equal(:my_code)
|
|
46
41
|
end
|
|
47
42
|
|
|
48
43
|
it "should allow configuration option 'reset_password_mailer'" do
|
|
49
|
-
|
|
44
|
+
sorcery_model_property_set(:reset_password_mailer, TestUser)
|
|
50
45
|
User.sorcery_config.reset_password_mailer.should equal(TestUser)
|
|
51
46
|
end
|
|
52
47
|
|
|
53
48
|
it "should allow configuration option 'reset_password_email_method_name'" do
|
|
54
|
-
|
|
49
|
+
sorcery_model_property_set(:reset_password_email_method_name, :my_mailer_method)
|
|
55
50
|
User.sorcery_config.reset_password_email_method_name.should equal(:my_mailer_method)
|
|
56
51
|
end
|
|
57
52
|
|
|
58
53
|
it "should allow configuration option 'reset_password_expiration_period'" do
|
|
59
|
-
|
|
54
|
+
sorcery_model_property_set(:reset_password_expiration_period, 16)
|
|
60
55
|
User.sorcery_config.reset_password_expiration_period.should equal(16)
|
|
61
56
|
end
|
|
62
57
|
|
|
63
58
|
it "should allow configuration option 'reset_password_email_sent_at_attribute_name'" do
|
|
64
|
-
|
|
59
|
+
sorcery_model_property_set(:reset_password_email_sent_at_attribute_name, :blabla)
|
|
65
60
|
User.sorcery_config.reset_password_email_sent_at_attribute_name.should equal(:blabla)
|
|
66
61
|
end
|
|
67
62
|
|
|
68
63
|
it "should allow configuration option 'reset_password_time_between_emails'" do
|
|
69
|
-
|
|
64
|
+
sorcery_model_property_set(:reset_password_time_between_emails, 16)
|
|
70
65
|
User.sorcery_config.reset_password_time_between_emails.should equal(16)
|
|
71
66
|
end
|
|
72
67
|
end
|
|
@@ -75,7 +70,7 @@ describe "User with reset_password submodule" do
|
|
|
75
70
|
describe User, "when activated with sorcery" do
|
|
76
71
|
|
|
77
72
|
before(:all) do
|
|
78
|
-
|
|
73
|
+
sorcery_reload!([:reset_password], :reset_password_mailer => ::SorceryMailer)
|
|
79
74
|
end
|
|
80
75
|
|
|
81
76
|
before(:each) do
|
|
@@ -96,19 +91,26 @@ describe "User with reset_password submodule" do
|
|
|
96
91
|
|
|
97
92
|
it "load_from_reset_password_token should return user when token is found and not expired" do
|
|
98
93
|
create_new_user
|
|
99
|
-
|
|
94
|
+
sorcery_model_property_set(:reset_password_expiration_period, 500)
|
|
100
95
|
@user.deliver_reset_password_instructions!
|
|
101
96
|
User.load_from_reset_password_token(@user.reset_password_token).should == @user
|
|
102
97
|
end
|
|
103
98
|
|
|
104
99
|
it "load_from_reset_password_token should NOT return user when token is found and expired" do
|
|
105
100
|
create_new_user
|
|
106
|
-
|
|
101
|
+
sorcery_model_property_set(:reset_password_expiration_period, 0.1)
|
|
107
102
|
@user.deliver_reset_password_instructions!
|
|
108
103
|
sleep 0.5
|
|
109
104
|
User.load_from_reset_password_token(@user.reset_password_token).should == nil
|
|
110
105
|
end
|
|
111
106
|
|
|
107
|
+
it "load_from_reset_password_token should always be valid if expiration period is nil" do
|
|
108
|
+
create_new_user
|
|
109
|
+
sorcery_model_property_set(:reset_password_expiration_period, nil)
|
|
110
|
+
@user.deliver_reset_password_instructions!
|
|
111
|
+
User.load_from_reset_password_token(@user.reset_password_token).should == @user
|
|
112
|
+
end
|
|
113
|
+
|
|
112
114
|
it "load_from_reset_password_token should return nil if token is blank" do
|
|
113
115
|
User.load_from_reset_password_token(nil).should == nil
|
|
114
116
|
User.load_from_reset_password_token("").should == nil
|
|
@@ -123,7 +125,7 @@ describe "User with reset_password submodule" do
|
|
|
123
125
|
|
|
124
126
|
it "the reset_password_token should be random" do
|
|
125
127
|
create_new_user
|
|
126
|
-
|
|
128
|
+
sorcery_model_property_set(:reset_password_time_between_emails, 0)
|
|
127
129
|
@user.deliver_reset_password_instructions!
|
|
128
130
|
old_password_code = @user.reset_password_token
|
|
129
131
|
@user.deliver_reset_password_instructions!
|
|
@@ -146,31 +148,9 @@ describe "User with reset_password submodule" do
|
|
|
146
148
|
@user.reset_password_token.should be_nil
|
|
147
149
|
end
|
|
148
150
|
|
|
149
|
-
it "code isn't valid if expiration passed" do
|
|
150
|
-
create_new_user
|
|
151
|
-
plugin_set_model_config_property(:reset_password_expiration_period, 0.1)
|
|
152
|
-
@user.deliver_reset_password_instructions!
|
|
153
|
-
sleep 0.5
|
|
154
|
-
@user.reset_password_token_valid?.should == false
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
it "code is valid if it's the same code and expiration period did not pass" do
|
|
158
|
-
create_new_user
|
|
159
|
-
plugin_set_model_config_property(:reset_password_expiration_period, 300)
|
|
160
|
-
@user.deliver_reset_password_instructions!
|
|
161
|
-
@user.reset_password_token_valid?.should == true
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
it "code is valid if it's the same code and expiration period is nil" do
|
|
165
|
-
create_new_user
|
|
166
|
-
plugin_set_model_config_property(:reset_password_expiration_period, nil)
|
|
167
|
-
@user.deliver_reset_password_instructions!
|
|
168
|
-
@user.reset_password_token_valid?.should == true
|
|
169
|
-
end
|
|
170
|
-
|
|
171
151
|
it "should not send an email if time between emails has not passed since last email" do
|
|
172
152
|
create_new_user
|
|
173
|
-
|
|
153
|
+
sorcery_model_property_set(:reset_password_time_between_emails, 10000)
|
|
174
154
|
old_size = ActionMailer::Base.deliveries.size
|
|
175
155
|
@user.deliver_reset_password_instructions!
|
|
176
156
|
ActionMailer::Base.deliveries.size.should == old_size + 1
|
|
@@ -180,7 +160,7 @@ describe "User with reset_password submodule" do
|
|
|
180
160
|
|
|
181
161
|
it "should send an email if time between emails has passed since last email" do
|
|
182
162
|
create_new_user
|
|
183
|
-
|
|
163
|
+
sorcery_model_property_set(:reset_password_time_between_emails, 0.5)
|
|
184
164
|
old_size = ActionMailer::Base.deliveries.size
|
|
185
165
|
@user.deliver_reset_password_instructions!
|
|
186
166
|
ActionMailer::Base.deliveries.size.should == old_size + 1
|
|
@@ -190,7 +170,7 @@ describe "User with reset_password submodule" do
|
|
|
190
170
|
end
|
|
191
171
|
|
|
192
172
|
it "if mailer is nil on activation, throw exception!" do
|
|
193
|
-
expect{
|
|
173
|
+
expect{sorcery_reload!([:reset_password])}.to raise_error(ArgumentError)
|
|
194
174
|
end
|
|
195
175
|
|
|
196
176
|
end
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../app/mailers/sorcery_mailer')
|
|
3
|
+
|
|
4
|
+
describe "User with no submodules (core)" do
|
|
5
|
+
before(:all) do
|
|
6
|
+
sorcery_reload!
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe User, "when app has plugin loaded" do
|
|
10
|
+
it "should respond to the plugin activation class method" do
|
|
11
|
+
ActiveRecord::Base.should respond_to(:activate_sorcery!)
|
|
12
|
+
User.should respond_to(:activate_sorcery!)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "plugin activation should yield config to block" do
|
|
16
|
+
User.activate_sorcery! do |config|
|
|
17
|
+
config.class.should == ::Sorcery::Model::Config
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# ----------------- PLUGIN ACTIVATION -----------------------
|
|
23
|
+
describe TestUser, "Testing activated class self-registration" do
|
|
24
|
+
it "should register itself as user_class if activated" do
|
|
25
|
+
TestUser.class_eval do
|
|
26
|
+
activate_sorcery!
|
|
27
|
+
end
|
|
28
|
+
::Sorcery::Controller::Config.user_class.should == TestUser
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# ----------------- PLUGIN CONFIGURATION -----------------------
|
|
33
|
+
describe User, "loaded plugin configuration" do
|
|
34
|
+
after(:each) do
|
|
35
|
+
User.sorcery_config.reset!
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should enable configuration option 'username_attribute_name'" do
|
|
39
|
+
sorcery_model_property_set(:username_attribute_name, :email)
|
|
40
|
+
User.sorcery_config.username_attribute_name.should equal(:email)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should enable configuration option 'password_attribute_name'" do
|
|
44
|
+
sorcery_model_property_set(:password_attribute_name, :mypassword)
|
|
45
|
+
User.sorcery_config.password_attribute_name.should equal(:mypassword)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should enable configuration option 'email_attribute_name'" do
|
|
49
|
+
sorcery_model_property_set(:email_attribute_name, :my_email)
|
|
50
|
+
User.sorcery_config.email_attribute_name.should equal(:my_email)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should enable configuration option 'crypted_password_attribute_name'" do
|
|
54
|
+
sorcery_model_property_set(:crypted_password_attribute_name, :password)
|
|
55
|
+
User.sorcery_config.crypted_password_attribute_name.should equal(:password)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should enable configuration option 'salt_attribute_name'" do
|
|
59
|
+
sorcery_model_property_set(:salt_attribute_name, :my_salt)
|
|
60
|
+
User.sorcery_config.salt_attribute_name.should equal(:my_salt)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should enable configuration option 'encryption_algorithm'" do
|
|
64
|
+
sorcery_model_property_set(:encryption_algorithm, :none)
|
|
65
|
+
User.sorcery_config.encryption_algorithm.should equal(:none)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should enable configuration option 'encryption_key'" do
|
|
69
|
+
sorcery_model_property_set(:encryption_key, 'asdadas424234242')
|
|
70
|
+
User.sorcery_config.encryption_key.should == 'asdadas424234242'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should enable configuration option 'custom_encryption_provider'" do
|
|
74
|
+
sorcery_model_property_set(:encryption_algorithm, :custom)
|
|
75
|
+
sorcery_model_property_set(:custom_encryption_provider, Array)
|
|
76
|
+
User.sorcery_config.custom_encryption_provider.should equal(Array)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should enable configuration option 'salt_join_token'" do
|
|
80
|
+
salt_join_token = "--%%*&-"
|
|
81
|
+
sorcery_model_property_set(:salt_join_token, salt_join_token)
|
|
82
|
+
User.sorcery_config.salt_join_token.should equal(salt_join_token)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should enable configuration option 'stretches'" do
|
|
86
|
+
stretches = 15
|
|
87
|
+
sorcery_model_property_set(:stretches, stretches)
|
|
88
|
+
User.sorcery_config.stretches.should equal(stretches)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# ----------------- PLUGIN ACTIVATED -----------------------
|
|
94
|
+
describe User, "when activated with sorcery" do
|
|
95
|
+
before(:all) do
|
|
96
|
+
sorcery_reload!()
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
before(:each) do
|
|
100
|
+
User.delete_all
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should respond to class method authenticate" do
|
|
104
|
+
ActiveRecord::Base.should_not respond_to(:authenticate)
|
|
105
|
+
User.should respond_to(:authenticate)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "authenticate should return true if credentials are good" do
|
|
109
|
+
create_new_user
|
|
110
|
+
User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "authenticate should return false if credentials are bad" do
|
|
114
|
+
create_new_user
|
|
115
|
+
User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'wrong!').should be_false
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should respond to the class method encrypt" do
|
|
119
|
+
User.should respond_to(:encrypt)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# ----------------- REGISTRATION -----------------------
|
|
124
|
+
describe User, "registration" do
|
|
125
|
+
|
|
126
|
+
before(:all) do
|
|
127
|
+
sorcery_reload!()
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
before(:each) do
|
|
131
|
+
User.delete_all
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "by default, encryption_provider should not be nil" do
|
|
135
|
+
User.sorcery_config.encryption_provider.should_not be_nil
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "should encrypt password when a new user is saved" do
|
|
139
|
+
create_new_user
|
|
140
|
+
User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should clear the virtual password field if the encryption process worked" do
|
|
144
|
+
create_new_user
|
|
145
|
+
@user.password.should be_nil
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "should not clear the virtual password field if save failed due to validity" do
|
|
149
|
+
create_new_user
|
|
150
|
+
User.class_eval do
|
|
151
|
+
validates_format_of :email, :with => /^(.)+@(.)+$/, :if => Proc.new {|r| r.email}, :message => "is invalid"
|
|
152
|
+
end
|
|
153
|
+
@user.password = 'blupush'
|
|
154
|
+
@user.email = 'asd'
|
|
155
|
+
@user.save
|
|
156
|
+
@user.password.should_not be_nil
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "should not clear the virtual password field if save failed due to exception" do
|
|
160
|
+
create_new_user
|
|
161
|
+
@user.password = 'blupush'
|
|
162
|
+
@user.username = nil
|
|
163
|
+
begin
|
|
164
|
+
@user.save # triggers SQL exception since username field is defined not null.
|
|
165
|
+
rescue
|
|
166
|
+
end
|
|
167
|
+
@user.password.should_not be_nil
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should not encrypt the password twice when a user is updated" do
|
|
171
|
+
create_new_user
|
|
172
|
+
@user.email = "blup@bla.com"
|
|
173
|
+
@user.save!
|
|
174
|
+
User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_true
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "should replace the crypted_password in case a new password is set" do
|
|
178
|
+
create_new_user
|
|
179
|
+
@user.password = 'new_secret'
|
|
180
|
+
@user.save!
|
|
181
|
+
User.sorcery_config.encryption_provider.matches?(@user.send(User.sorcery_config.crypted_password_attribute_name),'secret',@user.salt).should be_false
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# ----------------- PASSWORD ENCRYPTION -----------------------
|
|
187
|
+
describe User, "special encryption cases" do
|
|
188
|
+
before(:all) do
|
|
189
|
+
sorcery_reload!()
|
|
190
|
+
@text = "Some Text!"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
before(:each) do
|
|
194
|
+
User.delete_all
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
after(:each) do
|
|
198
|
+
User.sorcery_config.reset!
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "should work with no password encryption" do
|
|
202
|
+
sorcery_model_property_set(:encryption_algorithm, :none)
|
|
203
|
+
create_new_user
|
|
204
|
+
User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "should work with custom password encryption" do
|
|
208
|
+
class MyCrypto
|
|
209
|
+
def self.encrypt(*tokens)
|
|
210
|
+
tokens.flatten.join('').gsub(/e/,'A')
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def self.matches?(crypted,*tokens)
|
|
214
|
+
crypted = encrypt(*tokens)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
sorcery_model_property_set(:encryption_algorithm, :custom)
|
|
218
|
+
sorcery_model_property_set(:custom_encryption_provider, MyCrypto)
|
|
219
|
+
create_new_user
|
|
220
|
+
User.authenticate(@user.send(User.sorcery_config.username_attribute_name), 'secret').should be_true
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "if encryption algo is aes256, it should set key to crypto provider" do
|
|
224
|
+
sorcery_model_property_set(:encryption_algorithm, :aes256)
|
|
225
|
+
sorcery_model_property_set(:encryption_key, nil)
|
|
226
|
+
expect{User.encrypt(@text)}.to raise_error(ArgumentError)
|
|
227
|
+
sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343")
|
|
228
|
+
expect{User.encrypt(@text)}.to_not raise_error(ArgumentError)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "if encryption algo is aes256, it should set key to crypto provider, even if attributes are set in reverse" do
|
|
232
|
+
sorcery_model_property_set(:encryption_key, nil)
|
|
233
|
+
sorcery_model_property_set(:encryption_algorithm, :none)
|
|
234
|
+
sorcery_model_property_set(:encryption_key, "asd234dfs423fddsmndsflktsdf32343")
|
|
235
|
+
sorcery_model_property_set(:encryption_algorithm, :aes256)
|
|
236
|
+
expect{User.encrypt(@text)}.to_not raise_error(ArgumentError)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it "if encryption algo is md5 it should work" do
|
|
240
|
+
sorcery_model_property_set(:encryption_algorithm, :md5)
|
|
241
|
+
User.encrypt(@text).should == Sorcery::CryptoProviders::MD5.encrypt(@text)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
it "if encryption algo is sha1 it should work" do
|
|
245
|
+
sorcery_model_property_set(:encryption_algorithm, :sha1)
|
|
246
|
+
User.encrypt(@text).should == Sorcery::CryptoProviders::SHA1.encrypt(@text)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
it "if encryption algo is sha256 it should work" do
|
|
250
|
+
sorcery_model_property_set(:encryption_algorithm, :sha256)
|
|
251
|
+
User.encrypt(@text).should == Sorcery::CryptoProviders::SHA256.encrypt(@text)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it "if encryption algo is sha512 it should work" do
|
|
255
|
+
sorcery_model_property_set(:encryption_algorithm, :sha512)
|
|
256
|
+
User.encrypt(@text).should == Sorcery::CryptoProviders::SHA512.encrypt(@text)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it "salt should be random for each user and saved in db" do
|
|
260
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
261
|
+
create_new_user
|
|
262
|
+
@user.salt.should_not be_nil
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it "if salt is set should use it to encrypt" do
|
|
266
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
267
|
+
sorcery_model_property_set(:encryption_algorithm, :sha512)
|
|
268
|
+
create_new_user
|
|
269
|
+
@user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
|
|
270
|
+
@user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "if salt_join_token is set should use it to encrypt" do
|
|
274
|
+
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
275
|
+
sorcery_model_property_set(:salt_join_token, "-@=>")
|
|
276
|
+
sorcery_model_property_set(:encryption_algorithm, :sha512)
|
|
277
|
+
create_new_user
|
|
278
|
+
@user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret')
|
|
279
|
+
Sorcery::CryptoProviders::SHA512.join_token = ""
|
|
280
|
+
@user.crypted_password.should_not == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
|
|
281
|
+
Sorcery::CryptoProviders::SHA512.join_token = User.sorcery_config.salt_join_token
|
|
282
|
+
@user.crypted_password.should == Sorcery::CryptoProviders::SHA512.encrypt('secret',@user.salt)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
describe User, "external users" do
|
|
288
|
+
before(:all) do
|
|
289
|
+
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/external")
|
|
290
|
+
sorcery_reload!()
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
after(:all) do
|
|
294
|
+
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/external")
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
before(:each) do
|
|
298
|
+
User.delete_all
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "should respond to 'external?'" do
|
|
302
|
+
create_new_user
|
|
303
|
+
@user.should respond_to(:external?)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it "external? should be false for regular users" do
|
|
307
|
+
create_new_user
|
|
308
|
+
@user.external?.should be_false
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it "external? should be true for external users" do
|
|
312
|
+
create_new_external_user(:twitter)
|
|
313
|
+
@user.external?.should be_true
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
source 'http://rubygems.org'
|
|
2
|
+
|
|
3
|
+
gem 'sinatra', '>= 1.2.0'
|
|
4
|
+
gem 'sqlite3-ruby', :require => 'sqlite3'
|
|
5
|
+
gem "sorcery", '0.3.1', :path => '../../'
|
|
6
|
+
|
|
7
|
+
group :development, :test do
|
|
8
|
+
gem 'rspec'
|
|
9
|
+
gem 'ruby-debug19'
|
|
10
|
+
gem 'simplecov', '>= 0.3.8', :require => false # Will install simplecov-html as a dependency
|
|
11
|
+
gem 'spork', '~> 0.9.0.rc'
|
|
12
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: ../../
|
|
3
|
+
specs:
|
|
4
|
+
sorcery (0.3.1)
|
|
5
|
+
bcrypt-ruby (~> 2.1.4)
|
|
6
|
+
json (>= 1.5.1)
|
|
7
|
+
oauth (>= 0.4.4)
|
|
8
|
+
oauth (>= 0.4.4)
|
|
9
|
+
oauth2 (>= 0.1.1)
|
|
10
|
+
oauth2 (>= 0.1.1)
|
|
11
|
+
rails (>= 3.0.0)
|
|
12
|
+
|
|
13
|
+
GEM
|
|
14
|
+
remote: http://rubygems.org/
|
|
15
|
+
specs:
|
|
16
|
+
abstract (1.0.0)
|
|
17
|
+
actionmailer (3.0.3)
|
|
18
|
+
actionpack (= 3.0.3)
|
|
19
|
+
mail (~> 2.2.9)
|
|
20
|
+
actionpack (3.0.3)
|
|
21
|
+
activemodel (= 3.0.3)
|
|
22
|
+
activesupport (= 3.0.3)
|
|
23
|
+
builder (~> 2.1.2)
|
|
24
|
+
erubis (~> 2.6.6)
|
|
25
|
+
i18n (~> 0.4)
|
|
26
|
+
rack (~> 1.2.1)
|
|
27
|
+
rack-mount (~> 0.6.13)
|
|
28
|
+
rack-test (~> 0.5.6)
|
|
29
|
+
tzinfo (~> 0.3.23)
|
|
30
|
+
activemodel (3.0.3)
|
|
31
|
+
activesupport (= 3.0.3)
|
|
32
|
+
builder (~> 2.1.2)
|
|
33
|
+
i18n (~> 0.4)
|
|
34
|
+
activerecord (3.0.3)
|
|
35
|
+
activemodel (= 3.0.3)
|
|
36
|
+
activesupport (= 3.0.3)
|
|
37
|
+
arel (~> 2.0.2)
|
|
38
|
+
tzinfo (~> 0.3.23)
|
|
39
|
+
activeresource (3.0.3)
|
|
40
|
+
activemodel (= 3.0.3)
|
|
41
|
+
activesupport (= 3.0.3)
|
|
42
|
+
activesupport (3.0.3)
|
|
43
|
+
addressable (2.2.4)
|
|
44
|
+
archive-tar-minitar (0.5.2)
|
|
45
|
+
arel (2.0.7)
|
|
46
|
+
bcrypt-ruby (2.1.4)
|
|
47
|
+
builder (2.1.2)
|
|
48
|
+
columnize (0.3.2)
|
|
49
|
+
diff-lcs (1.1.2)
|
|
50
|
+
erubis (2.6.6)
|
|
51
|
+
abstract (>= 1.0.0)
|
|
52
|
+
faraday (0.5.5)
|
|
53
|
+
addressable (~> 2.2.4)
|
|
54
|
+
multipart-post (~> 1.1.0)
|
|
55
|
+
rack (< 2, >= 1.1.0)
|
|
56
|
+
i18n (0.5.0)
|
|
57
|
+
json (1.5.1)
|
|
58
|
+
linecache19 (0.5.11)
|
|
59
|
+
ruby_core_source (>= 0.1.4)
|
|
60
|
+
mail (2.2.15)
|
|
61
|
+
activesupport (>= 2.3.6)
|
|
62
|
+
i18n (>= 0.4.0)
|
|
63
|
+
mime-types (~> 1.16)
|
|
64
|
+
treetop (~> 1.4.8)
|
|
65
|
+
mime-types (1.16)
|
|
66
|
+
multi_json (0.0.5)
|
|
67
|
+
multipart-post (1.1.0)
|
|
68
|
+
oauth (0.4.4)
|
|
69
|
+
oauth2 (0.1.1)
|
|
70
|
+
faraday (~> 0.5.0)
|
|
71
|
+
multi_json (~> 0.0.4)
|
|
72
|
+
polyglot (0.3.1)
|
|
73
|
+
rack (1.2.1)
|
|
74
|
+
rack-mount (0.6.13)
|
|
75
|
+
rack (>= 1.0.0)
|
|
76
|
+
rack-test (0.5.7)
|
|
77
|
+
rack (>= 1.0)
|
|
78
|
+
rails (3.0.3)
|
|
79
|
+
actionmailer (= 3.0.3)
|
|
80
|
+
actionpack (= 3.0.3)
|
|
81
|
+
activerecord (= 3.0.3)
|
|
82
|
+
activeresource (= 3.0.3)
|
|
83
|
+
activesupport (= 3.0.3)
|
|
84
|
+
bundler (~> 1.0)
|
|
85
|
+
railties (= 3.0.3)
|
|
86
|
+
railties (3.0.3)
|
|
87
|
+
actionpack (= 3.0.3)
|
|
88
|
+
activesupport (= 3.0.3)
|
|
89
|
+
rake (>= 0.8.7)
|
|
90
|
+
thor (~> 0.14.4)
|
|
91
|
+
rake (0.8.7)
|
|
92
|
+
rspec (2.4.0)
|
|
93
|
+
rspec-core (~> 2.4.0)
|
|
94
|
+
rspec-expectations (~> 2.4.0)
|
|
95
|
+
rspec-mocks (~> 2.4.0)
|
|
96
|
+
rspec-core (2.4.0)
|
|
97
|
+
rspec-expectations (2.4.0)
|
|
98
|
+
diff-lcs (~> 1.1.2)
|
|
99
|
+
rspec-mocks (2.4.0)
|
|
100
|
+
ruby-debug-base19 (0.11.24)
|
|
101
|
+
columnize (>= 0.3.1)
|
|
102
|
+
linecache19 (>= 0.5.11)
|
|
103
|
+
ruby_core_source (>= 0.1.4)
|
|
104
|
+
ruby-debug19 (0.11.6)
|
|
105
|
+
columnize (>= 0.3.1)
|
|
106
|
+
linecache19 (>= 0.5.11)
|
|
107
|
+
ruby-debug-base19 (>= 0.11.19)
|
|
108
|
+
ruby_core_source (0.1.4)
|
|
109
|
+
archive-tar-minitar (>= 0.5.2)
|
|
110
|
+
simplecov (0.3.9)
|
|
111
|
+
simplecov-html (>= 0.3.7)
|
|
112
|
+
simplecov-html (0.3.9)
|
|
113
|
+
sinatra (1.2.0)
|
|
114
|
+
rack (~> 1.1)
|
|
115
|
+
tilt (< 2.0, >= 1.2.2)
|
|
116
|
+
spork (0.9.0.rc3)
|
|
117
|
+
sqlite3-ruby (1.3.2)
|
|
118
|
+
thor (0.14.6)
|
|
119
|
+
tilt (1.2.2)
|
|
120
|
+
treetop (1.4.9)
|
|
121
|
+
polyglot (>= 0.3.1)
|
|
122
|
+
tzinfo (0.3.24)
|
|
123
|
+
|
|
124
|
+
PLATFORMS
|
|
125
|
+
ruby
|
|
126
|
+
|
|
127
|
+
DEPENDENCIES
|
|
128
|
+
rspec
|
|
129
|
+
ruby-debug19
|
|
130
|
+
simplecov (>= 0.3.8)
|
|
131
|
+
sinatra (>= 1.2.0)
|
|
132
|
+
sorcery (= 0.3.1)!
|
|
133
|
+
spork (~> 0.9.0.rc)
|
|
134
|
+
sqlite3-ruby
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class AddActivationToUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :users, :activation_state, :string, :default => nil
|
|
4
|
+
add_column :users, :activation_token, :string, :default => nil
|
|
5
|
+
add_column :users, :activation_token_expires_at, :datetime, :default => nil
|
|
6
|
+
|
|
7
|
+
add_index :users, :activation_token
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.down
|
|
11
|
+
remove_index :users, :activation_token
|
|
12
|
+
|
|
13
|
+
remove_column :users, :activation_token_expires_at
|
|
14
|
+
remove_column :users, :activation_token
|
|
15
|
+
remove_column :users, :activation_state
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class AddActivityLoggingToUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :users, :last_login_at, :datetime, :default => nil
|
|
4
|
+
add_column :users, :last_logout_at, :datetime, :default => nil
|
|
5
|
+
add_column :users, :last_activity_at, :datetime, :default => nil
|
|
6
|
+
|
|
7
|
+
add_index :users, [:last_logout_at, :last_activity_at]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.down
|
|
11
|
+
remove_index :users, [:last_logout_at, :last_activity_at]
|
|
12
|
+
|
|
13
|
+
remove_column :users, :last_activity_at
|
|
14
|
+
remove_column :users, :last_logout_at
|
|
15
|
+
remove_column :users, :last_login_at
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class AddBruteForceProtectionToUsers < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :users, :failed_logins_count, :integer, :default => 0
|
|
4
|
+
add_column :users, :lock_expires_at, :datetime, :default => nil
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.down
|
|
8
|
+
remove_column :users, :lock_expires_at
|
|
9
|
+
remove_column :users, :failed_logins_count
|
|
10
|
+
end
|
|
11
|
+
end
|