omniauth-identity 3.0.9 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe OmniAuth::Identity::Model do
4
- before do
5
- identity_test_klass = Class.new do
6
- include OmniAuth::Identity::Model
7
- end
8
- stub_const('IdentityTestClass', identity_test_klass)
9
- end
10
-
11
- describe 'Class Methods' do
12
- subject(:model_klass) { IdentityTestClass }
13
-
14
- include_context 'model with class methods'
15
-
16
- describe '::locate' do
17
- it('is abstract') do
18
- expect { model_klass.locate('email' => 'example') }.to raise_error(NotImplementedError)
19
- end
20
- end
21
- end
22
-
23
- describe 'Instance Methods' do
24
- subject(:instance) { IdentityTestClass.new }
25
-
26
- include_context 'instance with instance methods'
27
-
28
- describe '#authenticate' do
29
- it('is abstract') { expect { instance.authenticate('my-password') }.to raise_error(NotImplementedError) }
30
- end
31
-
32
- describe '#auth_key' do
33
- it 'raises a NotImplementedError if the auth_key method is not defined' do
34
- expect { instance.auth_key }.to raise_error(NotImplementedError)
35
- end
36
- end
37
-
38
- describe '#auth_key=' do
39
- it 'raises a NotImplementedError if the auth_key method is not defined' do
40
- expect { instance.auth_key = 'broken' }.to raise_error(NotImplementedError)
41
- end
42
- end
43
- end
44
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sqlite3'
4
- require 'active_record'
5
- require 'anonymous_active_record'
6
-
7
- class TestIdentity < OmniAuth::Identity::Models::ActiveRecord; end
8
-
9
- RSpec.describe(OmniAuth::Identity::Models::ActiveRecord, sqlite3: true) do
10
- describe 'model', type: :model do
11
- subject(:model_klass) do
12
- AnonymousActiveRecord.generate(
13
- parent_klass: 'OmniAuth::Identity::Models::ActiveRecord',
14
- columns: OmniAuth::Identity::Model::SCHEMA_ATTRIBUTES | %w[provider password_digest],
15
- connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' }
16
- ) do
17
- auth_key :email
18
- def flower
19
- '🌸'
20
- end
21
- end
22
- end
23
-
24
- include_context 'persistable model'
25
-
26
- describe '::table_name' do
27
- it 'does not use STI rules for its table name' do
28
- expect(TestIdentity.table_name).to eq('test_identities')
29
- end
30
- end
31
-
32
- describe '::locate' do
33
- it 'delegates locate to the where query method' do
34
- allow(model_klass).to receive(:where).with('email' => 'open faced', 'category' => 'sandwiches',
35
- 'provider' => 'identity').and_return(['wakka'])
36
- expect(model_klass.locate('email' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
37
- end
38
- end
39
- end
40
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sqlite3'
4
- require 'sequel'
5
-
6
- DB = Sequel.sqlite
7
-
8
- RSpec.describe(OmniAuth::Identity::Models::Sequel, sqlite3: true) do
9
- before(:all) do
10
- # Connect to an in-memory sqlite3 database.
11
- DB.create_table :sequel_test_identities do
12
- primary_key :id
13
- String :email, null: false
14
- String :password_digest, null: false
15
- end
16
- end
17
-
18
- before do
19
- sequel_test_identity = Class.new(Sequel::Model(:sequel_test_identities)) do
20
- include ::OmniAuth::Identity::Models::Sequel
21
- auth_key :email
22
- end
23
- stub_const('SequelTestIdentity', sequel_test_identity)
24
- end
25
-
26
- describe 'model', type: :model do
27
- subject(:model_klass) { SequelTestIdentity }
28
-
29
- include_context 'persistable model'
30
-
31
- describe '::locate' do
32
- it 'delegates to the where query method' do
33
- allow(model_klass).to receive(:where).with('email' => 'open faced',
34
- 'category' => 'sandwiches').and_return(['wakka'])
35
- expect(model_klass.locate('email' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
36
- end
37
- end
38
- end
39
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class HasTheMethod
4
- def self.has_secure_password; end
5
- end
6
-
7
- class DoesNotHaveTheMethod
8
- end
9
-
10
- RSpec.describe OmniAuth::Identity::SecurePassword do
11
- it 'extends with the class methods if it does not have the method' do
12
- expect(DoesNotHaveTheMethod).to receive(:extend).with(OmniAuth::Identity::SecurePassword::ClassMethods)
13
- DoesNotHaveTheMethod.include described_class
14
- end
15
-
16
- it 'does not extend if the method is already defined' do
17
- expect(HasTheMethod).not_to receive(:extend)
18
- HasTheMethod.include described_class
19
- end
20
-
21
- it 'responds to has_secure_password afterwards' do
22
- [HasTheMethod, DoesNotHaveTheMethod].each do |klass|
23
- klass.send(:include, described_class)
24
- expect(klass).to be_respond_to(:has_secure_password)
25
- end
26
- end
27
- end
@@ -1,373 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sqlite3'
4
- require 'active_record'
5
- require 'anonymous_active_record'
6
-
7
- RSpec.describe OmniAuth::Strategies::Identity, sqlite3: true do
8
- attr_accessor :app
9
-
10
- let(:env_hash) { last_response.headers['env'] }
11
- let(:auth_hash) { env_hash['omniauth.auth'] }
12
- let(:identity_hash) { env_hash['omniauth.identity'] }
13
- let(:identity_options) { {} }
14
- let(:anon_ar) do
15
- AnonymousActiveRecord.generate(
16
- parent_klass: 'OmniAuth::Identity::Models::ActiveRecord',
17
- columns: OmniAuth::Identity::Model::SCHEMA_ATTRIBUTES | %w[provider password_digest],
18
- connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' }
19
- ) do
20
- auth_key :email
21
- def balloon
22
- '🎈'
23
- end
24
- end
25
- end
26
-
27
- # customize rack app for testing, if block is given, reverts to default
28
- # rack app after testing is done
29
- def set_app!(identity_options = {})
30
- old_app = app
31
- self.app = Rack::Builder.app do
32
- use Rack::Session::Cookie, secret: '1234567890qwertyuiop'
33
- use OmniAuth::Strategies::Identity, identity_options
34
- run ->(env) { [404, { 'env' => env }, ['HELLO!']] }
35
- end
36
- if block_given?
37
- yield
38
- self.app = old_app
39
- end
40
- app
41
- end
42
-
43
- before do
44
- opts = identity_options.reverse_merge({ model: anon_ar })
45
- set_app!(opts)
46
- end
47
-
48
- describe '#request_phase' do
49
- context 'with default settings' do
50
- let(:identity_options) { { model: anon_ar } }
51
-
52
- it 'displays a form' do
53
- get '/auth/identity'
54
-
55
- expect(last_response.body).not_to eq('HELLO!')
56
- expect(last_response.body).to be_include('<form')
57
- end
58
- end
59
-
60
- context 'when login is enabled' do
61
- context 'when registration is enabled' do
62
- let(:identity_options) { { model: anon_ar, enable_registration: true, enable_login: true } }
63
-
64
- it 'displays a form with a link to register' do
65
- get '/auth/identity'
66
-
67
- expect(last_response.body).not_to eq('HELLO!')
68
- expect(last_response.body).to be_include('<form')
69
- expect(last_response.body).to be_include('<a')
70
- expect(last_response.body).to be_include('Create an Identity')
71
- end
72
- end
73
-
74
- context 'when registration is disabled' do
75
- let(:identity_options) { { model: anon_ar, enable_registration: false, enable_login: true } }
76
-
77
- it 'displays a form without a link to register' do
78
- get '/auth/identity'
79
-
80
- expect(last_response.body).not_to eq('HELLO!')
81
- expect(last_response.body).to be_include('<form')
82
- expect(last_response.body).not_to be_include('<a')
83
- expect(last_response.body).not_to be_include('Create an Identity')
84
- end
85
- end
86
- end
87
-
88
- context 'when login is disabled' do
89
- context 'when registration is enabled' do
90
- let(:identity_options) { { model: anon_ar, enable_registration: true, enable_login: false } }
91
-
92
- it 'bypasses registration form' do
93
- get '/auth/identity'
94
-
95
- expect(last_response.body).to eq('HELLO!')
96
- expect(last_response.body).not_to be_include('<form')
97
- expect(last_response.body).not_to be_include('<a')
98
- expect(last_response.body).not_to be_include('Create an Identity')
99
- end
100
- end
101
-
102
- context 'when registration is disabled' do
103
- let(:identity_options) { { model: anon_ar, enable_registration: false, enable_login: false } }
104
-
105
- it 'displays a form without a link to register' do
106
- get '/auth/identity'
107
-
108
- expect(last_response.body).to eq('HELLO!')
109
- expect(last_response.body).not_to be_include('<form')
110
- expect(last_response.body).not_to be_include('<a')
111
- expect(last_response.body).not_to be_include('Create an Identity')
112
- end
113
- end
114
- end
115
- end
116
-
117
- describe '#callback_phase' do
118
- let(:user) { double(uid: 'user1', info: { 'name' => 'Rockefeller' }) }
119
-
120
- context 'with valid credentials' do
121
- before do
122
- allow(anon_ar).to receive('auth_key').and_return('email')
123
- expect(anon_ar).to receive('authenticate').with({ 'email' => 'john' }, 'awesome').and_return(user)
124
- post '/auth/identity/callback', auth_key: 'john', password: 'awesome'
125
- end
126
-
127
- it 'populates the auth hash' do
128
- expect(auth_hash).to be_kind_of(Hash)
129
- end
130
-
131
- it 'populates the uid' do
132
- expect(auth_hash['uid']).to eq('user1')
133
- end
134
-
135
- it 'populates the info hash' do
136
- expect(auth_hash['info']).to eq({ 'name' => 'Rockefeller' })
137
- end
138
- end
139
-
140
- context 'with invalid credentials' do
141
- before do
142
- allow(anon_ar).to receive('auth_key').and_return('email')
143
- OmniAuth.config.on_failure = ->(env) { [401, {}, [env['omniauth.error.type'].inspect]] }
144
- expect(anon_ar).to receive(:authenticate).with({ 'email' => 'wrong' }, 'login').and_return(false)
145
- post '/auth/identity/callback', auth_key: 'wrong', password: 'login'
146
- end
147
-
148
- it 'fails with :invalid_credentials' do
149
- expect(last_response.body).to eq(':invalid_credentials')
150
- end
151
- end
152
-
153
- context 'with auth scopes' do
154
- let(:identity_options) do
155
- { model: anon_ar, locate_conditions: lambda { |req|
156
- { model.auth_key => req['auth_key'], 'user_type' => 'admin' }
157
- } }
158
- end
159
-
160
- it 'evaluates and pass through conditions proc' do
161
- allow(anon_ar).to receive('auth_key').and_return('email')
162
- expect(anon_ar).to receive('authenticate').with({ 'email' => 'john', 'user_type' => 'admin' },
163
- 'awesome').and_return(user)
164
- post '/auth/identity/callback', auth_key: 'john', password: 'awesome'
165
- end
166
- end
167
- end
168
-
169
- describe '#registration_form' do
170
- context 'registration is enabled' do
171
- it 'triggers from /auth/identity/register by default' do
172
- get '/auth/identity/register'
173
- expect(last_response.body).to be_include('Register Identity')
174
- end
175
- end
176
-
177
- context 'registration is disabled' do
178
- let(:identity_options) { { model: anon_ar, enable_registration: false } }
179
-
180
- it 'calls app' do
181
- get '/auth/identity/register'
182
- expect(last_response.body).to be_include('HELLO!')
183
- end
184
- end
185
-
186
- it 'supports methods other than GET and POST' do
187
- head '/auth/identity/register'
188
- expect(last_response.status).to eq(404)
189
- end
190
- end
191
-
192
- describe '#registration_phase' do
193
- context 'registration is disabled' do
194
- let(:identity_options) { { model: anon_ar, enable_registration: false } }
195
-
196
- it 'calls app' do
197
- post '/auth/identity/register'
198
- expect(last_response.body).to eq('HELLO!')
199
- end
200
- end
201
-
202
- context 'with good identity' do
203
- let(:properties) do
204
- {
205
- name: 'Awesome Dude',
206
- email: 'awesome@example.com',
207
- password: 'face',
208
- password_confirmation: 'face',
209
- provider: 'identity'
210
- }
211
- end
212
-
213
- it 'sets the auth hash' do
214
- post '/auth/identity/register', properties
215
- expect(auth_hash['uid']).to match(/\d+/)
216
- expect(auth_hash['provider']).to eq('identity')
217
- end
218
-
219
- context 'with on_validation proc' do
220
- let(:identity_options) do
221
- { model: anon_ar, on_validation: on_validation_proc }
222
- end
223
- let(:on_validation_proc) do
224
- lambda { |_env|
225
- false
226
- }
227
- end
228
-
229
- context 'when validation fails' do
230
- it 'does not set the env hash' do
231
- post '/auth/identity/register', properties
232
- expect(env_hash).to eq(nil)
233
- end
234
-
235
- it 'renders registration form' do
236
- post '/auth/identity/register', properties
237
- expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
238
- end
239
-
240
- it 'displays validation failure message' do
241
- post '/auth/identity/register', properties
242
- expect(last_response.body).to be_include(described_class.default_options[:validation_failure_message])
243
- end
244
- end
245
-
246
- context 'when validation succeeds' do
247
- let(:on_validation_proc) do
248
- lambda { |_env|
249
- true
250
- }
251
- end
252
-
253
- it 'sets the auth hash' do
254
- post '/auth/identity/register', properties
255
- expect(auth_hash['uid']).to match(/\d+/)
256
- expect(auth_hash['provider']).to eq('identity')
257
- end
258
-
259
- it 'does not render registration form' do
260
- post '/auth/identity/register', properties
261
- expect(last_response.body).not_to be_include(described_class.default_options[:registration_form_title])
262
- end
263
-
264
- it 'does not display validation failure message' do
265
- post '/auth/identity/register', properties
266
- expect(last_response.body).not_to be_include(described_class.default_options[:validation_failure_message])
267
- end
268
-
269
- it 'does not display registration failure message' do
270
- post '/auth/identity/register', properties
271
- expect(last_response.body).not_to be_include(described_class.default_options[:registration_failure_message])
272
- end
273
- end
274
- end
275
- end
276
-
277
- context 'with bad identity' do
278
- let(:properties) do
279
- {
280
- name: 'Awesome Dude',
281
- email: 'awesome@example.com',
282
- password: 'NOT',
283
- password_confirmation: 'MATCHING',
284
- provider: 'identity'
285
- }
286
- end
287
- let(:invalid_identity) { double(persisted?: false, save: false) }
288
-
289
- before do
290
- expect(anon_ar).to receive(:new).with(properties).and_return(invalid_identity)
291
- end
292
-
293
- context 'default' do
294
- it 'shows registration form' do
295
- post '/auth/identity/register', properties
296
- expect(last_response.body).to be_include('Register Identity')
297
- expect(last_response.body).to be_include('One or more fields were invalid')
298
- end
299
- end
300
-
301
- context 'custom on_failed_registration endpoint' do
302
- let(:identity_options) do
303
- { model: anon_ar, on_failed_registration: lambda { |env|
304
- [404, { 'env' => env }, ["FAIL'DOH!"]]
305
- } }
306
- end
307
-
308
- it 'sets the identity hash' do
309
- post '/auth/identity/register', properties
310
- expect(identity_hash).to eq(invalid_identity)
311
- expect(last_response.body).to be_include("FAIL'DOH!")
312
- expect(last_response.body).not_to be_include('One or more fields were invalid')
313
- end
314
- end
315
-
316
- context 'with on_validation proc' do
317
- let(:identity_options) do
318
- { model: anon_ar, on_validation: on_validation_proc }
319
- end
320
- let(:on_validation_proc) do
321
- lambda { |_env|
322
- false
323
- }
324
- end
325
-
326
- context 'when validation fails' do
327
- it 'does not set the env hash' do
328
- post '/auth/identity/register', properties
329
- expect(env_hash).to eq(nil)
330
- end
331
-
332
- it 'renders registration form' do
333
- post '/auth/identity/register', properties
334
- expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
335
- end
336
-
337
- it 'displays validation failure message' do
338
- post '/auth/identity/register', properties
339
- expect(last_response.body).to be_include(described_class.default_options[:validation_failure_message])
340
- end
341
- end
342
-
343
- context 'when validation succeeds' do
344
- let(:on_validation_proc) do
345
- lambda { |_env|
346
- true
347
- }
348
- end
349
-
350
- it 'does not set the env hash' do
351
- post '/auth/identity/register', properties
352
- expect(env_hash).to eq(nil)
353
- end
354
-
355
- it 'renders registration form' do
356
- post '/auth/identity/register', properties
357
- expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
358
- end
359
-
360
- it 'does not display validation failure message' do
361
- post '/auth/identity/register', properties
362
- expect(last_response.body).not_to be_include(described_class.default_options[:validation_failure_message])
363
- end
364
-
365
- it 'display registration failure message' do
366
- post '/auth/identity/register', properties
367
- expect(last_response.body).to be_include(described_class.default_options[:registration_failure_message])
368
- end
369
- end
370
- end
371
- end
372
- end
373
- end
data/spec/spec_helper.rb DELETED
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # NOTE: mongoid and no_brainer can't be loaded at the same time.
4
- # If you try it, one or both of them will not work.
5
- # This is why the ORM specs are split into a separate directory and run in separate threads.
6
-
7
- ENV['RUBY_ENV'] = 'test' # Used by NoBrainer
8
- ENV['MONGOID_ENV'] = 'test' # Used by Mongoid
9
-
10
- ruby_version = Gem::Version.new(RUBY_VERSION)
11
- require 'simplecov' if ruby_version >= Gem::Version.new('2.7') && RUBY_ENGINE == 'ruby'
12
-
13
- require 'rack/test'
14
- require 'rspec/block_is_expected'
15
- require 'byebug' if RUBY_ENGINE == 'ruby'
16
-
17
- # This gem
18
- require 'omniauth/identity'
19
-
20
- spec_root_matcher = %r{#{__dir__}/(.+)\.rb\Z}
21
- Dir.glob(Pathname.new(__dir__).join('support/**/', '*.rb')).each { |f| require f.match(spec_root_matcher)[1] }
22
-
23
- DEFAULT_PASSWORD = 'hang-a-left-at-the-diner'
24
- DEFAULT_EMAIL = 'mojo@example.com'
25
-
26
- RSpec.configure do |config|
27
- config.include Rack::Test::Methods
28
-
29
- # config.include ::Mongoid::Matchers, db: :mongodb
30
-
31
- # Enable flags like --only-failures and --next-failure
32
- config.example_status_persistence_file_path = '.rspec_status'
33
-
34
- # Disable RSpec exposing methods globally on `Module` and `main`
35
- config.disable_monkey_patching!
36
-
37
- config.expect_with :rspec do |c|
38
- c.syntax = :expect
39
- end
40
- end
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.shared_examples 'instance with instance methods' do
4
- describe '#initialize' do
5
- it 'does not raise an error' do
6
- block_is_expected.not_to raise_error
7
- end
8
- end
9
-
10
- describe '#uid' do
11
- it 'defaults to #id' do
12
- allow(instance).to receive(:respond_to?).with(:id).and_return(true)
13
- allow(instance).to receive(:id).and_return 'wakka-do'
14
- expect(instance.uid).to eq('wakka-do')
15
- end
16
-
17
- it 'stringifies it' do
18
- allow(instance).to receive(:id).and_return 123
19
- expect(instance.uid).to eq('123')
20
- end
21
-
22
- it 'raises NotImplementedError if #id is not defined' do
23
- allow(instance).to receive(:respond_to?).with(:id).and_return(false)
24
- expect { instance.uid }.to raise_error(NotImplementedError)
25
- end
26
- end
27
-
28
- describe '#auth_key' do
29
- it 'defaults to #email' do
30
- allow(instance).to receive(:respond_to?).with(:email).and_return(true)
31
- allow(instance).to receive(:email).and_return('bob@bob.com')
32
- expect(instance.auth_key).to eq('bob@bob.com')
33
- end
34
-
35
- it 'uses the class .auth_key' do
36
- instance.class.auth_key 'login'
37
- allow(instance).to receive(:login).and_return 'bob'
38
- expect(instance.auth_key).to eq('bob')
39
- instance.class.auth_key nil
40
- end
41
- end
42
-
43
- describe '#auth_key=' do
44
- it 'defaults to setting email' do
45
- allow(instance).to receive(:respond_to?).with(:email=).and_return(true)
46
- expect(instance).to receive(:email=).with 'abc'
47
-
48
- instance.auth_key = 'abc'
49
- end
50
-
51
- it 'uses a custom .auth_key if one is provided' do
52
- instance.class.auth_key 'login'
53
- allow(instance).to receive(:respond_to?).with(:login=).and_return(true)
54
- expect(instance).to receive(:login=).with('abc')
55
-
56
- instance.auth_key = 'abc'
57
- end
58
- end
59
-
60
- describe '#info' do
61
- it 'includes all attributes as they have been set' do
62
- allow(instance).to receive(:name).and_return('Bob Bobson')
63
- allow(instance).to receive(:nickname).and_return('bob')
64
-
65
- expect(instance.info).to include({
66
- 'name' => 'Bob Bobson',
67
- 'nickname' => 'bob'
68
- })
69
- end
70
-
71
- it 'uses firstname and lastname, over nickname, to set missing name' do
72
- allow(instance).to receive(:first_name).and_return('shoeless')
73
- allow(instance).to receive(:last_name).and_return('joe')
74
- allow(instance).to receive(:nickname).and_return('george')
75
- instance.info['name'] == 'shoeless joe'
76
- end
77
-
78
- it 'uses nickname to set missing name when first and last are not set' do
79
- allow(instance).to receive(:nickname).and_return('bob')
80
- instance.info['name'] == 'bob'
81
- end
82
-
83
- it 'does not overwrite a provided name' do
84
- allow(instance).to receive(:name).and_return('Awesome Dude')
85
- allow(instance).to receive(:first_name).and_return('Frank')
86
- expect(instance.info['name']).to eq('Awesome Dude')
87
- end
88
- end
89
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.shared_examples 'model with class methods' do
4
- describe 'class definition' do
5
- it 'does not raise an error' do
6
- block_is_expected.not_to raise_error
7
- end
8
- end
9
-
10
- describe '::authenticate' do
11
- it 'calls locate and then authenticate' do
12
- mocked_instance = double('ExampleModel', authenticate: 'abbadoo')
13
- allow(model_klass).to receive(:locate).with('email' => 'example').and_return(mocked_instance)
14
- expect(model_klass.authenticate({ 'email' => 'example' }, 'pass')).to eq('abbadoo')
15
- end
16
-
17
- it 'calls locate with additional scopes when provided' do
18
- mocked_instance = double('ExampleModel', authenticate: 'abbadoo')
19
- allow(model_klass).to receive(:locate).with('email' => 'example',
20
- 'user_type' => 'admin').and_return(mocked_instance)
21
- expect(model_klass.authenticate({ 'email' => 'example', 'user_type' => 'admin' }, 'pass')).to eq('abbadoo')
22
- end
23
-
24
- it 'recovers gracefully if locate is nil' do
25
- allow(model_klass).to receive(:locate).and_return(nil)
26
- expect(model_klass.authenticate('blah', 'foo')).to be false
27
- end
28
- end
29
- end