omniauth-identity 3.0.9 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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