sorcery 0.8.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.travis.yml +122 -5
- data/CHANGELOG.md +37 -1
- data/Gemfile +10 -18
- data/README.md +159 -88
- data/gemfiles/active_record-rails40.gemfile +7 -0
- data/gemfiles/active_record-rails41.gemfile +7 -0
- data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
- data/gemfiles/mongo_mapper-rails41.gemfile +9 -0
- data/gemfiles/mongoid-rails40.gemfile +9 -0
- data/gemfiles/mongoid-rails41.gemfile +9 -0
- data/gemfiles/mongoid3-rails32.gemfile +9 -0
- data/lib/generators/sorcery/USAGE +1 -1
- data/lib/generators/sorcery/install_generator.rb +19 -5
- data/lib/generators/sorcery/templates/initializer.rb +34 -9
- data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
- data/lib/generators/sorcery/templates/migration/core.rb +2 -2
- data/lib/generators/sorcery/templates/migration/external.rb +3 -1
- data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
- data/lib/sorcery/adapters/base_adapter.rb +30 -0
- data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
- data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
- data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
- data/lib/sorcery/controller/config.rb +65 -0
- data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
- data/lib/sorcery/controller/submodules/external.rb +35 -40
- data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
- data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
- data/lib/sorcery/controller.rb +10 -74
- data/lib/sorcery/model/config.rb +96 -0
- data/lib/sorcery/model/submodules/activity_logging.rb +30 -13
- data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -21
- data/lib/sorcery/model/submodules/external.rb +53 -9
- data/lib/sorcery/model/submodules/remember_me.rb +15 -19
- data/lib/sorcery/model/submodules/reset_password.rb +33 -34
- data/lib/sorcery/model/submodules/user_activation.rb +36 -47
- data/lib/sorcery/model/temporary_token.rb +4 -4
- data/lib/sorcery/model.rb +73 -173
- data/lib/sorcery/protocols/oauth.rb +42 -0
- data/lib/sorcery/protocols/oauth2.rb +47 -0
- data/lib/sorcery/providers/base.rb +38 -0
- data/lib/sorcery/providers/facebook.rb +63 -0
- data/lib/sorcery/providers/github.rb +51 -0
- data/lib/sorcery/providers/google.rb +51 -0
- data/lib/sorcery/providers/heroku.rb +57 -0
- data/lib/sorcery/providers/jira.rb +77 -0
- data/lib/sorcery/providers/linkedin.rb +66 -0
- data/lib/sorcery/providers/liveid.rb +53 -0
- data/lib/sorcery/providers/salesforce.rb +50 -0
- data/lib/sorcery/providers/twitter.rb +59 -0
- data/lib/sorcery/providers/vk.rb +63 -0
- data/lib/sorcery/providers/xing.rb +64 -0
- data/lib/sorcery/test_helpers/internal/rails.rb +14 -3
- data/lib/sorcery/test_helpers/internal.rb +7 -3
- data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
- data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
- data/lib/sorcery/version.rb +3 -0
- data/lib/sorcery.rb +82 -58
- data/sorcery.gemspec +19 -19
- data/spec/active_record/user_activation_spec.rb +1 -1
- data/spec/active_record/user_activity_logging_spec.rb +10 -1
- data/spec/active_record/user_brute_force_protection_spec.rb +1 -1
- data/spec/active_record/user_oauth_spec.rb +1 -1
- data/spec/active_record/user_remember_me_spec.rb +1 -1
- data/spec/active_record/user_reset_password_spec.rb +1 -1
- data/spec/active_record/user_spec.rb +7 -8
- data/spec/controllers/controller_activity_logging_spec.rb +124 -0
- data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
- data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
- data/spec/controllers/controller_oauth2_spec.rb +414 -0
- data/spec/controllers/controller_oauth_spec.rb +240 -0
- data/spec/controllers/controller_remember_me_spec.rb +117 -0
- data/spec/controllers/controller_session_timeout_spec.rb +80 -0
- data/spec/controllers/controller_spec.rb +218 -0
- data/spec/data_mapper/user_activation_spec.rb +10 -0
- data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
- data/spec/data_mapper/user_brute_force_protection_spec.rb +9 -0
- data/spec/data_mapper/user_oauth_spec.rb +9 -0
- data/spec/data_mapper/user_remember_me_spec.rb +8 -0
- data/spec/data_mapper/user_reset_password_spec.rb +8 -0
- data/spec/data_mapper/user_spec.rb +27 -0
- data/spec/mongo_mapper/user_activation_spec.rb +1 -2
- data/spec/mongo_mapper/user_activity_logging_spec.rb +1 -1
- data/spec/mongo_mapper/user_brute_force_protection_spec.rb +1 -1
- data/spec/mongo_mapper/user_oauth_spec.rb +1 -1
- data/spec/mongo_mapper/user_remember_me_spec.rb +1 -1
- data/spec/mongo_mapper/user_reset_password_spec.rb +1 -1
- data/spec/mongo_mapper/user_spec.rb +7 -8
- data/spec/mongoid/user_activation_spec.rb +1 -2
- data/spec/mongoid/user_activity_logging_spec.rb +1 -2
- data/spec/mongoid/user_brute_force_protection_spec.rb +1 -2
- data/spec/mongoid/user_oauth_spec.rb +1 -2
- data/spec/mongoid/user_remember_me_spec.rb +1 -2
- data/spec/mongoid/user_reset_password_spec.rb +1 -2
- data/spec/mongoid/user_spec.rb +21 -9
- data/spec/orm/active_record.rb +14 -0
- data/spec/orm/data_mapper.rb +48 -0
- data/spec/orm/mongo_mapper.rb +1 -1
- data/spec/orm/mongoid.rb +5 -0
- data/spec/rails_app/app/controllers/sorcery_controller.rb +125 -59
- data/spec/rails_app/app/data_mapper/authentication.rb +8 -0
- data/spec/rails_app/app/data_mapper/user.rb +7 -0
- data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
- data/spec/rails_app/config/routes.rb +27 -13
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
- data/spec/shared_examples/user_activation_shared_examples.rb +108 -91
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +83 -15
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +140 -21
- data/spec/shared_examples/user_oauth_shared_examples.rb +21 -16
- data/spec/shared_examples/user_remember_me_shared_examples.rb +36 -24
- data/spec/shared_examples/user_reset_password_shared_examples.rb +138 -117
- data/spec/shared_examples/user_shared_examples.rb +297 -150
- data/spec/sorcery_crypto_providers_spec.rb +28 -28
- data/spec/spec_helper.rb +12 -18
- metadata +99 -165
- data/Gemfile.rails4 +0 -24
- data/VERSION +0 -1
- data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +0 -46
- data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +0 -50
- data/lib/sorcery/controller/submodules/external/providers/base.rb +0 -21
- data/lib/sorcery/controller/submodules/external/providers/facebook.rb +0 -99
- data/lib/sorcery/controller/submodules/external/providers/github.rb +0 -93
- data/lib/sorcery/controller/submodules/external/providers/google.rb +0 -92
- data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +0 -103
- data/lib/sorcery/controller/submodules/external/providers/liveid.rb +0 -93
- data/lib/sorcery/controller/submodules/external/providers/twitter.rb +0 -94
- data/lib/sorcery/controller/submodules/external/providers/vk.rb +0 -101
- data/lib/sorcery/controller/submodules/external/providers/xing.rb +0 -98
- data/lib/sorcery/model/adapters/active_record.rb +0 -49
- data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -56
- data/lib/sorcery/model/adapters/mongoid.rb +0 -88
- data/lib/sorcery/test_helpers/rails.rb +0 -16
- data/lib/sorcery/test_helpers.rb +0 -5
- data/spec/active_record/controller_activity_logging_spec.rb +0 -140
- data/spec/active_record/controller_brute_force_protection_spec.rb +0 -136
- data/spec/active_record/controller_http_basic_auth_spec.rb +0 -59
- data/spec/active_record/controller_oauth2_spec.rb +0 -417
- data/spec/active_record/controller_oauth_spec.rb +0 -212
- data/spec/active_record/controller_remember_me_spec.rb +0 -96
- data/spec/active_record/controller_session_timeout_spec.rb +0 -55
- data/spec/active_record/controller_spec.rb +0 -182
- data/spec/active_record/integration_spec.rb +0 -23
- data/spec/mongo_mapper/controller_spec.rb +0 -175
- data/spec/mongoid/controller_activity_logging_spec.rb +0 -111
- data/spec/mongoid/controller_spec.rb +0 -186
- data/spec/rails_app/public/404.html +0 -26
- data/spec/rails_app/public/422.html +0 -26
- data/spec/rails_app/public/500.html +0 -26
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/images/rails.png +0 -0
- data/spec/rails_app/public/javascripts/application.js +0 -2
- data/spec/rails_app/public/javascripts/controls.js +0 -965
- data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
- data/spec/rails_app/public/javascripts/effects.js +0 -1123
- data/spec/rails_app/public/javascripts/prototype.js +0 -6001
- data/spec/rails_app/public/javascripts/rails.js +0 -175
- data/spec/rails_app/public/robots.txt +0 -5
- data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
- data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -56
- data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -69
- /data/lib/sorcery/{controller/submodules/external/protocols → protocols}/certs/ca-bundle.crt +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
shared_examples_for "rails_3_activation_model" do
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
let(:user) { create_new_user }
|
|
3
|
+
let(:new_user) { build_new_user }
|
|
4
|
+
|
|
5
|
+
context "loaded plugin configuration" do
|
|
4
6
|
before(:all) do
|
|
5
7
|
sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
|
|
6
8
|
end
|
|
@@ -10,34 +12,40 @@ shared_examples_for "rails_3_activation_model" do
|
|
|
10
12
|
sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
it "
|
|
15
|
+
it "enables configuration option 'activation_state_attribute_name'" do
|
|
14
16
|
sorcery_model_property_set(:activation_state_attribute_name, :status)
|
|
15
|
-
|
|
17
|
+
|
|
18
|
+
expect(User.sorcery_config.activation_state_attribute_name).to eq :status
|
|
16
19
|
end
|
|
17
20
|
|
|
18
|
-
it "
|
|
21
|
+
it "enables configuration option 'activation_token_attribute_name'" do
|
|
19
22
|
sorcery_model_property_set(:activation_token_attribute_name, :code)
|
|
20
|
-
|
|
23
|
+
|
|
24
|
+
expect(User.sorcery_config.activation_token_attribute_name).to eql :code
|
|
21
25
|
end
|
|
22
26
|
|
|
23
|
-
it "
|
|
27
|
+
it "enables configuration option 'user_activation_mailer'" do
|
|
24
28
|
sorcery_model_property_set(:user_activation_mailer, TestMailer)
|
|
25
|
-
|
|
29
|
+
|
|
30
|
+
expect(User.sorcery_config.user_activation_mailer).to equal(TestMailer)
|
|
26
31
|
end
|
|
27
32
|
|
|
28
|
-
it "
|
|
33
|
+
it "enables configuration option 'activation_needed_email_method_name'" do
|
|
29
34
|
sorcery_model_property_set(:activation_needed_email_method_name, :my_activation_email)
|
|
30
|
-
|
|
35
|
+
|
|
36
|
+
expect(User.sorcery_config.activation_needed_email_method_name).to eq :my_activation_email
|
|
31
37
|
end
|
|
32
38
|
|
|
33
|
-
it "
|
|
39
|
+
it "enables configuration option 'activation_success_email_method_name'" do
|
|
34
40
|
sorcery_model_property_set(:activation_success_email_method_name, :my_activation_email)
|
|
35
|
-
|
|
41
|
+
|
|
42
|
+
expect(User.sorcery_config.activation_success_email_method_name).to eq :my_activation_email
|
|
36
43
|
end
|
|
37
44
|
|
|
38
|
-
it "
|
|
45
|
+
it "enables configuration option 'activation_mailer_disabled'" do
|
|
39
46
|
sorcery_model_property_set(:activation_mailer_disabled, :my_activation_mailer_disabled)
|
|
40
|
-
|
|
47
|
+
|
|
48
|
+
expect(User.sorcery_config.activation_mailer_disabled).to eq :my_activation_mailer_disabled
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
it "if mailer is nil and mailer is enabled, throw exception!" do
|
|
@@ -49,83 +57,88 @@ shared_examples_for "rails_3_activation_model" do
|
|
|
49
57
|
end
|
|
50
58
|
end
|
|
51
59
|
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
|
|
61
|
+
context "activation process" do
|
|
54
62
|
before(:all) do
|
|
55
63
|
sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
|
|
56
64
|
end
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
it "initializes user state to 'pending'" do
|
|
67
|
+
expect(user.activation_state).to eq "pending"
|
|
60
68
|
end
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
@user.activation_state.should == "pending"
|
|
64
|
-
end
|
|
70
|
+
specify { expect(user).to respond_to :activate! }
|
|
65
71
|
|
|
66
|
-
|
|
72
|
+
it "clears activation code and change state to 'active' on activation" do
|
|
73
|
+
activation_token = user.activation_token
|
|
74
|
+
user.activate!
|
|
75
|
+
user2 = User.sorcery_adapter.find(user.id) # go to db to make sure it was saved and not just in memory
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@user2 = User.find(@user.id) # go to db to make sure it was saved and not just in memory
|
|
72
|
-
@user2.activation_token.should be_nil
|
|
73
|
-
@user2.activation_state.should == "active"
|
|
74
|
-
User.find_by_activation_token(activation_token).should be_nil
|
|
77
|
+
expect(user2.activation_token).to be_nil
|
|
78
|
+
expect(user2.activation_state).to eq "active"
|
|
79
|
+
expect(User.sorcery_adapter.find_by_activation_token activation_token).to be_nil
|
|
75
80
|
end
|
|
76
81
|
|
|
77
82
|
|
|
78
83
|
context "mailer is enabled" do
|
|
79
|
-
it "
|
|
84
|
+
it "sends the user an activation email" do
|
|
80
85
|
old_size = ActionMailer::Base.deliveries.size
|
|
81
86
|
create_new_user
|
|
82
|
-
|
|
87
|
+
|
|
88
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
|
|
83
89
|
end
|
|
84
90
|
|
|
85
|
-
it "
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
it "calls send_activation_needed_email! method of user" do
|
|
92
|
+
expect(new_user).to receive(:send_activation_needed_email!).once
|
|
93
|
+
|
|
94
|
+
new_user.sorcery_adapter.save(:raise_on_failure => true)
|
|
89
95
|
end
|
|
90
96
|
|
|
91
97
|
it "subsequent saves do not send activation email" do
|
|
98
|
+
user
|
|
92
99
|
old_size = ActionMailer::Base.deliveries.size
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
user.email = "Shauli"
|
|
101
|
+
user.sorcery_adapter.save(:raise_on_failure => true)
|
|
102
|
+
|
|
103
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
96
104
|
end
|
|
97
105
|
|
|
98
|
-
it "
|
|
106
|
+
it "sends the user an activation success email on successful activation" do
|
|
107
|
+
user
|
|
99
108
|
old_size = ActionMailer::Base.deliveries.size
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
user.activate!
|
|
110
|
+
|
|
111
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
|
|
102
112
|
end
|
|
103
113
|
|
|
104
|
-
it "
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
it "calls send_activation_success_email! method of user on activation" do
|
|
115
|
+
expect(user).to receive(:send_activation_success_email!).once
|
|
116
|
+
|
|
117
|
+
user.activate!
|
|
107
118
|
end
|
|
108
119
|
|
|
109
120
|
it "subsequent saves do not send activation success email" do
|
|
110
|
-
|
|
121
|
+
user.activate!
|
|
111
122
|
old_size = ActionMailer::Base.deliveries.size
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
user.email = "Shauli"
|
|
124
|
+
user.sorcery_adapter.save(:raise_on_failure => true)
|
|
125
|
+
|
|
126
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
115
127
|
end
|
|
116
128
|
|
|
117
129
|
it "activation needed email is optional" do
|
|
118
130
|
sorcery_model_property_set(:activation_needed_email_method_name, nil)
|
|
119
131
|
old_size = ActionMailer::Base.deliveries.size
|
|
120
|
-
|
|
121
|
-
ActionMailer::Base.deliveries.size.
|
|
132
|
+
|
|
133
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
122
134
|
end
|
|
123
135
|
|
|
124
136
|
it "activation success email is optional" do
|
|
125
137
|
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
126
138
|
old_size = ActionMailer::Base.deliveries.size
|
|
127
|
-
|
|
128
|
-
|
|
139
|
+
user.activate!
|
|
140
|
+
|
|
141
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
129
142
|
end
|
|
130
143
|
end
|
|
131
144
|
|
|
@@ -134,52 +147,56 @@ shared_examples_for "rails_3_activation_model" do
|
|
|
134
147
|
sorcery_reload!([:user_activation], :activation_mailer_disabled => true, :user_activation_mailer => ::SorceryMailer)
|
|
135
148
|
end
|
|
136
149
|
|
|
137
|
-
it "
|
|
150
|
+
it "does not send the user an activation email" do
|
|
138
151
|
old_size = ActionMailer::Base.deliveries.size
|
|
139
|
-
|
|
140
|
-
ActionMailer::Base.deliveries.size.
|
|
152
|
+
|
|
153
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
141
154
|
end
|
|
142
155
|
|
|
143
|
-
it "
|
|
156
|
+
it "does not call send_activation_needed_email! method of user" do
|
|
144
157
|
user = build_new_user
|
|
145
|
-
|
|
146
|
-
user.
|
|
158
|
+
|
|
159
|
+
expect(user).to receive(:send_activation_needed_email!).never
|
|
160
|
+
|
|
161
|
+
user.sorcery_adapter.save(:raise_on_failure => true)
|
|
147
162
|
end
|
|
148
163
|
|
|
149
|
-
it "
|
|
164
|
+
it "does not send the user an activation success email on successful activation" do
|
|
150
165
|
old_size = ActionMailer::Base.deliveries.size
|
|
151
|
-
|
|
152
|
-
|
|
166
|
+
user.activate!
|
|
167
|
+
|
|
168
|
+
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
153
169
|
end
|
|
154
170
|
|
|
155
|
-
it "
|
|
156
|
-
|
|
157
|
-
|
|
171
|
+
it "calls send_activation_success_email! method of user on activation" do
|
|
172
|
+
expect(user).to receive(:send_activation_success_email!).never
|
|
173
|
+
|
|
174
|
+
user.activate!
|
|
158
175
|
end
|
|
159
176
|
end
|
|
160
177
|
end
|
|
161
178
|
|
|
162
|
-
describe
|
|
179
|
+
describe "prevent non-active login feature" do
|
|
163
180
|
before(:all) do
|
|
164
181
|
sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
|
|
165
182
|
end
|
|
166
183
|
|
|
167
184
|
before(:each) do
|
|
168
|
-
User.delete_all
|
|
169
|
-
create_new_user
|
|
185
|
+
User.sorcery_adapter.delete_all
|
|
170
186
|
end
|
|
171
187
|
|
|
172
|
-
it "
|
|
173
|
-
User.authenticate
|
|
188
|
+
it "does not allow a non-active user to authenticate" do
|
|
189
|
+
expect(User.authenticate user.email, 'secret').to be_falsy
|
|
174
190
|
end
|
|
175
191
|
|
|
176
|
-
it "
|
|
192
|
+
it "allows a non-active user to authenticate if configured so" do
|
|
177
193
|
sorcery_model_property_set(:prevent_non_active_users_to_login, false)
|
|
178
|
-
|
|
194
|
+
|
|
195
|
+
expect(User.authenticate user.email, 'secret').to be_truthy
|
|
179
196
|
end
|
|
180
197
|
end
|
|
181
198
|
|
|
182
|
-
describe
|
|
199
|
+
describe "load_from_activation_token" do
|
|
183
200
|
before(:all) do
|
|
184
201
|
sorcery_reload!([:user_activation], :user_activation_mailer => ::SorceryMailer)
|
|
185
202
|
end
|
|
@@ -188,38 +205,38 @@ shared_examples_for "rails_3_activation_model" do
|
|
|
188
205
|
Timecop.return
|
|
189
206
|
end
|
|
190
207
|
|
|
191
|
-
it "load_from_activation_token
|
|
192
|
-
|
|
193
|
-
User.load_from_activation_token(@user.activation_token).should == @user
|
|
208
|
+
it "load_from_activation_token returns user when token is found" do
|
|
209
|
+
expect(User.load_from_activation_token user.activation_token).to eq user
|
|
194
210
|
end
|
|
195
211
|
|
|
196
|
-
it "load_from_activation_token
|
|
197
|
-
|
|
198
|
-
User.load_from_activation_token("a").should == nil
|
|
212
|
+
it "load_from_activation_token does NOT return user when token is NOT found" do
|
|
213
|
+
expect(User.load_from_activation_token "a").to be_nil
|
|
199
214
|
end
|
|
200
215
|
|
|
201
|
-
it "load_from_activation_token
|
|
216
|
+
it "load_from_activation_token returas user when token is found and not expired" do
|
|
202
217
|
sorcery_model_property_set(:activation_token_expiration_period, 500)
|
|
203
|
-
|
|
204
|
-
User.load_from_activation_token
|
|
218
|
+
|
|
219
|
+
expect(User.load_from_activation_token user.activation_token).to eq user
|
|
205
220
|
end
|
|
206
221
|
|
|
207
|
-
it "load_from_activation_token
|
|
222
|
+
it "load_from_activation_token does NOT return user when token is found and expired" do
|
|
208
223
|
sorcery_model_property_set(:activation_token_expiration_period, 0.1)
|
|
209
|
-
|
|
224
|
+
user
|
|
225
|
+
|
|
210
226
|
Timecop.travel(Time.now.in_time_zone+0.5)
|
|
211
|
-
|
|
227
|
+
|
|
228
|
+
expect(User.load_from_activation_token user.activation_token).to be_nil
|
|
212
229
|
end
|
|
213
230
|
|
|
214
|
-
it "load_from_activation_token
|
|
215
|
-
User.load_from_activation_token
|
|
216
|
-
User.load_from_activation_token
|
|
231
|
+
it "load_from_activation_token returns nil if token is blank" do
|
|
232
|
+
expect(User.load_from_activation_token nil).to be_nil
|
|
233
|
+
expect(User.load_from_activation_token "").to be_nil
|
|
217
234
|
end
|
|
218
235
|
|
|
219
|
-
it "load_from_activation_token
|
|
236
|
+
it "load_from_activation_token is always valid if expiration period is nil" do
|
|
220
237
|
sorcery_model_property_set(:activation_token_expiration_period, nil)
|
|
221
|
-
|
|
222
|
-
User.load_from_activation_token
|
|
238
|
+
|
|
239
|
+
expect(User.load_from_activation_token user.activation_token).to eq user
|
|
223
240
|
end
|
|
224
241
|
end
|
|
225
|
-
end
|
|
242
|
+
end
|
|
@@ -1,32 +1,100 @@
|
|
|
1
1
|
shared_examples_for "rails_3_activity_logging_model" do
|
|
2
|
-
|
|
3
|
-
describe User, "loaded plugin configuration" do
|
|
2
|
+
context "loaded plugin configuration" do
|
|
4
3
|
before(:all) do
|
|
5
4
|
sorcery_reload!([:activity_logging])
|
|
6
5
|
end
|
|
7
|
-
|
|
6
|
+
|
|
8
7
|
after(:each) do
|
|
9
8
|
User.sorcery_config.reset!
|
|
10
9
|
end
|
|
11
|
-
|
|
12
|
-
it "
|
|
10
|
+
|
|
11
|
+
it "allows configuration option 'last_login_at_attribute_name'" do
|
|
13
12
|
sorcery_model_property_set(:last_login_at_attribute_name, :login_time)
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
expect(User.sorcery_config.last_login_at_attribute_name).to eq :login_time
|
|
15
15
|
end
|
|
16
|
-
|
|
17
|
-
it "
|
|
16
|
+
|
|
17
|
+
it "allows configuration option 'last_logout_at_attribute_name'" do
|
|
18
18
|
sorcery_model_property_set(:last_logout_at_attribute_name, :logout_time)
|
|
19
|
-
User.sorcery_config.last_logout_at_attribute_name.
|
|
19
|
+
expect(User.sorcery_config.last_logout_at_attribute_name).to eq :logout_time
|
|
20
20
|
end
|
|
21
|
-
|
|
22
|
-
it "
|
|
21
|
+
|
|
22
|
+
it "allows configuration option 'last_activity_at_attribute_name'" do
|
|
23
23
|
sorcery_model_property_set(:last_activity_at_attribute_name, :activity_time)
|
|
24
|
-
User.sorcery_config.last_activity_at_attribute_name.
|
|
24
|
+
expect(User.sorcery_config.last_activity_at_attribute_name).to eq :activity_time
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
it "
|
|
27
|
+
it "allows configuration option 'last_login_from_ip_adress'" do
|
|
28
28
|
sorcery_model_property_set(:last_login_from_ip_address_name, :ip_address)
|
|
29
|
-
User.sorcery_config.last_login_from_ip_address_name.
|
|
29
|
+
expect(User.sorcery_config.last_login_from_ip_address_name).to eq :ip_address
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe ".current_users" do
|
|
33
|
+
let(:user) { create_new_user }
|
|
34
|
+
|
|
35
|
+
it "is empty when no users are logged in" do
|
|
36
|
+
skip('unavailable in MongoMapper') if SORCERY_ORM == :mongo_mapper
|
|
37
|
+
expect(User.current_users).to be_empty
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "holds the user object when 1 user is logged in" do
|
|
41
|
+
skip('unavailable in MongoMapper') if SORCERY_ORM == :mongo_mapper
|
|
42
|
+
user.set_last_activity_at(Time.now.in_time_zone)
|
|
43
|
+
|
|
44
|
+
expect(User.current_users).to match([User.sorcery_adapter.find(user.id)])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "'current_users' shows all current_users, whether they have logged out before or not." do
|
|
48
|
+
skip('unavailable in MongoMapper') if SORCERY_ORM == :mongo_mapper
|
|
49
|
+
User.sorcery_adapter.delete_all
|
|
50
|
+
user1 = create_new_user({:username => 'gizmo1', :email => "bla1@bla.com", :password => 'secret1'})
|
|
51
|
+
user2 = create_new_user({:username => 'gizmo2', :email => "bla2@bla.com", :password => 'secret2'})
|
|
52
|
+
user3 = create_new_user({:username => 'gizmo3', :email => "bla3@bla.com", :password => 'secret3'})
|
|
53
|
+
|
|
54
|
+
now = Time.now.in_time_zone
|
|
55
|
+
[user1, user2, user3].each do |user|
|
|
56
|
+
user.set_last_login_at(now)
|
|
57
|
+
user.set_last_activity_at(now)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
expect(User.current_users.map(&:id)).to match_array([user1, user2, user3].map(&:id))
|
|
61
|
+
Timecop.travel now + 5
|
|
62
|
+
user1.set_last_logout_at(Time.now.in_time_zone)
|
|
63
|
+
expect(User.current_users.map(&:id)).to match_array([user2, user3].map(&:id))
|
|
64
|
+
Timecop.return
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it '.set_last_login_at update last_login_at' do
|
|
70
|
+
user = create_new_user
|
|
71
|
+
now = Time.now.in_time_zone
|
|
72
|
+
expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_login_at, now)
|
|
73
|
+
|
|
74
|
+
user.set_last_login_at(now)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it '.set_last_logout_at update last_logout_at' do
|
|
78
|
+
user = create_new_user
|
|
79
|
+
now = Time.now.in_time_zone
|
|
80
|
+
expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_logout_at, now)
|
|
81
|
+
|
|
82
|
+
user.set_last_logout_at(now)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it '.set_last_activity_at update last_activity_at' do
|
|
86
|
+
user = create_new_user
|
|
87
|
+
now = Time.now.in_time_zone
|
|
88
|
+
expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_activity_at, now)
|
|
89
|
+
|
|
90
|
+
user.set_last_activity_at(now)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it '.set_last_ip_addess update last_login_from_ip_address' do
|
|
94
|
+
user = create_new_user
|
|
95
|
+
expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_login_from_ip_address, '0.0.0.0')
|
|
96
|
+
|
|
97
|
+
user.set_last_ip_addess('0.0.0.0')
|
|
30
98
|
end
|
|
31
99
|
end
|
|
32
|
-
end
|
|
100
|
+
end
|
|
@@ -1,37 +1,156 @@
|
|
|
1
1
|
shared_examples_for "rails_3_brute_force_protection_model" do
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
let(:user) { create_new_user }
|
|
3
|
+
before(:each) do
|
|
4
|
+
User.sorcery_adapter.delete_all
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
context "loaded plugin configuration" do
|
|
9
|
+
|
|
10
|
+
let(:config) { User.sorcery_config }
|
|
11
|
+
|
|
5
12
|
before(:all) do
|
|
6
13
|
sorcery_reload!([:brute_force_protection])
|
|
7
|
-
create_new_user
|
|
8
14
|
end
|
|
9
|
-
|
|
15
|
+
|
|
10
16
|
after(:each) do
|
|
11
17
|
User.sorcery_config.reset!
|
|
12
18
|
end
|
|
13
|
-
|
|
14
|
-
specify {
|
|
15
|
-
specify {
|
|
16
|
-
|
|
17
|
-
it "
|
|
19
|
+
|
|
20
|
+
specify { expect(user).to respond_to(:failed_logins_count) }
|
|
21
|
+
specify { expect(user).to respond_to(:lock_expires_at) }
|
|
22
|
+
|
|
23
|
+
it "enables configuration option 'failed_logins_count_attribute_name'" do
|
|
18
24
|
sorcery_model_property_set(:failed_logins_count_attribute_name, :my_count)
|
|
19
|
-
|
|
25
|
+
expect(config.failed_logins_count_attribute_name).to eq :my_count
|
|
20
26
|
end
|
|
21
|
-
|
|
22
|
-
it "
|
|
27
|
+
|
|
28
|
+
it "enables configuration option 'lock_expires_at_attribute_name'" do
|
|
23
29
|
sorcery_model_property_set(:lock_expires_at_attribute_name, :expires)
|
|
24
|
-
|
|
30
|
+
expect(config.lock_expires_at_attribute_name).to eq :expires
|
|
25
31
|
end
|
|
26
|
-
|
|
27
|
-
it "
|
|
32
|
+
|
|
33
|
+
it "enables configuration option 'consecutive_login_retries_amount_allowed'" do
|
|
28
34
|
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 34)
|
|
29
|
-
|
|
35
|
+
expect(config.consecutive_login_retries_amount_limit).to eq 34
|
|
30
36
|
end
|
|
31
|
-
|
|
32
|
-
it "
|
|
37
|
+
|
|
38
|
+
it "enables configuration option 'login_lock_time_period'" do
|
|
33
39
|
sorcery_model_property_set(:login_lock_time_period, 2.hours)
|
|
34
|
-
|
|
40
|
+
expect(config.login_lock_time_period).to eq 2.hours
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#locked?" do
|
|
44
|
+
it "is locked" do
|
|
45
|
+
user.send("#{config.lock_expires_at_attribute_name}=", Time.now + 5.days)
|
|
46
|
+
expect(user).to be_locked
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "isn't locked" do
|
|
50
|
+
user.send("#{config.lock_expires_at_attribute_name}=", nil)
|
|
51
|
+
expect(user).not_to be_locked
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "#register_failed_login!" do
|
|
57
|
+
it "locks user when number of retries reached the limit" do
|
|
58
|
+
expect(user.lock_expires_at).to be_nil
|
|
59
|
+
|
|
60
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 1)
|
|
61
|
+
user.register_failed_login!
|
|
62
|
+
lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
|
|
63
|
+
|
|
64
|
+
expect(lock_expires_at).not_to be_nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "unlock_token_mailer_disabled is true" do
|
|
68
|
+
it "does not automatically send unlock email" do
|
|
69
|
+
sorcery_model_property_set(:unlock_token_mailer_disabled, true)
|
|
70
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
71
|
+
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
72
|
+
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
73
|
+
|
|
74
|
+
3.times { user.register_failed_login! }
|
|
75
|
+
|
|
76
|
+
expect(ActionMailer::Base.deliveries.size).to eq 0
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "unlock_token_mailer_disabled is false" do
|
|
82
|
+
before do
|
|
83
|
+
sorcery_model_property_set(:unlock_token_mailer_disabled, false)
|
|
84
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
85
|
+
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
86
|
+
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "does not automatically send unlock email" do
|
|
90
|
+
3.times { user.register_failed_login! }
|
|
91
|
+
|
|
92
|
+
expect(ActionMailer::Base.deliveries.size).to eq 1
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "generates unlock token before mail is sent" do
|
|
96
|
+
3.times { user.register_failed_login! }
|
|
97
|
+
|
|
98
|
+
expect(ActionMailer::Base.deliveries.last.body.to_s.match(user.unlock_token)).not_to be_nil
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context ".authenticate" do
|
|
104
|
+
|
|
105
|
+
it "unlocks after lock time period passes" do
|
|
106
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
107
|
+
sorcery_model_property_set(:login_lock_time_period, 0.2)
|
|
108
|
+
2.times { user.register_failed_login! }
|
|
109
|
+
|
|
110
|
+
lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
|
|
111
|
+
expect(lock_expires_at).not_to be_nil
|
|
112
|
+
|
|
113
|
+
Timecop.travel(Time.now.in_time_zone + 0.3)
|
|
114
|
+
User.authenticate('bla@bla.com', 'secret')
|
|
115
|
+
|
|
116
|
+
lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
|
|
117
|
+
expect(lock_expires_at).to be_nil
|
|
118
|
+
Timecop.return
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "doest not unlock if time period is 0 (permanent lock)" do
|
|
122
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
123
|
+
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
124
|
+
|
|
125
|
+
2.times { user.register_failed_login! }
|
|
126
|
+
|
|
127
|
+
unlock_date = user.lock_expires_at
|
|
128
|
+
Timecop.travel(Time.now.in_time_zone + 1)
|
|
129
|
+
|
|
130
|
+
user.register_failed_login!
|
|
131
|
+
|
|
132
|
+
expect(user.lock_expires_at.to_s).to eq unlock_date.to_s
|
|
133
|
+
Timecop.return
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe "#unlock!" do
|
|
139
|
+
it "unlocks after entering unlock token" do
|
|
140
|
+
sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
|
|
141
|
+
sorcery_model_property_set(:login_lock_time_period, 0)
|
|
142
|
+
sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
|
|
143
|
+
3.times { user.register_failed_login! }
|
|
144
|
+
|
|
145
|
+
expect(user.unlock_token).not_to be_nil
|
|
146
|
+
|
|
147
|
+
token = user.unlock_token
|
|
148
|
+
user = User.load_from_unlock_token(token)
|
|
149
|
+
|
|
150
|
+
expect(user).not_to be_nil
|
|
151
|
+
|
|
152
|
+
user.unlock!
|
|
153
|
+
expect(User.load_from_unlock_token(user.unlock_token)).to be_nil
|
|
35
154
|
end
|
|
36
155
|
end
|
|
37
|
-
end
|
|
156
|
+
end
|