sorcery 0.17.0 → 0.18.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/CHANGELOG.md +4 -1
- data/README.md +8 -5
- data/lib/generators/sorcery/helpers.rb +1 -1
- data/lib/generators/sorcery/install_generator.rb +9 -18
- data/lib/generators/sorcery/templates/initializer.rb +24 -10
- data/lib/sorcery/adapters/active_record_adapter.rb +12 -14
- data/lib/sorcery/adapters/mongoid_adapter.rb +6 -8
- data/lib/sorcery/controller/config.rb +27 -29
- data/lib/sorcery/controller/submodules/activity_logging.rb +4 -7
- data/lib/sorcery/controller/submodules/brute_force_protection.rb +4 -1
- data/lib/sorcery/controller/submodules/external.rb +11 -11
- data/lib/sorcery/controller/submodules/http_basic_auth.rb +7 -2
- data/lib/sorcery/controller/submodules/remember_me.rb +2 -1
- data/lib/sorcery/controller/submodules/session_timeout.rb +2 -2
- data/lib/sorcery/controller.rb +36 -18
- data/lib/sorcery/crypto_providers/aes256.rb +4 -2
- data/lib/sorcery/crypto_providers/bcrypt.rb +2 -1
- data/lib/sorcery/crypto_providers/md5.rb +1 -0
- data/lib/sorcery/crypto_providers/sha1.rb +1 -0
- data/lib/sorcery/crypto_providers/sha256.rb +1 -0
- data/lib/sorcery/crypto_providers/sha512.rb +1 -0
- data/lib/sorcery/engine.rb +6 -4
- data/lib/sorcery/errors.rb +10 -0
- data/lib/sorcery/model/config.rb +20 -31
- data/lib/sorcery/model/submodules/activity_logging.rb +8 -6
- data/lib/sorcery/model/submodules/brute_force_protection.rb +16 -14
- data/lib/sorcery/model/submodules/external.rb +8 -10
- data/lib/sorcery/model/submodules/magic_login.rb +8 -4
- data/lib/sorcery/model/submodules/remember_me.rb +3 -3
- data/lib/sorcery/model/submodules/reset_password.rb +21 -13
- data/lib/sorcery/model/submodules/user_activation.rb +19 -17
- data/lib/sorcery/model/temporary_token.rb +5 -5
- data/lib/sorcery/model.rb +21 -25
- data/lib/sorcery/providers/base.rb +1 -1
- data/lib/sorcery/providers/facebook.rb +2 -2
- data/lib/sorcery/providers/github.rb +3 -3
- data/lib/sorcery/providers/heroku.rb +1 -2
- data/lib/sorcery/providers/jira.rb +3 -2
- data/lib/sorcery/providers/line.rb +2 -4
- data/lib/sorcery/providers/microsoft.rb +1 -1
- data/lib/sorcery/providers/twitter.rb +2 -2
- data/lib/sorcery/providers/vk.rb +4 -4
- data/lib/sorcery/providers/xing.rb +3 -2
- data/lib/sorcery/test_helpers/internal/rails.rb +5 -22
- data/lib/sorcery/test_helpers/internal.rb +4 -6
- data/lib/sorcery/test_helpers/rails/integration.rb +1 -1
- data/lib/sorcery/test_helpers/rails/request.rb +1 -1
- data/lib/sorcery/version.rb +1 -1
- data/lib/sorcery.rb +6 -1
- metadata +21 -150
- data/.devcontainer/Dockerfile +0 -10
- data/.devcontainer/devcontainer.json +0 -29
- data/.devcontainer/postcreate.sh +0 -4
- data/.document +0 -5
- data/.github/FUNDING.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -24
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -7
- data/.github/workflows/ruby.yml +0 -54
- data/.gitignore +0 -60
- data/.rspec +0 -1
- data/.rubocop.yml +0 -55
- data/.rubocop_todo.yml +0 -163
- data/CODE_OF_CONDUCT.md +0 -14
- data/Gemfile +0 -8
- data/MAINTAINING.md +0 -64
- data/Rakefile +0 -8
- data/SECURITY.md +0 -19
- data/gemfiles/rails_61.gemfile +0 -7
- data/gemfiles/rails_70.gemfile +0 -7
- data/gemfiles/rails_71.gemfile +0 -7
- data/sorcery.gemspec +0 -49
- data/spec/active_record/user_activation_spec.rb +0 -17
- data/spec/active_record/user_activity_logging_spec.rb +0 -15
- data/spec/active_record/user_brute_force_protection_spec.rb +0 -15
- data/spec/active_record/user_magic_login_spec.rb +0 -15
- data/spec/active_record/user_oauth_spec.rb +0 -15
- data/spec/active_record/user_remember_me_spec.rb +0 -15
- data/spec/active_record/user_reset_password_spec.rb +0 -15
- data/spec/active_record/user_spec.rb +0 -27
- data/spec/controllers/controller_activity_logging_spec.rb +0 -113
- data/spec/controllers/controller_brute_force_protection_spec.rb +0 -41
- data/spec/controllers/controller_http_basic_auth_spec.rb +0 -67
- data/spec/controllers/controller_oauth2_spec.rb +0 -568
- data/spec/controllers/controller_oauth_spec.rb +0 -266
- data/spec/controllers/controller_remember_me_spec.rb +0 -130
- data/spec/controllers/controller_session_timeout_spec.rb +0 -168
- data/spec/controllers/controller_spec.rb +0 -200
- data/spec/orm/active_record.rb +0 -21
- data/spec/providers/example_provider_spec.rb +0 -17
- data/spec/providers/example_spec.rb +0 -17
- data/spec/providers/examples_spec.rb +0 -17
- data/spec/providers/vk_spec.rb +0 -42
- data/spec/rails_app/app/active_record/authentication.rb +0 -3
- data/spec/rails_app/app/active_record/user.rb +0 -5
- data/spec/rails_app/app/active_record/user_provider.rb +0 -3
- data/spec/rails_app/app/assets/config/manifest.js +0 -1
- data/spec/rails_app/app/controllers/application_controller.rb +0 -2
- data/spec/rails_app/app/controllers/sorcery_controller.rb +0 -489
- data/spec/rails_app/app/helpers/application_helper.rb +0 -2
- data/spec/rails_app/app/mailers/sorcery_mailer.rb +0 -38
- data/spec/rails_app/app/views/application/index.html.erb +0 -17
- data/spec/rails_app/app/views/layouts/application.html.erb +0 -14
- data/spec/rails_app/app/views/sorcery_mailer/activation_email.html.erb +0 -17
- data/spec/rails_app/app/views/sorcery_mailer/activation_email.text.erb +0 -9
- data/spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb +0 -17
- data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb +0 -17
- data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb +0 -9
- data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.html.erb +0 -13
- data/spec/rails_app/app/views/sorcery_mailer/magic_login_email.text.erb +0 -6
- data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb +0 -16
- data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb +0 -8
- data/spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb +0 -1
- data/spec/rails_app/config/application.rb +0 -61
- data/spec/rails_app/config/boot.rb +0 -4
- data/spec/rails_app/config/database.yml +0 -22
- data/spec/rails_app/config/environment.rb +0 -5
- data/spec/rails_app/config/environments/test.rb +0 -37
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/rails_app/config/initializers/compatible_legacy_migration.rb +0 -11
- data/spec/rails_app/config/initializers/inflections.rb +0 -10
- data/spec/rails_app/config/initializers/mime_types.rb +0 -5
- data/spec/rails_app/config/initializers/session_store.rb +0 -12
- data/spec/rails_app/config/locales/en.yml +0 -5
- data/spec/rails_app/config/routes.rb +0 -81
- data/spec/rails_app/config/secrets.yml +0 -4
- data/spec/rails_app/config.ru +0 -4
- data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
- data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -19
- data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -13
- data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +0 -16
- data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +0 -22
- data/spec/rails_app/db/migrate/invalidate_active_sessions/20180221093235_add_invalidate_active_sessions_before_to_users.rb +0 -9
- data/spec/rails_app/db/migrate/magic_login/20170924151831_add_magic_login_to_users.rb +0 -17
- data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
- data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -15
- data/spec/rails_app/db/schema.rb +0 -21
- data/spec/rails_app/db/seeds.rb +0 -7
- data/spec/shared_examples/user_activation_shared_examples.rb +0 -361
- data/spec/shared_examples/user_activity_logging_shared_examples.rb +0 -106
- data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +0 -151
- data/spec/shared_examples/user_magic_login_shared_examples.rb +0 -150
- data/spec/shared_examples/user_oauth_shared_examples.rb +0 -33
- data/spec/shared_examples/user_remember_me_shared_examples.rb +0 -129
- data/spec/shared_examples/user_reset_password_shared_examples.rb +0 -370
- data/spec/shared_examples/user_shared_examples.rb +0 -678
- data/spec/sorcery_crypto_providers_spec.rb +0 -245
- data/spec/sorcery_temporary_token_spec.rb +0 -27
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -50
- data/spec/support/migration_helper.rb +0 -29
- data/spec/support/providers/example.rb +0 -11
- data/spec/support/providers/example_provider.rb +0 -11
- data/spec/support/providers/examples.rb +0 -11
|
@@ -1,678 +0,0 @@
|
|
|
1
|
-
shared_examples_for 'rails_3_core_model' do
|
|
2
|
-
let(:user) { create_new_user }
|
|
3
|
-
let(:crypted_password) { user.send User.sorcery_config.crypted_password_attribute_name }
|
|
4
|
-
|
|
5
|
-
describe 'loaded plugin configuration' do
|
|
6
|
-
after(:each) { User.sorcery_config.reset! }
|
|
7
|
-
|
|
8
|
-
it "enables configuration option 'username_attribute_names'" do
|
|
9
|
-
sorcery_model_property_set(:username_attribute_names, :email)
|
|
10
|
-
|
|
11
|
-
expect(User.sorcery_config.username_attribute_names).to eq [:email]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it "enables configuration option 'password_attribute_name'" do
|
|
15
|
-
sorcery_model_property_set(:password_attribute_name, :mypassword)
|
|
16
|
-
|
|
17
|
-
expect(User.sorcery_config.password_attribute_name).to eq :mypassword
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "enables configuration option 'email_attribute_name'" do
|
|
21
|
-
sorcery_model_property_set(:email_attribute_name, :my_email)
|
|
22
|
-
|
|
23
|
-
expect(User.sorcery_config.email_attribute_name).to eq :my_email
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "enables configuration option 'crypted_password_attribute_name'" do
|
|
27
|
-
sorcery_model_property_set(:crypted_password_attribute_name, :password)
|
|
28
|
-
|
|
29
|
-
expect(User.sorcery_config.crypted_password_attribute_name).to eq :password
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it "enables configuration option 'salt_attribute_name'" do
|
|
33
|
-
sorcery_model_property_set(:salt_attribute_name, :my_salt)
|
|
34
|
-
|
|
35
|
-
expect(User.sorcery_config.salt_attribute_name).to eq :my_salt
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "enables configuration option 'encryption_algorithm'" do
|
|
39
|
-
sorcery_model_property_set(:encryption_algorithm, :none)
|
|
40
|
-
|
|
41
|
-
expect(User.sorcery_config.encryption_algorithm).to eq :none
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it "enables configuration option 'encryption_key'" do
|
|
45
|
-
sorcery_model_property_set(:encryption_key, 'asdadas424234242')
|
|
46
|
-
|
|
47
|
-
expect(User.sorcery_config.encryption_key).to eq 'asdadas424234242'
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it "enables configuration option 'custom_encryption_provider'" do
|
|
51
|
-
sorcery_model_property_set(:encryption_algorithm, :custom)
|
|
52
|
-
sorcery_model_property_set(:custom_encryption_provider, Array)
|
|
53
|
-
|
|
54
|
-
expect(User.sorcery_config.custom_encryption_provider).to eq Array
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it "enables configuration option 'pepper'" do
|
|
58
|
-
pepper = '*$%&%*++'
|
|
59
|
-
sorcery_model_property_set(:pepper, pepper)
|
|
60
|
-
|
|
61
|
-
expect(User.sorcery_config.pepper).to eq pepper
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it "enables configuration option 'salt_join_token'" do
|
|
65
|
-
salt_join_token = '--%%*&-'
|
|
66
|
-
sorcery_model_property_set(:salt_join_token, salt_join_token)
|
|
67
|
-
|
|
68
|
-
expect(User.sorcery_config.salt_join_token).to eq salt_join_token
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "enables configuration option 'stretches'" do
|
|
72
|
-
stretches = 15
|
|
73
|
-
sorcery_model_property_set(:stretches, stretches)
|
|
74
|
-
|
|
75
|
-
expect(User.sorcery_config.stretches).to eq stretches
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it "enables configuration option 'deliver_later_enabled" do
|
|
79
|
-
sorcery_model_property_set(:email_delivery_method, :deliver_later)
|
|
80
|
-
expect(User.sorcery_config.email_delivery_method).to eq :deliver_later
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it 'respond to username=' do
|
|
84
|
-
expect(User.new).to respond_to(:username=)
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
describe 'when activated with sorcery' do
|
|
89
|
-
before(:all) { sorcery_reload! }
|
|
90
|
-
before(:each) { User.sorcery_adapter.delete_all }
|
|
91
|
-
|
|
92
|
-
it 'does not add authenticate method to base class', active_record: true do
|
|
93
|
-
expect(ActiveRecord::Base).not_to respond_to(:authenticate) if defined?(ActiveRecord)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
it 'responds to class method authenticate' do
|
|
97
|
-
expect(User).to respond_to :authenticate
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
describe '#authenticate' do
|
|
101
|
-
it 'returns user if credentials are good' do
|
|
102
|
-
expect(User.authenticate(user.email, 'secret')).to eq user
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
it 'returns nil if credentials are bad' do
|
|
106
|
-
expect(User.authenticate(user.email, 'wrong!')).to be nil
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
context 'downcasing username' do
|
|
110
|
-
after do
|
|
111
|
-
sorcery_reload!
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
context 'when downcasing set to false' do
|
|
115
|
-
before do
|
|
116
|
-
sorcery_model_property_set(:downcase_username_before_authenticating, false)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
it 'does not find user with wrongly capitalized username' do
|
|
120
|
-
expect(User.authenticate(user.email.capitalize, 'secret')).to be_nil
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
it 'finds user with correctly capitalized username' do
|
|
124
|
-
expect(User.authenticate(user.email, 'secret')).to eq user
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
context 'when downcasing set to true' do
|
|
129
|
-
before do
|
|
130
|
-
sorcery_model_property_set(:downcase_username_before_authenticating, true)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
it 'does not find user with wrongly capitalized username' do
|
|
134
|
-
expect(User.authenticate(user.email.capitalize, 'secret')).to eq user
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
it 'finds user with correctly capitalized username' do
|
|
138
|
-
expect(User.authenticate(user.email, 'secret')).to eq user
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
context 'and model implements active_for_authentication?' do
|
|
144
|
-
it 'authenticates returns user if active_for_authentication? returns true' do
|
|
145
|
-
allow_any_instance_of(User).to receive(:active_for_authentication?) { true }
|
|
146
|
-
|
|
147
|
-
expect(User.authenticate(user.email, 'secret')).to eq user
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
it 'authenticate returns nil if active_for_authentication? returns false' do
|
|
151
|
-
allow_any_instance_of(User).to receive(:active_for_authentication?) { false }
|
|
152
|
-
|
|
153
|
-
expect(User.authenticate(user.email, 'secret')).to be_nil
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
context 'in block mode' do
|
|
158
|
-
it 'yields the user if credentials are good' do
|
|
159
|
-
User.authenticate(user.email, 'secret') do |user2, failure|
|
|
160
|
-
expect(user2).to eq user
|
|
161
|
-
expect(failure).to be_nil
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
it 'yields the user and proper error if credentials are bad' do
|
|
166
|
-
User.authenticate(user.email, 'wrong!') do |user2, failure|
|
|
167
|
-
expect(user2).to eq user
|
|
168
|
-
expect(failure).to eq :invalid_password
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
it 'yields the proper error if no user exists' do
|
|
173
|
-
[nil, '', 'not@a.user'].each do |email|
|
|
174
|
-
User.authenticate(email, 'wrong!') do |user2, failure|
|
|
175
|
-
expect(user2).to be_nil
|
|
176
|
-
expect(failure).to eq :invalid_login
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
specify { expect(User).to respond_to(:encrypt) }
|
|
184
|
-
|
|
185
|
-
it 'subclass inherits config if defined so' do
|
|
186
|
-
sorcery_reload!([], subclasses_inherit_config: true)
|
|
187
|
-
class Admin < User; end
|
|
188
|
-
|
|
189
|
-
expect(Admin.sorcery_config).not_to be_nil
|
|
190
|
-
expect(Admin.sorcery_config).to eq User.sorcery_config
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
it 'subclass does not inherit config if not defined so' do
|
|
194
|
-
sorcery_reload!([], subclasses_inherit_config: false)
|
|
195
|
-
class Admin2 < User; end
|
|
196
|
-
|
|
197
|
-
expect(Admin2.sorcery_config).to be_nil
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
describe 'registration' do
|
|
202
|
-
before(:all) { sorcery_reload! }
|
|
203
|
-
before(:each) { User.sorcery_adapter.delete_all }
|
|
204
|
-
|
|
205
|
-
it 'by default, encryption_provider is not nil' do
|
|
206
|
-
expect(User.sorcery_config.encryption_provider).not_to be_nil
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
it 'encrypts password when a new user is saved' do
|
|
210
|
-
expect(
|
|
211
|
-
User.sorcery_config.encryption_provider.matches?(crypted_password, 'secret', user.salt)
|
|
212
|
-
).to be true
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
it 'clears the virtual password field if the encryption process worked' do
|
|
216
|
-
expect(user.password).to be_nil
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
it 'does not clear the virtual password field if save failed due to validity' do
|
|
220
|
-
User.class_eval do
|
|
221
|
-
validates_format_of :email, with: /\A(.)+@(.)+\Z/,
|
|
222
|
-
if: proc { |r| r.email }, message: 'is invalid'
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
user.password = 'blupush'
|
|
226
|
-
user.email = 'asd'
|
|
227
|
-
user.save
|
|
228
|
-
|
|
229
|
-
expect(user.password).not_to be_nil
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
it 'does not clear the virtual password field if save failed due to exception' do
|
|
233
|
-
user.password = '4blupush'
|
|
234
|
-
user.username = nil
|
|
235
|
-
|
|
236
|
-
expect(user).to receive(:save) { raise RuntimeError }
|
|
237
|
-
|
|
238
|
-
# rubocop:disable Lint/HandleExceptions
|
|
239
|
-
begin
|
|
240
|
-
user.save
|
|
241
|
-
rescue RuntimeError
|
|
242
|
-
# Intentionally force exception during save
|
|
243
|
-
end
|
|
244
|
-
# rubocop:enable Lint/HandleExceptions
|
|
245
|
-
|
|
246
|
-
expect(user.password).not_to be_nil
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
it 'does not encrypt the password twice when a user is updated' do
|
|
250
|
-
user.email = 'blup@bla.com'
|
|
251
|
-
user.save
|
|
252
|
-
|
|
253
|
-
expect(
|
|
254
|
-
User.sorcery_config.encryption_provider.matches?(crypted_password, 'secret', user.salt)
|
|
255
|
-
).to be true
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
it 'replaces the crypted_password in case a new password is set' do
|
|
259
|
-
user.password = 'new_secret'
|
|
260
|
-
user.save
|
|
261
|
-
|
|
262
|
-
expect(
|
|
263
|
-
User.sorcery_config.encryption_provider.matches?(crypted_password, 'secret', user.salt)
|
|
264
|
-
).to be false
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
describe 'when user has password_confirmation_defined' do
|
|
268
|
-
before(:all) do
|
|
269
|
-
update_model { attr_accessor :password_confirmation }
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
after(:all) do
|
|
273
|
-
User.send(:remove_method, :password_confirmation)
|
|
274
|
-
User.send(:remove_method, :password_confirmation=)
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
it 'clears the virtual password field if the encryption process worked' do
|
|
278
|
-
user = create_new_user(
|
|
279
|
-
username: 'u',
|
|
280
|
-
password: 'secret', password_confirmation: 'secret',
|
|
281
|
-
email: 'email@example.com'
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
expect(user.password_confirmation).to be_nil
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
it 'does not clear the virtual password field if save failed due to validity' do
|
|
288
|
-
User.class_eval do
|
|
289
|
-
validates_format_of :email, with: /\A(.)+@(.)+\Z/
|
|
290
|
-
end
|
|
291
|
-
user = build_new_user(
|
|
292
|
-
username: 'u',
|
|
293
|
-
password: 'secret', password_confirmation: 'secret',
|
|
294
|
-
email: 'asd'
|
|
295
|
-
)
|
|
296
|
-
user.save
|
|
297
|
-
|
|
298
|
-
expect(user.password_confirmation).not_to be_nil
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
describe 'password validation' do
|
|
304
|
-
let(:user_with_pass) do
|
|
305
|
-
create_new_user(username: 'foo_bar', email: 'foo@bar.com', password: 'foobar')
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
specify { expect(user_with_pass).to respond_to :valid_password? }
|
|
309
|
-
|
|
310
|
-
it 'returns true if password is correct' do
|
|
311
|
-
expect(user_with_pass.valid_password?('foobar')).to be true
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
it 'returns false if password is incorrect' do
|
|
315
|
-
expect(user_with_pass.valid_password?('foobug')).to be false
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
describe 'generic send email' do
|
|
320
|
-
before(:all) do
|
|
321
|
-
MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
|
|
322
|
-
User.reset_column_information
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
after(:all) do
|
|
326
|
-
MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
before do
|
|
330
|
-
@mail = double('mail')
|
|
331
|
-
allow(::SorceryMailer).to receive(:activation_success_email).and_return(@mail)
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
it 'use deliver_later' do
|
|
335
|
-
sorcery_reload!(
|
|
336
|
-
%i[
|
|
337
|
-
user_activation
|
|
338
|
-
user_activation_mailer
|
|
339
|
-
activation_needed_email_method_name
|
|
340
|
-
email_delivery_method
|
|
341
|
-
],
|
|
342
|
-
user_activation_mailer: SorceryMailer,
|
|
343
|
-
activation_needed_email_method_name: nil,
|
|
344
|
-
email_delivery_method: :deliver_later
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
expect(@mail).to receive(:deliver_later).once
|
|
348
|
-
user.activate!
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
describe 'email_delivery_method is default' do
|
|
352
|
-
it 'use deliver_now if rails version 4.2+' do
|
|
353
|
-
allow(Rails).to receive(:version).and_return('4.2.0')
|
|
354
|
-
sorcery_reload!(
|
|
355
|
-
%i[
|
|
356
|
-
user_activation
|
|
357
|
-
user_activation_mailer
|
|
358
|
-
activation_needed_email_method_name
|
|
359
|
-
],
|
|
360
|
-
user_activation_mailer: SorceryMailer,
|
|
361
|
-
activation_needed_email_method_name: nil
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
expect(@mail).to receive(:deliver_now).once
|
|
365
|
-
user.activate!
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
it 'use deliver if rails version < 4.2' do
|
|
369
|
-
allow(Rails).to receive(:version).and_return('4.1.0')
|
|
370
|
-
sorcery_reload!(
|
|
371
|
-
%i[
|
|
372
|
-
user_activation
|
|
373
|
-
user_activation_mailer
|
|
374
|
-
activation_needed_email_method_name
|
|
375
|
-
],
|
|
376
|
-
user_activation_mailer: SorceryMailer,
|
|
377
|
-
activation_needed_email_method_name: nil
|
|
378
|
-
)
|
|
379
|
-
|
|
380
|
-
expect(@mail).to receive(:deliver).once
|
|
381
|
-
user.activate!
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
describe 'special encryption cases' do
|
|
387
|
-
before(:all) do
|
|
388
|
-
sorcery_reload!
|
|
389
|
-
@text = 'Some Text!'
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
before(:each) do
|
|
393
|
-
User.sorcery_adapter.delete_all
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
after(:each) do
|
|
397
|
-
User.sorcery_config.reset!
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
it 'works with no password encryption' do
|
|
401
|
-
sorcery_model_property_set(:encryption_algorithm, :none)
|
|
402
|
-
username = user.send(User.sorcery_config.username_attribute_names.first)
|
|
403
|
-
|
|
404
|
-
expect(User.authenticate(username, 'secret')).to be_truthy
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
it 'works with custom password encryption' do
|
|
408
|
-
class MyCrypto
|
|
409
|
-
def self.encrypt(*tokens)
|
|
410
|
-
tokens.flatten.join('').tr('e', 'A')
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
def self.matches?(crypted, *tokens)
|
|
414
|
-
crypted == encrypt(*tokens)
|
|
415
|
-
end
|
|
416
|
-
end
|
|
417
|
-
sorcery_model_property_set(:encryption_algorithm, :custom)
|
|
418
|
-
sorcery_model_property_set(:custom_encryption_provider, MyCrypto)
|
|
419
|
-
|
|
420
|
-
username = user.send(User.sorcery_config.username_attribute_names.first)
|
|
421
|
-
|
|
422
|
-
expect(User.authenticate(username, 'secret')).to be_truthy
|
|
423
|
-
end
|
|
424
|
-
|
|
425
|
-
it 'if encryption algo is aes256, it sets key to crypto provider' do
|
|
426
|
-
sorcery_model_property_set(:encryption_algorithm, :aes256)
|
|
427
|
-
sorcery_model_property_set(:encryption_key, nil)
|
|
428
|
-
|
|
429
|
-
expect { User.encrypt @text }.to raise_error(ArgumentError)
|
|
430
|
-
|
|
431
|
-
sorcery_model_property_set(:encryption_key, 'asd234dfs423fddsmndsflktsdf32343')
|
|
432
|
-
|
|
433
|
-
expect { User.encrypt @text }.not_to raise_error
|
|
434
|
-
end
|
|
435
|
-
|
|
436
|
-
it 'if encryption algo is aes256, it sets key to crypto provider, even if attributes are set in reverse' do
|
|
437
|
-
sorcery_model_property_set(:encryption_key, nil)
|
|
438
|
-
sorcery_model_property_set(:encryption_algorithm, :none)
|
|
439
|
-
sorcery_model_property_set(:encryption_key, 'asd234dfs423fddsmndsflktsdf32343')
|
|
440
|
-
sorcery_model_property_set(:encryption_algorithm, :aes256)
|
|
441
|
-
|
|
442
|
-
expect { User.encrypt @text }.not_to raise_error
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
it 'if encryption algo is md5 it works' do
|
|
446
|
-
sorcery_model_property_set(:encryption_algorithm, :md5)
|
|
447
|
-
|
|
448
|
-
expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::MD5.encrypt(@text)
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
it 'if encryption algo is sha1 it works' do
|
|
452
|
-
sorcery_model_property_set(:encryption_algorithm, :sha1)
|
|
453
|
-
|
|
454
|
-
expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::SHA1.encrypt(@text)
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
it 'if encryption algo is sha256 it works' do
|
|
458
|
-
sorcery_model_property_set(:encryption_algorithm, :sha256)
|
|
459
|
-
|
|
460
|
-
expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::SHA256.encrypt(@text)
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
it 'if encryption algo is sha512 it works' do
|
|
464
|
-
sorcery_model_property_set(:encryption_algorithm, :sha512)
|
|
465
|
-
|
|
466
|
-
expect(User.encrypt(@text)).to eq Sorcery::CryptoProviders::SHA512.encrypt(@text)
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
it 'if encryption algo is bcrypt it works' do
|
|
470
|
-
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
|
471
|
-
|
|
472
|
-
# comparison is done using BCrypt::Password#==(raw_token), not by String#==
|
|
473
|
-
expect(User.encrypt(@text)).to be_an_instance_of BCrypt::Password
|
|
474
|
-
expect(User.encrypt(@text)).to eq @text
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
it 'salt is random for each user and saved in db' do
|
|
478
|
-
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
479
|
-
|
|
480
|
-
expect(user.salt).not_to be_nil
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
it 'if salt is set uses it to encrypt' do
|
|
484
|
-
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
485
|
-
sorcery_model_property_set(:encryption_algorithm, :sha512)
|
|
486
|
-
|
|
487
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::SHA512.encrypt('secret')
|
|
488
|
-
expect(user.crypted_password).to eq Sorcery::CryptoProviders::SHA512.encrypt('secret', user.salt)
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
it 'if salt_join_token is set uses it to encrypt' do
|
|
492
|
-
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
493
|
-
sorcery_model_property_set(:salt_join_token, '-@=>')
|
|
494
|
-
sorcery_model_property_set(:encryption_algorithm, :sha512)
|
|
495
|
-
|
|
496
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::SHA512.encrypt('secret')
|
|
497
|
-
|
|
498
|
-
Sorcery::CryptoProviders::SHA512.join_token = ''
|
|
499
|
-
|
|
500
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::SHA512.encrypt('secret', user.salt)
|
|
501
|
-
|
|
502
|
-
Sorcery::CryptoProviders::SHA512.join_token = User.sorcery_config.salt_join_token
|
|
503
|
-
|
|
504
|
-
expect(user.crypted_password).to eq Sorcery::CryptoProviders::SHA512.encrypt('secret', user.salt)
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
it 'if pepper is set uses it to encrypt' do
|
|
508
|
-
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
509
|
-
sorcery_model_property_set(:pepper, '++@^$')
|
|
510
|
-
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
|
511
|
-
|
|
512
|
-
# password comparison is done using BCrypt::Password#==(raw_token), not String#==
|
|
513
|
-
bcrypt_password = BCrypt::Password.new(user.crypted_password)
|
|
514
|
-
allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
|
|
515
|
-
# need to use common BCrypt's salt when genarating BCrypt::Password objects
|
|
516
|
-
# so that any generated password hashes can be compared each other
|
|
517
|
-
::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret')
|
|
521
|
-
|
|
522
|
-
Sorcery::CryptoProviders::BCrypt.pepper = ''
|
|
523
|
-
|
|
524
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
|
525
|
-
|
|
526
|
-
Sorcery::CryptoProviders::BCrypt.pepper = User.sorcery_config.pepper
|
|
527
|
-
|
|
528
|
-
expect(user.crypted_password).to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
it 'if pepper is empty string (default) does not use pepper to encrypt' do
|
|
532
|
-
sorcery_model_property_set(:salt_attribute_name, :salt)
|
|
533
|
-
sorcery_model_property_set(:pepper, '')
|
|
534
|
-
sorcery_model_property_set(:encryption_algorithm, :bcrypt)
|
|
535
|
-
|
|
536
|
-
# password comparison is done using BCrypt::Password#==(raw_token), not String#==
|
|
537
|
-
bcrypt_password = BCrypt::Password.new(user.crypted_password)
|
|
538
|
-
allow(::BCrypt::Password).to receive(:create) do |token, options = {}|
|
|
539
|
-
# need to use common BCrypt's salt when genarating BCrypt::Password objects
|
|
540
|
-
# so that any generated password hashes can be compared each other
|
|
541
|
-
::BCrypt::Engine.hash_secret(token, bcrypt_password.salt)
|
|
542
|
-
end
|
|
543
|
-
|
|
544
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret')
|
|
545
|
-
|
|
546
|
-
Sorcery::CryptoProviders::BCrypt.pepper = 'some_pepper'
|
|
547
|
-
|
|
548
|
-
expect(user.crypted_password).not_to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
|
549
|
-
|
|
550
|
-
Sorcery::CryptoProviders::BCrypt.pepper = User.sorcery_config.pepper
|
|
551
|
-
|
|
552
|
-
expect(user.crypted_password).to eq Sorcery::CryptoProviders::BCrypt.encrypt('secret', user.salt)
|
|
553
|
-
end
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
describe 'ORM adapter' do
|
|
557
|
-
before(:all) do
|
|
558
|
-
sorcery_reload!
|
|
559
|
-
User.sorcery_adapter.delete_all
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
before(:each) { user }
|
|
563
|
-
|
|
564
|
-
after(:each) do
|
|
565
|
-
User.sorcery_adapter.delete_all
|
|
566
|
-
User.sorcery_config.reset!
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
it 'find_by_username works as expected' do
|
|
570
|
-
sorcery_model_property_set(:username_attribute_names, [:username])
|
|
571
|
-
|
|
572
|
-
expect(User.sorcery_adapter.find_by_username('gizmo')).to eq user
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
it 'find_by_username works as expected with multiple username attributes' do
|
|
576
|
-
sorcery_model_property_set(:username_attribute_names, %i[username email])
|
|
577
|
-
|
|
578
|
-
expect(User.sorcery_adapter.find_by_username('gizmo')).to eq user
|
|
579
|
-
end
|
|
580
|
-
|
|
581
|
-
it 'find_by_email works as expected' do
|
|
582
|
-
expect(User.sorcery_adapter.find_by_email('bla@bla.com')).to eq user
|
|
583
|
-
end
|
|
584
|
-
end
|
|
585
|
-
end
|
|
586
|
-
|
|
587
|
-
shared_examples_for 'external_user' do
|
|
588
|
-
let(:user) { create_new_user }
|
|
589
|
-
let(:external_user) { create_new_external_user :twitter }
|
|
590
|
-
|
|
591
|
-
before(:all) do
|
|
592
|
-
if SORCERY_ORM == :active_record
|
|
593
|
-
MigrationHelper.migrate("#{Rails.root}/db/migrate/external")
|
|
594
|
-
MigrationHelper.migrate("#{Rails.root}/db/migrate/activation")
|
|
595
|
-
end
|
|
596
|
-
sorcery_reload!
|
|
597
|
-
end
|
|
598
|
-
|
|
599
|
-
after(:all) do
|
|
600
|
-
if SORCERY_ORM == :active_record
|
|
601
|
-
MigrationHelper.rollback("#{Rails.root}/db/migrate/external")
|
|
602
|
-
MigrationHelper.rollback("#{Rails.root}/db/migrate/activation")
|
|
603
|
-
end
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
before(:each) do
|
|
607
|
-
User.sorcery_adapter.delete_all
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
it "responds to 'external?'" do
|
|
611
|
-
expect(user).to respond_to(:external?)
|
|
612
|
-
end
|
|
613
|
-
|
|
614
|
-
it 'external? is false for regular users' do
|
|
615
|
-
expect(user.external?).to be false
|
|
616
|
-
end
|
|
617
|
-
|
|
618
|
-
it 'external? is true for external users' do
|
|
619
|
-
expect(external_user.external?).to be true
|
|
620
|
-
end
|
|
621
|
-
|
|
622
|
-
describe '.create_from_provider' do
|
|
623
|
-
before(:each) do
|
|
624
|
-
sorcery_reload!([:external])
|
|
625
|
-
sorcery_model_property_set(:authentications_class, Authentication)
|
|
626
|
-
end
|
|
627
|
-
|
|
628
|
-
it 'supports nested attributes' do
|
|
629
|
-
expect do
|
|
630
|
-
User.create_from_provider('facebook', '123', username: 'Noam Ben Ari')
|
|
631
|
-
end.to change { User.count }.by(1)
|
|
632
|
-
|
|
633
|
-
expect(User.first.username).to eq 'Noam Ben Ari'
|
|
634
|
-
end
|
|
635
|
-
|
|
636
|
-
context 'with block' do
|
|
637
|
-
it 'create user when block return true' do
|
|
638
|
-
expect do
|
|
639
|
-
User.create_from_provider('facebook', '123', username: 'Noam Ben Ari') { true }
|
|
640
|
-
end.to change { User.count }.by(1)
|
|
641
|
-
end
|
|
642
|
-
|
|
643
|
-
it 'does not create user when block return false' do
|
|
644
|
-
expect do
|
|
645
|
-
User.create_from_provider('facebook', '123', username: 'Noam Ben Ari') { false }
|
|
646
|
-
end.not_to(change { User.count })
|
|
647
|
-
end
|
|
648
|
-
end
|
|
649
|
-
end
|
|
650
|
-
|
|
651
|
-
describe 'activation' do
|
|
652
|
-
before(:each) do
|
|
653
|
-
sorcery_reload!(%i[user_activation external], user_activation_mailer: ::SorceryMailer)
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
after(:each) do
|
|
657
|
-
User.sorcery_adapter.delete_all
|
|
658
|
-
end
|
|
659
|
-
|
|
660
|
-
%i[facebook github google liveid slack].each do |provider|
|
|
661
|
-
it 'does not send activation email to external users' do
|
|
662
|
-
old_size = ActionMailer::Base.deliveries.size
|
|
663
|
-
create_new_external_user(provider)
|
|
664
|
-
|
|
665
|
-
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
666
|
-
end
|
|
667
|
-
|
|
668
|
-
it 'does not send external users an activation success email' do
|
|
669
|
-
sorcery_model_property_set(:activation_success_email_method_name, nil)
|
|
670
|
-
create_new_external_user(provider)
|
|
671
|
-
old_size = ActionMailer::Base.deliveries.size
|
|
672
|
-
@user.activate!
|
|
673
|
-
|
|
674
|
-
expect(ActionMailer::Base.deliveries.size).to eq old_size
|
|
675
|
-
end
|
|
676
|
-
end
|
|
677
|
-
end
|
|
678
|
-
end
|