omniauth-identity 2.0.0 → 3.0.4
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 +61 -1
- data/CODE_OF_CONDUCT.md +133 -0
- data/LICENSE +2 -1
- data/README.md +256 -0
- data/lib/omniauth-identity.rb +2 -0
- data/lib/omniauth-identity/version.rb +3 -1
- data/lib/omniauth/identity.rb +4 -1
- data/lib/omniauth/identity/model.rb +13 -11
- data/lib/omniauth/identity/models/active_record.rb +4 -1
- data/lib/omniauth/identity/models/couch_potato.rb +3 -4
- data/lib/omniauth/identity/models/mongoid.rb +3 -7
- data/lib/omniauth/identity/models/no_brainer.rb +30 -0
- data/lib/omniauth/identity/models/sequel.rb +37 -0
- data/lib/omniauth/identity/secure_password.rb +4 -4
- data/lib/omniauth/strategies/identity.rb +92 -39
- data/spec/omniauth/identity/model_spec.rb +36 -33
- data/spec/omniauth/identity/models/active_record_spec.rb +23 -9
- data/spec/omniauth/identity/models/couch_potato_spec.rb +13 -8
- data/spec/omniauth/identity/models/mongoid_spec.rb +16 -11
- data/spec/omniauth/identity/models/no_brainer_spec.rb +17 -0
- data/spec/omniauth/identity/models/sequel_spec.rb +23 -0
- data/spec/omniauth/identity/secure_password_spec.rb +10 -8
- data/spec/omniauth/strategies/identity_spec.rb +174 -61
- data/spec/spec_helper.rb +17 -8
- metadata +60 -97
- data/.gitignore +0 -6
- data/.rspec +0 -3
- data/Gemfile +0 -13
- data/Guardfile +0 -10
- data/README.markdown +0 -204
- data/Rakefile +0 -9
- data/lib/omniauth/identity/models/data_mapper.rb +0 -32
- data/omniauth-identity.gemspec +0 -32
- data/spec/omniauth/identity/models/data_mapper_spec.rb +0 -24
@@ -1,88 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class ExampleModel
|
2
4
|
include OmniAuth::Identity::Model
|
3
5
|
end
|
4
6
|
|
5
|
-
describe OmniAuth::Identity::Model do
|
7
|
+
RSpec.describe OmniAuth::Identity::Model do
|
6
8
|
context 'Class Methods' do
|
7
|
-
subject{ ExampleModel }
|
9
|
+
subject { ExampleModel }
|
8
10
|
|
9
11
|
describe '.locate' do
|
10
|
-
it('
|
12
|
+
it('is abstract') { expect { subject.locate('abc') }.to raise_error(NotImplementedError) }
|
11
13
|
end
|
12
14
|
|
13
15
|
describe '.authenticate' do
|
14
|
-
it '
|
15
|
-
mocked_instance = double('ExampleModel', :
|
16
|
+
it 'calls locate and then authenticate' do
|
17
|
+
mocked_instance = double('ExampleModel', authenticate: 'abbadoo')
|
16
18
|
allow(subject).to receive(:locate).with('email' => 'example').and_return(mocked_instance)
|
17
|
-
expect(subject.authenticate({'email' => 'example'},'pass')).to eq('abbadoo')
|
19
|
+
expect(subject.authenticate({ 'email' => 'example' }, 'pass')).to eq('abbadoo')
|
18
20
|
end
|
19
21
|
|
20
|
-
it '
|
21
|
-
mocked_instance = double('ExampleModel', :
|
22
|
-
allow(subject).to receive(:locate).with('email' => 'example',
|
23
|
-
|
22
|
+
it 'calls locate with additional scopes when provided' do
|
23
|
+
mocked_instance = double('ExampleModel', authenticate: 'abbadoo')
|
24
|
+
allow(subject).to receive(:locate).with('email' => 'example',
|
25
|
+
'user_type' => 'admin').and_return(mocked_instance)
|
26
|
+
expect(subject.authenticate({ 'email' => 'example', 'user_type' => 'admin' }, 'pass')).to eq('abbadoo')
|
24
27
|
end
|
25
28
|
|
26
|
-
it '
|
29
|
+
it 'recovers gracefully if locate is nil' do
|
27
30
|
allow(subject).to receive(:locate).and_return(nil)
|
28
|
-
expect(subject.authenticate('blah','foo')).to be false
|
31
|
+
expect(subject.authenticate('blah', 'foo')).to be false
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
36
|
context 'Instance Methods' do
|
34
|
-
subject{ ExampleModel.new }
|
37
|
+
subject { ExampleModel.new }
|
35
38
|
|
36
39
|
describe '#authenticate' do
|
37
|
-
it('
|
40
|
+
it('is abstract') { expect { subject.authenticate('abc') }.to raise_error(NotImplementedError) }
|
38
41
|
end
|
39
42
|
|
40
43
|
describe '#uid' do
|
41
|
-
it '
|
44
|
+
it 'defaults to #id' do
|
42
45
|
allow(subject).to receive(:respond_to?).with(:id).and_return(true)
|
43
46
|
allow(subject).to receive(:id).and_return 'wakka-do'
|
44
47
|
expect(subject.uid).to eq('wakka-do')
|
45
48
|
end
|
46
49
|
|
47
|
-
it '
|
50
|
+
it 'stringifies it' do
|
48
51
|
allow(subject).to receive(:id).and_return 123
|
49
52
|
expect(subject.uid).to eq('123')
|
50
53
|
end
|
51
54
|
|
52
|
-
it '
|
55
|
+
it 'raises NotImplementedError if #id is not defined' do
|
53
56
|
allow(subject).to receive(:respond_to?).with(:id).and_return(false)
|
54
|
-
expect{ subject.uid }.to raise_error(NotImplementedError)
|
57
|
+
expect { subject.uid }.to raise_error(NotImplementedError)
|
55
58
|
end
|
56
59
|
end
|
57
60
|
|
58
61
|
describe '#auth_key' do
|
59
|
-
it '
|
62
|
+
it 'defaults to #email' do
|
60
63
|
allow(subject).to receive(:respond_to?).with(:email).and_return(true)
|
61
64
|
allow(subject).to receive(:email).and_return('bob@bob.com')
|
62
65
|
expect(subject.auth_key).to eq('bob@bob.com')
|
63
66
|
end
|
64
67
|
|
65
|
-
it '
|
68
|
+
it 'uses the class .auth_key' do
|
66
69
|
subject.class.auth_key 'login'
|
67
70
|
allow(subject).to receive(:login).and_return 'bob'
|
68
71
|
expect(subject.auth_key).to eq('bob')
|
69
72
|
subject.class.auth_key nil
|
70
73
|
end
|
71
74
|
|
72
|
-
it '
|
73
|
-
expect{ subject.auth_key }.to raise_error(NotImplementedError)
|
75
|
+
it 'raises a NotImplementedError if the auth_key method is not defined' do
|
76
|
+
expect { subject.auth_key }.to raise_error(NotImplementedError)
|
74
77
|
end
|
75
78
|
end
|
76
79
|
|
77
80
|
describe '#auth_key=' do
|
78
|
-
it '
|
81
|
+
it 'defaults to setting email' do
|
79
82
|
allow(subject).to receive(:respond_to?).with(:email=).and_return(true)
|
80
83
|
expect(subject).to receive(:email=).with 'abc'
|
81
|
-
|
84
|
+
|
82
85
|
subject.auth_key = 'abc'
|
83
86
|
end
|
84
87
|
|
85
|
-
it '
|
88
|
+
it 'uses a custom .auth_key if one is provided' do
|
86
89
|
subject.class.auth_key 'login'
|
87
90
|
allow(subject).to receive(:respond_to?).with(:login=).and_return(true)
|
88
91
|
expect(subject).to receive(:login=).with('abc')
|
@@ -90,28 +93,28 @@ describe OmniAuth::Identity::Model do
|
|
90
93
|
subject.auth_key = 'abc'
|
91
94
|
end
|
92
95
|
|
93
|
-
it '
|
94
|
-
expect{ subject.auth_key = 'broken' }.to raise_error(NotImplementedError)
|
96
|
+
it 'raises a NotImplementedError if the autH_key method is not defined' do
|
97
|
+
expect { subject.auth_key = 'broken' }.to raise_error(NotImplementedError)
|
95
98
|
end
|
96
99
|
end
|
97
100
|
|
98
101
|
describe '#info' do
|
99
|
-
it '
|
102
|
+
it 'includes attributes that are set' do
|
100
103
|
allow(subject).to receive(:name).and_return('Bob Bobson')
|
101
104
|
allow(subject).to receive(:nickname).and_return('bob')
|
102
105
|
|
103
106
|
expect(subject.info).to eq({
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
+
'name' => 'Bob Bobson',
|
108
|
+
'nickname' => 'bob'
|
109
|
+
})
|
107
110
|
end
|
108
111
|
|
109
|
-
it '
|
112
|
+
it 'automaticallies set name off of nickname' do
|
110
113
|
allow(subject).to receive(:nickname).and_return('bob')
|
111
114
|
subject.info['name'] == 'bob'
|
112
115
|
end
|
113
116
|
|
114
|
-
it '
|
117
|
+
it 'does not overwrite a provided name' do
|
115
118
|
allow(subject).to receive(:name).and_return('Awesome Dude')
|
116
119
|
allow(subject).to receive(:first_name).and_return('Frank')
|
117
120
|
expect(subject.info['name']).to eq('Awesome Dude')
|
@@ -1,16 +1,30 @@
|
|
1
|
-
|
2
|
-
class TestIdentity < OmniAuth::Identity::Models::ActiveRecord; end
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
RSpec.describe(OmniAuth::Identity::Models::ActiveRecord, db: true) do
|
4
|
+
describe 'model', type: :model do
|
5
|
+
subject(:model_klass) do
|
6
|
+
AnonymousActiveRecord.generate(
|
7
|
+
parent_klass: 'OmniAuth::Identity::Models::ActiveRecord',
|
8
|
+
columns: OmniAuth::Identity::Model::SCHEMA_ATTRIBUTES | %w[provider password_digest],
|
9
|
+
connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' }
|
10
|
+
) do
|
11
|
+
def flower
|
12
|
+
'🌸'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
6
16
|
|
7
|
-
it '
|
8
|
-
allow(
|
9
|
-
|
17
|
+
it 'delegates locate to the where query method' do
|
18
|
+
allow(model_klass).to receive(:where).with('ham_sandwich' => 'open faced', 'category' => 'sandwiches',
|
19
|
+
'provider' => 'identity').and_return(['wakka'])
|
20
|
+
expect(model_klass.locate('ham_sandwich' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
|
10
21
|
end
|
22
|
+
end
|
11
23
|
|
12
|
-
|
13
|
-
|
24
|
+
describe '#table_name' do
|
25
|
+
class TestIdentity < OmniAuth::Identity::Models::ActiveRecord; end
|
26
|
+
it 'does not use STI rules for its table name' do
|
27
|
+
expect(TestIdentity.table_name).to eq('test_identities')
|
14
28
|
end
|
15
29
|
end
|
16
30
|
end
|
@@ -1,15 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'couch_potato'
|
4
|
+
|
5
|
+
class CouchPotatoTestIdentity
|
6
|
+
include CouchPotato::Persistence
|
7
|
+
include OmniAuth::Identity::Models::CouchPotatoModule
|
8
|
+
auth_key :ham_sandwich
|
9
|
+
end
|
7
10
|
|
11
|
+
RSpec.describe(OmniAuth::Identity::Models::CouchPotatoModule, db: true) do
|
8
12
|
describe 'model', type: :model do
|
9
13
|
subject { CouchPotatoTestIdentity }
|
10
14
|
|
11
|
-
it '
|
12
|
-
allow(subject).to receive(:where).with('ham_sandwich' => 'open faced',
|
15
|
+
it 'delegates locate to the where query method' do
|
16
|
+
allow(subject).to receive(:where).with('ham_sandwich' => 'open faced',
|
17
|
+
'category' => 'sandwiches').and_return(['wakka'])
|
13
18
|
expect(subject.locate('ham_sandwich' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
|
14
19
|
end
|
15
20
|
end
|
@@ -1,22 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mongoid'
|
4
|
+
|
5
|
+
class MongoidTestIdentity
|
6
|
+
include Mongoid::Document
|
7
|
+
include OmniAuth::Identity::Models::Mongoid
|
8
|
+
auth_key :ham_sandwich
|
9
|
+
store_in database: 'db1', collection: 'mongoid_test_identities', client: 'secondary'
|
10
|
+
end
|
8
11
|
|
9
|
-
|
12
|
+
RSpec.describe(OmniAuth::Identity::Models::Mongoid, db: true) do
|
13
|
+
describe 'model', type: :model do
|
10
14
|
subject { MongoidTestIdentity }
|
11
15
|
|
12
16
|
it { is_expected.to be_mongoid_document }
|
13
17
|
|
14
18
|
it 'does not munge collection name' do
|
15
|
-
|
19
|
+
expect(subject).to be_stored_in(database: 'db1', collection: 'mongoid_test_identities', client: 'secondary')
|
16
20
|
end
|
17
21
|
|
18
|
-
it '
|
19
|
-
allow(subject).to receive(:where).with('ham_sandwich' => 'open faced',
|
22
|
+
it 'delegates locate to the where query method' do
|
23
|
+
allow(subject).to receive(:where).with('ham_sandwich' => 'open faced',
|
24
|
+
'category' => 'sandwiches').and_return(['wakka'])
|
20
25
|
expect(subject.locate('ham_sandwich' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
|
21
26
|
end
|
22
27
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nobrainer'
|
4
|
+
|
5
|
+
class NobrainerTestIdentity
|
6
|
+
include NoBrainer::Document
|
7
|
+
include OmniAuth::Identity::Models::NoBrainer
|
8
|
+
auth_key :ham_sandwich
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec.describe(OmniAuth::Identity::Models::NoBrainer, db: true) do
|
12
|
+
it 'delegates locate to the where query method' do
|
13
|
+
allow(NobrainerTestIdentity).to receive(:where).with('ham_sandwich' => 'open faced',
|
14
|
+
'category' => 'sandwiches').and_return(['wakka'])
|
15
|
+
expect(NobrainerTestIdentity.locate('ham_sandwich' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sequel'
|
4
|
+
# Connect to an in-memory sqlite3 database.
|
5
|
+
DB = Sequel.sqlite
|
6
|
+
DB.create_table :sequel_test_identities do
|
7
|
+
primary_key :id
|
8
|
+
String :ham_sandwich, null: false
|
9
|
+
String :password_digest, null: false
|
10
|
+
end
|
11
|
+
|
12
|
+
class SequelTestIdentity < Sequel::Model
|
13
|
+
include OmniAuth::Identity::Models::Sequel
|
14
|
+
auth_key :ham_sandwich
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.describe(OmniAuth::Identity::Models::Sequel, db: true) do
|
18
|
+
it 'delegates locate to the where query method' do
|
19
|
+
allow(SequelTestIdentity).to receive(:where).with('ham_sandwich' => 'open faced',
|
20
|
+
'category' => 'sandwiches').and_return(['wakka'])
|
21
|
+
expect(SequelTestIdentity.locate('ham_sandwich' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
|
22
|
+
end
|
23
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class HasTheMethod
|
2
4
|
def self.has_secure_password; end
|
3
5
|
end
|
@@ -5,20 +7,20 @@ end
|
|
5
7
|
class DoesNotHaveTheMethod
|
6
8
|
end
|
7
9
|
|
8
|
-
describe OmniAuth::Identity::SecurePassword do
|
9
|
-
it '
|
10
|
+
RSpec.describe OmniAuth::Identity::SecurePassword do
|
11
|
+
it 'extends with the class methods if it does not have the method' do
|
10
12
|
expect(DoesNotHaveTheMethod).to receive(:extend).with(OmniAuth::Identity::SecurePassword::ClassMethods)
|
11
|
-
DoesNotHaveTheMethod.
|
13
|
+
DoesNotHaveTheMethod.include described_class
|
12
14
|
end
|
13
15
|
|
14
|
-
it '
|
16
|
+
it 'does not extend if the method is already defined' do
|
15
17
|
expect(HasTheMethod).not_to receive(:extend)
|
16
|
-
HasTheMethod.
|
18
|
+
HasTheMethod.include described_class
|
17
19
|
end
|
18
20
|
|
19
|
-
it '
|
20
|
-
[HasTheMethod,DoesNotHaveTheMethod].each do |klass|
|
21
|
-
klass.send(:include,
|
21
|
+
it 'responds to has_secure_password afterwards' do
|
22
|
+
[HasTheMethod, DoesNotHaveTheMethod].each do |klass|
|
23
|
+
klass.send(:include, described_class)
|
22
24
|
expect(klass).to be_respond_to(:has_secure_password)
|
23
25
|
end
|
24
26
|
end
|
@@ -1,139 +1,252 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
describe OmniAuth::Strategies::Identity do
|
3
|
+
RSpec.describe OmniAuth::Strategies::Identity do
|
4
4
|
attr_accessor :app
|
5
5
|
|
6
|
-
let(:auth_hash){ last_response.headers['env']['omniauth.auth'] }
|
7
|
-
let(:identity_hash){ last_response.headers['env']['omniauth.identity'] }
|
6
|
+
let(:auth_hash) { last_response.headers['env']['omniauth.auth'] }
|
7
|
+
let(:identity_hash) { last_response.headers['env']['omniauth.identity'] }
|
8
|
+
let(:identity_options) { {} }
|
9
|
+
let(:anon_ar) do
|
10
|
+
AnonymousActiveRecord.generate(
|
11
|
+
parent_klass: 'OmniAuth::Identity::Models::ActiveRecord',
|
12
|
+
columns: OmniAuth::Identity::Model::SCHEMA_ATTRIBUTES | %w[provider password_digest],
|
13
|
+
connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' }
|
14
|
+
) do
|
15
|
+
def balloon
|
16
|
+
'🎈'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
8
20
|
|
9
21
|
# customize rack app for testing, if block is given, reverts to default
|
10
22
|
# rack app after testing is done
|
11
23
|
def set_app!(identity_options = {})
|
12
|
-
|
13
|
-
old_app = self.app
|
24
|
+
old_app = app
|
14
25
|
self.app = Rack::Builder.app do
|
15
26
|
use Rack::Session::Cookie, secret: '1234567890qwertyuiop'
|
16
27
|
use OmniAuth::Strategies::Identity, identity_options
|
17
|
-
run
|
28
|
+
run ->(env) { [404, { 'env' => env }, ['HELLO!']] }
|
18
29
|
end
|
19
30
|
if block_given?
|
20
31
|
yield
|
21
32
|
self.app = old_app
|
22
33
|
end
|
23
|
-
|
34
|
+
app
|
24
35
|
end
|
25
36
|
|
26
|
-
before
|
27
|
-
|
37
|
+
before do
|
38
|
+
opts = identity_options.reverse_merge({ model: anon_ar })
|
39
|
+
set_app!(opts)
|
28
40
|
end
|
29
41
|
|
30
42
|
describe '#request_phase' do
|
31
|
-
|
32
|
-
|
33
|
-
|
43
|
+
context 'with default settings' do
|
44
|
+
let(:identity_options) { { model: anon_ar } }
|
45
|
+
|
46
|
+
it 'displays a form' do
|
47
|
+
get '/auth/identity'
|
48
|
+
|
49
|
+
expect(last_response.body).not_to eq('HELLO!')
|
50
|
+
expect(last_response.body).to be_include('<form')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when login is enabled' do
|
55
|
+
context 'when registration is enabled' do
|
56
|
+
let(:identity_options) { { model: anon_ar, enable_registration: true, enable_login: true } }
|
57
|
+
|
58
|
+
it 'displays a form with a link to register' do
|
59
|
+
get '/auth/identity'
|
60
|
+
|
61
|
+
expect(last_response.body).not_to eq('HELLO!')
|
62
|
+
expect(last_response.body).to be_include('<form')
|
63
|
+
expect(last_response.body).to be_include('<a')
|
64
|
+
expect(last_response.body).to be_include('Create an Identity')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when registration is disabled' do
|
69
|
+
let(:identity_options) { { model: anon_ar, enable_registration: false, enable_login: true } }
|
70
|
+
|
71
|
+
it 'displays a form without a link to register' do
|
72
|
+
get '/auth/identity'
|
73
|
+
|
74
|
+
expect(last_response.body).not_to eq('HELLO!')
|
75
|
+
expect(last_response.body).to be_include('<form')
|
76
|
+
expect(last_response.body).not_to be_include('<a')
|
77
|
+
expect(last_response.body).not_to be_include('Create an Identity')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'when login is disabled' do
|
83
|
+
context 'when registration is enabled' do
|
84
|
+
let(:identity_options) { { model: anon_ar, enable_registration: true, enable_login: false } }
|
85
|
+
|
86
|
+
it 'bypasses registration form' do
|
87
|
+
get '/auth/identity'
|
88
|
+
|
89
|
+
expect(last_response.body).to eq('HELLO!')
|
90
|
+
expect(last_response.body).not_to be_include('<form')
|
91
|
+
expect(last_response.body).not_to be_include('<a')
|
92
|
+
expect(last_response.body).not_to be_include('Create an Identity')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when registration is disabled' do
|
97
|
+
let(:identity_options) { { model: anon_ar, enable_registration: false, enable_login: false } }
|
98
|
+
|
99
|
+
it 'displays a form without a link to register' do
|
100
|
+
get '/auth/identity'
|
101
|
+
|
102
|
+
expect(last_response.body).to eq('HELLO!')
|
103
|
+
expect(last_response.body).not_to be_include('<form')
|
104
|
+
expect(last_response.body).not_to be_include('<a')
|
105
|
+
expect(last_response.body).not_to be_include('Create an Identity')
|
106
|
+
end
|
107
|
+
end
|
34
108
|
end
|
35
109
|
end
|
36
110
|
|
37
111
|
describe '#callback_phase' do
|
38
|
-
let(:user){ double(:
|
112
|
+
let(:user) { double(uid: 'user1', info: { 'name' => 'Rockefeller' }) }
|
39
113
|
|
40
114
|
context 'with valid credentials' do
|
41
115
|
before do
|
42
|
-
allow(
|
43
|
-
expect(
|
44
|
-
post '/auth/identity/callback', :
|
116
|
+
allow(anon_ar).to receive('auth_key').and_return('email')
|
117
|
+
expect(anon_ar).to receive('authenticate').with({ 'email' => 'john' }, 'awesome').and_return(user)
|
118
|
+
post '/auth/identity/callback', auth_key: 'john', password: 'awesome'
|
45
119
|
end
|
46
120
|
|
47
|
-
it '
|
121
|
+
it 'populates the auth hash' do
|
48
122
|
expect(auth_hash).to be_kind_of(Hash)
|
49
123
|
end
|
50
124
|
|
51
|
-
it '
|
125
|
+
it 'populates the uid' do
|
52
126
|
expect(auth_hash['uid']).to eq('user1')
|
53
127
|
end
|
54
128
|
|
55
|
-
it '
|
56
|
-
expect(auth_hash['info']).to eq({'name' => 'Rockefeller'})
|
129
|
+
it 'populates the info hash' do
|
130
|
+
expect(auth_hash['info']).to eq({ 'name' => 'Rockefeller' })
|
57
131
|
end
|
58
132
|
end
|
59
133
|
|
60
134
|
context 'with invalid credentials' do
|
61
135
|
before do
|
62
|
-
allow(
|
63
|
-
OmniAuth.config.on_failure =
|
64
|
-
expect(
|
65
|
-
post '/auth/identity/callback', :
|
136
|
+
allow(anon_ar).to receive('auth_key').and_return('email')
|
137
|
+
OmniAuth.config.on_failure = ->(env) { [401, {}, [env['omniauth.error.type'].inspect]] }
|
138
|
+
expect(anon_ar).to receive(:authenticate).with({ 'email' => 'wrong' }, 'login').and_return(false)
|
139
|
+
post '/auth/identity/callback', auth_key: 'wrong', password: 'login'
|
66
140
|
end
|
67
141
|
|
68
|
-
it '
|
142
|
+
it 'fails with :invalid_credentials' do
|
69
143
|
expect(last_response.body).to eq(':invalid_credentials')
|
70
144
|
end
|
71
145
|
end
|
72
146
|
|
73
147
|
context 'with auth scopes' do
|
148
|
+
let(:identity_options) do
|
149
|
+
{ model: anon_ar, locate_conditions: lambda { |req|
|
150
|
+
{ model.auth_key => req['auth_key'], 'user_type' => 'admin' }
|
151
|
+
} }
|
152
|
+
end
|
74
153
|
|
75
|
-
it '
|
76
|
-
allow(
|
77
|
-
|
78
|
-
|
79
|
-
post '/auth/identity/callback', :
|
154
|
+
it 'evaluates and pass through conditions proc' do
|
155
|
+
allow(anon_ar).to receive('auth_key').and_return('email')
|
156
|
+
expect(anon_ar).to receive('authenticate').with({ 'email' => 'john', 'user_type' => 'admin' },
|
157
|
+
'awesome').and_return(user)
|
158
|
+
post '/auth/identity/callback', auth_key: 'john', password: 'awesome'
|
80
159
|
end
|
81
160
|
end
|
82
161
|
end
|
83
162
|
|
84
163
|
describe '#registration_form' do
|
85
|
-
|
86
|
-
|
87
|
-
|
164
|
+
context 'registration is enabled' do
|
165
|
+
it 'triggers from /auth/identity/register by default' do
|
166
|
+
get '/auth/identity/register'
|
167
|
+
expect(last_response.body).to be_include('Register Identity')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'registration is disabled' do
|
172
|
+
let(:identity_options) { { model: anon_ar, enable_registration: false } }
|
173
|
+
|
174
|
+
it 'calls app' do
|
175
|
+
get '/auth/identity/register'
|
176
|
+
expect(last_response.body).to be_include('HELLO!')
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'supports methods other than GET and POST' do
|
181
|
+
head '/auth/identity/register'
|
182
|
+
expect(last_response.status).to eq(404)
|
88
183
|
end
|
89
184
|
end
|
90
185
|
|
91
186
|
describe '#registration_phase' do
|
92
|
-
context '
|
93
|
-
let(:
|
94
|
-
:name => 'Awesome Dude',
|
95
|
-
:email => 'awesome@example.com',
|
96
|
-
:password => 'face',
|
97
|
-
:password_confirmation => 'face'
|
98
|
-
} }
|
187
|
+
context 'registration is disabled' do
|
188
|
+
let(:identity_options) { { model: anon_ar, enable_registration: false } }
|
99
189
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
expect(MockIdentity).to receive(:create).with(properties).and_return(m)
|
190
|
+
it 'calls app' do
|
191
|
+
post '/auth/identity/register'
|
192
|
+
expect(last_response.body).to eq('HELLO!')
|
104
193
|
end
|
194
|
+
end
|
105
195
|
|
106
|
-
|
196
|
+
context 'with successful creation' do
|
197
|
+
let(:properties) do
|
198
|
+
{
|
199
|
+
name: 'Awesome Dude',
|
200
|
+
email: 'awesome@example.com',
|
201
|
+
password: 'face',
|
202
|
+
password_confirmation: 'face',
|
203
|
+
provider: 'identity'
|
204
|
+
}
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'sets the auth hash' do
|
107
208
|
post '/auth/identity/register', properties
|
108
|
-
expect(auth_hash['uid']).to
|
209
|
+
expect(auth_hash['uid']).to match(/\d+/)
|
210
|
+
expect(auth_hash['provider']).to eq('identity')
|
109
211
|
end
|
110
212
|
end
|
111
213
|
|
112
214
|
context 'with invalid identity' do
|
113
|
-
let(:properties)
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
215
|
+
let(:properties) do
|
216
|
+
{
|
217
|
+
name: 'Awesome Dude',
|
218
|
+
email: 'awesome@example.com',
|
219
|
+
password: 'NOT',
|
220
|
+
password_confirmation: 'MATCHING',
|
221
|
+
provider: 'identity'
|
222
|
+
}
|
223
|
+
end
|
224
|
+
let(:invalid_identity) { double(persisted?: false, save: false) }
|
119
225
|
|
120
226
|
before do
|
121
|
-
expect(
|
227
|
+
expect(anon_ar).to receive(:new).with(properties).and_return(invalid_identity)
|
122
228
|
end
|
123
229
|
|
124
230
|
context 'default' do
|
125
|
-
it '
|
231
|
+
it 'shows registration form' do
|
126
232
|
post '/auth/identity/register', properties
|
127
|
-
expect(last_response.body).to be_include(
|
233
|
+
expect(last_response.body).to be_include('Register Identity')
|
234
|
+
expect(last_response.body).to be_include('One or more fields were invalid')
|
128
235
|
end
|
129
236
|
end
|
130
237
|
|
131
238
|
context 'custom on_failed_registration endpoint' do
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
239
|
+
let(:identity_options) do
|
240
|
+
{ model: anon_ar, on_failed_registration: lambda { |env|
|
241
|
+
[404, { 'env' => env }, ["FAIL'DOH!"]]
|
242
|
+
} }
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'sets the identity hash' do
|
246
|
+
post '/auth/identity/register', properties
|
247
|
+
expect(identity_hash).to eq(invalid_identity)
|
248
|
+
expect(last_response.body).to be_include("FAIL'DOH!")
|
249
|
+
expect(last_response.body).not_to be_include('One or more fields were invalid')
|
137
250
|
end
|
138
251
|
end
|
139
252
|
end
|