omniauth-identity 3.0.8 → 3.1.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.
@@ -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,39 +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
- def flower
18
- '🌸'
19
- end
20
- end
21
- end
22
-
23
- include_context 'persistable model'
24
-
25
- describe '::table_name' do
26
- it 'does not use STI rules for its table name' do
27
- expect(TestIdentity.table_name).to eq('test_identities')
28
- end
29
- end
30
-
31
- describe '::locate' do
32
- it 'delegates locate to the where query method' do
33
- allow(model_klass).to receive(:where).with('email' => 'open faced', 'category' => 'sandwiches',
34
- 'provider' => 'identity').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,38 +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
- end
22
- stub_const('SequelTestIdentity', sequel_test_identity)
23
- end
24
-
25
- describe 'model', type: :model do
26
- subject(:model_klass) { SequelTestIdentity }
27
-
28
- include_context 'persistable model'
29
-
30
- describe '::locate' do
31
- it 'delegates to the where query method' do
32
- allow(model_klass).to receive(:where).with('email' => 'open faced',
33
- 'category' => 'sandwiches').and_return(['wakka'])
34
- expect(model_klass.locate('email' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
35
- end
36
- end
37
- end
38
- 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,372 +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
- def balloon
21
- '🎈'
22
- end
23
- end
24
- end
25
-
26
- # customize rack app for testing, if block is given, reverts to default
27
- # rack app after testing is done
28
- def set_app!(identity_options = {})
29
- old_app = app
30
- self.app = Rack::Builder.app do
31
- use Rack::Session::Cookie, secret: '1234567890qwertyuiop'
32
- use OmniAuth::Strategies::Identity, identity_options
33
- run ->(env) { [404, { 'env' => env }, ['HELLO!']] }
34
- end
35
- if block_given?
36
- yield
37
- self.app = old_app
38
- end
39
- app
40
- end
41
-
42
- before do
43
- opts = identity_options.reverse_merge({ model: anon_ar })
44
- set_app!(opts)
45
- end
46
-
47
- describe '#request_phase' do
48
- context 'with default settings' do
49
- let(:identity_options) { { model: anon_ar } }
50
-
51
- it 'displays a form' do
52
- get '/auth/identity'
53
-
54
- expect(last_response.body).not_to eq('HELLO!')
55
- expect(last_response.body).to be_include('<form')
56
- end
57
- end
58
-
59
- context 'when login is enabled' do
60
- context 'when registration is enabled' do
61
- let(:identity_options) { { model: anon_ar, enable_registration: true, enable_login: true } }
62
-
63
- it 'displays a form with a link to register' do
64
- get '/auth/identity'
65
-
66
- expect(last_response.body).not_to eq('HELLO!')
67
- expect(last_response.body).to be_include('<form')
68
- expect(last_response.body).to be_include('<a')
69
- expect(last_response.body).to be_include('Create an Identity')
70
- end
71
- end
72
-
73
- context 'when registration is disabled' do
74
- let(:identity_options) { { model: anon_ar, enable_registration: false, enable_login: true } }
75
-
76
- it 'displays a form without a link to register' do
77
- get '/auth/identity'
78
-
79
- expect(last_response.body).not_to eq('HELLO!')
80
- expect(last_response.body).to be_include('<form')
81
- expect(last_response.body).not_to be_include('<a')
82
- expect(last_response.body).not_to be_include('Create an Identity')
83
- end
84
- end
85
- end
86
-
87
- context 'when login is disabled' do
88
- context 'when registration is enabled' do
89
- let(:identity_options) { { model: anon_ar, enable_registration: true, enable_login: false } }
90
-
91
- it 'bypasses registration form' do
92
- get '/auth/identity'
93
-
94
- expect(last_response.body).to eq('HELLO!')
95
- expect(last_response.body).not_to be_include('<form')
96
- expect(last_response.body).not_to be_include('<a')
97
- expect(last_response.body).not_to be_include('Create an Identity')
98
- end
99
- end
100
-
101
- context 'when registration is disabled' do
102
- let(:identity_options) { { model: anon_ar, enable_registration: false, enable_login: false } }
103
-
104
- it 'displays a form without a link to register' do
105
- get '/auth/identity'
106
-
107
- expect(last_response.body).to eq('HELLO!')
108
- expect(last_response.body).not_to be_include('<form')
109
- expect(last_response.body).not_to be_include('<a')
110
- expect(last_response.body).not_to be_include('Create an Identity')
111
- end
112
- end
113
- end
114
- end
115
-
116
- describe '#callback_phase' do
117
- let(:user) { double(uid: 'user1', info: { 'name' => 'Rockefeller' }) }
118
-
119
- context 'with valid credentials' do
120
- before do
121
- allow(anon_ar).to receive('auth_key').and_return('email')
122
- expect(anon_ar).to receive('authenticate').with({ 'email' => 'john' }, 'awesome').and_return(user)
123
- post '/auth/identity/callback', auth_key: 'john', password: 'awesome'
124
- end
125
-
126
- it 'populates the auth hash' do
127
- expect(auth_hash).to be_kind_of(Hash)
128
- end
129
-
130
- it 'populates the uid' do
131
- expect(auth_hash['uid']).to eq('user1')
132
- end
133
-
134
- it 'populates the info hash' do
135
- expect(auth_hash['info']).to eq({ 'name' => 'Rockefeller' })
136
- end
137
- end
138
-
139
- context 'with invalid credentials' do
140
- before do
141
- allow(anon_ar).to receive('auth_key').and_return('email')
142
- OmniAuth.config.on_failure = ->(env) { [401, {}, [env['omniauth.error.type'].inspect]] }
143
- expect(anon_ar).to receive(:authenticate).with({ 'email' => 'wrong' }, 'login').and_return(false)
144
- post '/auth/identity/callback', auth_key: 'wrong', password: 'login'
145
- end
146
-
147
- it 'fails with :invalid_credentials' do
148
- expect(last_response.body).to eq(':invalid_credentials')
149
- end
150
- end
151
-
152
- context 'with auth scopes' do
153
- let(:identity_options) do
154
- { model: anon_ar, locate_conditions: lambda { |req|
155
- { model.auth_key => req['auth_key'], 'user_type' => 'admin' }
156
- } }
157
- end
158
-
159
- it 'evaluates and pass through conditions proc' do
160
- allow(anon_ar).to receive('auth_key').and_return('email')
161
- expect(anon_ar).to receive('authenticate').with({ 'email' => 'john', 'user_type' => 'admin' },
162
- 'awesome').and_return(user)
163
- post '/auth/identity/callback', auth_key: 'john', password: 'awesome'
164
- end
165
- end
166
- end
167
-
168
- describe '#registration_form' do
169
- context 'registration is enabled' do
170
- it 'triggers from /auth/identity/register by default' do
171
- get '/auth/identity/register'
172
- expect(last_response.body).to be_include('Register Identity')
173
- end
174
- end
175
-
176
- context 'registration is disabled' do
177
- let(:identity_options) { { model: anon_ar, enable_registration: false } }
178
-
179
- it 'calls app' do
180
- get '/auth/identity/register'
181
- expect(last_response.body).to be_include('HELLO!')
182
- end
183
- end
184
-
185
- it 'supports methods other than GET and POST' do
186
- head '/auth/identity/register'
187
- expect(last_response.status).to eq(404)
188
- end
189
- end
190
-
191
- describe '#registration_phase' do
192
- context 'registration is disabled' do
193
- let(:identity_options) { { model: anon_ar, enable_registration: false } }
194
-
195
- it 'calls app' do
196
- post '/auth/identity/register'
197
- expect(last_response.body).to eq('HELLO!')
198
- end
199
- end
200
-
201
- context 'with good identity' do
202
- let(:properties) do
203
- {
204
- name: 'Awesome Dude',
205
- email: 'awesome@example.com',
206
- password: 'face',
207
- password_confirmation: 'face',
208
- provider: 'identity'
209
- }
210
- end
211
-
212
- it 'sets the auth hash' do
213
- post '/auth/identity/register', properties
214
- expect(auth_hash['uid']).to match(/\d+/)
215
- expect(auth_hash['provider']).to eq('identity')
216
- end
217
-
218
- context 'with on_validation proc' do
219
- let(:identity_options) do
220
- { model: anon_ar, on_validation: on_validation_proc }
221
- end
222
- let(:on_validation_proc) do
223
- lambda { |_env|
224
- false
225
- }
226
- end
227
-
228
- context 'when validation fails' do
229
- it 'does not set the env hash' do
230
- post '/auth/identity/register', properties
231
- expect(env_hash).to eq(nil)
232
- end
233
-
234
- it 'renders registration form' do
235
- post '/auth/identity/register', properties
236
- expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
237
- end
238
-
239
- it 'displays validation failure message' do
240
- post '/auth/identity/register', properties
241
- expect(last_response.body).to be_include(described_class.default_options[:validation_failure_message])
242
- end
243
- end
244
-
245
- context 'when validation succeeds' do
246
- let(:on_validation_proc) do
247
- lambda { |_env|
248
- true
249
- }
250
- end
251
-
252
- it 'sets the auth hash' do
253
- post '/auth/identity/register', properties
254
- expect(auth_hash['uid']).to match(/\d+/)
255
- expect(auth_hash['provider']).to eq('identity')
256
- end
257
-
258
- it 'does not render registration form' do
259
- post '/auth/identity/register', properties
260
- expect(last_response.body).not_to be_include(described_class.default_options[:registration_form_title])
261
- end
262
-
263
- it 'does not display validation failure message' do
264
- post '/auth/identity/register', properties
265
- expect(last_response.body).not_to be_include(described_class.default_options[:validation_failure_message])
266
- end
267
-
268
- it 'does not display registration failure message' do
269
- post '/auth/identity/register', properties
270
- expect(last_response.body).not_to be_include(described_class.default_options[:registration_failure_message])
271
- end
272
- end
273
- end
274
- end
275
-
276
- context 'with bad identity' do
277
- let(:properties) do
278
- {
279
- name: 'Awesome Dude',
280
- email: 'awesome@example.com',
281
- password: 'NOT',
282
- password_confirmation: 'MATCHING',
283
- provider: 'identity'
284
- }
285
- end
286
- let(:invalid_identity) { double(persisted?: false, save: false) }
287
-
288
- before do
289
- expect(anon_ar).to receive(:new).with(properties).and_return(invalid_identity)
290
- end
291
-
292
- context 'default' do
293
- it 'shows registration form' do
294
- post '/auth/identity/register', properties
295
- expect(last_response.body).to be_include('Register Identity')
296
- expect(last_response.body).to be_include('One or more fields were invalid')
297
- end
298
- end
299
-
300
- context 'custom on_failed_registration endpoint' do
301
- let(:identity_options) do
302
- { model: anon_ar, on_failed_registration: lambda { |env|
303
- [404, { 'env' => env }, ["FAIL'DOH!"]]
304
- } }
305
- end
306
-
307
- it 'sets the identity hash' do
308
- post '/auth/identity/register', properties
309
- expect(identity_hash).to eq(invalid_identity)
310
- expect(last_response.body).to be_include("FAIL'DOH!")
311
- expect(last_response.body).not_to be_include('One or more fields were invalid')
312
- end
313
- end
314
-
315
- context 'with on_validation proc' do
316
- let(:identity_options) do
317
- { model: anon_ar, on_validation: on_validation_proc }
318
- end
319
- let(:on_validation_proc) do
320
- lambda { |_env|
321
- false
322
- }
323
- end
324
-
325
- context 'when validation fails' do
326
- it 'does not set the env hash' do
327
- post '/auth/identity/register', properties
328
- expect(env_hash).to eq(nil)
329
- end
330
-
331
- it 'renders registration form' do
332
- post '/auth/identity/register', properties
333
- expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
334
- end
335
-
336
- it 'displays validation failure message' do
337
- post '/auth/identity/register', properties
338
- expect(last_response.body).to be_include(described_class.default_options[:validation_failure_message])
339
- end
340
- end
341
-
342
- context 'when validation succeeds' do
343
- let(:on_validation_proc) do
344
- lambda { |_env|
345
- true
346
- }
347
- end
348
-
349
- it 'does not set the env hash' do
350
- post '/auth/identity/register', properties
351
- expect(env_hash).to eq(nil)
352
- end
353
-
354
- it 'renders registration form' do
355
- post '/auth/identity/register', properties
356
- expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
357
- end
358
-
359
- it 'does not display validation failure message' do
360
- post '/auth/identity/register', properties
361
- expect(last_response.body).not_to be_include(described_class.default_options[:validation_failure_message])
362
- end
363
-
364
- it 'display registration failure message' do
365
- post '/auth/identity/register', properties
366
- expect(last_response.body).to be_include(described_class.default_options[:registration_failure_message])
367
- end
368
- end
369
- end
370
- end
371
- end
372
- 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