g5_authentication_client 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +39 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +351 -0
- data/Rakefile +14 -0
- data/g5_authentication_client.gemspec +34 -0
- data/lib/g5_authentication_client/client.rb +177 -0
- data/lib/g5_authentication_client/configuration.rb +138 -0
- data/lib/g5_authentication_client/token_info.rb +27 -0
- data/lib/g5_authentication_client/user.rb +32 -0
- data/lib/g5_authentication_client/version.rb +3 -0
- data/lib/g5_authentication_client.rb +11 -0
- data/spec/g5_authentication_client/client_spec.rb +335 -0
- data/spec/g5_authentication_client/configuration_spec.rb +210 -0
- data/spec/g5_authentication_client/token_info_spec.rb +36 -0
- data/spec/g5_authentication_client/user_spec.rb +92 -0
- data/spec/g5_authentication_client_spec.rb +11 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/module_configured_attribute.rb +37 -0
- data/spec/support/oauth_protected_resource.rb +81 -0
- metadata +252 -0
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe G5AuthenticationClient::Configuration do
|
4
|
+
let(:test_module) do
|
5
|
+
module TestModule
|
6
|
+
extend G5AuthenticationClient::Configuration
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { test_module }
|
11
|
+
|
12
|
+
let(:logger) { double() }
|
13
|
+
let(:username) {'username'}
|
14
|
+
let(:password) {'password'}
|
15
|
+
let(:client_id) {'client id'}
|
16
|
+
let(:client_secret) {'client secret'}
|
17
|
+
let(:redirect_uri) {'/stuff'}
|
18
|
+
let(:endpoint){ 'http://endpoint.com' }
|
19
|
+
let(:authorization_code){ 'code' }
|
20
|
+
let(:access_token) { 'access_token_test' }
|
21
|
+
let(:allow_password_credentials) { 'false' }
|
22
|
+
|
23
|
+
after { test_module.reset }
|
24
|
+
|
25
|
+
it { should respond_to(:configure) }
|
26
|
+
|
27
|
+
context 'with default configuration' do
|
28
|
+
it { should_not be_debug }
|
29
|
+
its(:logger) { should be_an_instance_of(Logger) }
|
30
|
+
its(:username) {should be_nil}
|
31
|
+
its(:password) {should be_nil}
|
32
|
+
its(:client_id) {should == G5AuthenticationClient::DEFAULT_CLIENT_ID}
|
33
|
+
its(:client_secret) {should == G5AuthenticationClient::DEFAULT_CLIENT_SECRET}
|
34
|
+
its(:redirect_uri) {should == G5AuthenticationClient::DEFAULT_REDIRECT_URI}
|
35
|
+
its(:endpoint){should == G5AuthenticationClient::DEFAULT_ENDPOINT}
|
36
|
+
its(:authorization_code){ should be_nil }
|
37
|
+
its(:access_token) { should be_nil }
|
38
|
+
its(:allow_password_credentials) { should eq('true') }
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with environment variable configuration' do
|
42
|
+
before do
|
43
|
+
ENV['G5_AUTH_CLIENT_ID'] = client_id
|
44
|
+
ENV['G5_AUTH_CLIENT_SECRET'] = client_secret
|
45
|
+
ENV['G5_AUTH_REDIRECT_URI'] = redirect_uri
|
46
|
+
ENV['G5_AUTH_ENDPOINT'] = endpoint
|
47
|
+
ENV['G5_AUTH_USERNAME'] = 'foo'
|
48
|
+
ENV['G5_AUTH_ALLOW_PASSWORD_CREDENTIALS'] = 'false'
|
49
|
+
end
|
50
|
+
|
51
|
+
after do
|
52
|
+
ENV['G5_AUTH_CLIENT_ID'] = nil
|
53
|
+
ENV['G5_AUTH_CLIENT_SECRET'] = nil
|
54
|
+
ENV['G5_AUTH_REDIRECT_URI'] = nil
|
55
|
+
ENV['G5_AUTH_ENDPOINT'] = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it { should_not be_debug }
|
59
|
+
its(:logger) { should be_an_instance_of(Logger) }
|
60
|
+
its(:username) { should eq('foo')}
|
61
|
+
its(:password) { should be_nil }
|
62
|
+
its(:client_id) { should == client_id }
|
63
|
+
its(:client_secret) { should == client_secret }
|
64
|
+
its(:redirect_uri) { should == redirect_uri }
|
65
|
+
its(:endpoint) { should == endpoint }
|
66
|
+
its(:authorization_code) { should be_nil }
|
67
|
+
its(:access_token) { should be_nil }
|
68
|
+
its(:allow_password_credentials) { should == allow_password_credentials }
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '.configure' do
|
73
|
+
subject { test_module.configure(&config_block) }
|
74
|
+
|
75
|
+
context 'with full configuration' do
|
76
|
+
let(:config_block) do
|
77
|
+
lambda do |config|
|
78
|
+
config.debug = true
|
79
|
+
config.logger = logger
|
80
|
+
config.username = username
|
81
|
+
config.password = password
|
82
|
+
config.client_id = client_id
|
83
|
+
config.client_secret = client_secret
|
84
|
+
config.redirect_uri = redirect_uri
|
85
|
+
config.endpoint = endpoint
|
86
|
+
config.authorization_code = authorization_code
|
87
|
+
config.access_token = access_token
|
88
|
+
config.allow_password_credentials = allow_password_credentials
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it { should == test_module }
|
93
|
+
it { should be_debug }
|
94
|
+
its(:logger) { should == logger }
|
95
|
+
its(:username){ should == username }
|
96
|
+
its(:password){ should == password }
|
97
|
+
its(:client_id){ should == client_id }
|
98
|
+
its(:client_secret){ should == client_secret }
|
99
|
+
its(:redirect_uri){ should == redirect_uri}
|
100
|
+
its(:endpoint){ should == endpoint}
|
101
|
+
its(:authorization_code){ should == authorization_code}
|
102
|
+
its(:access_token) { should == access_token }
|
103
|
+
its(:allow_password_credentials) { should == allow_password_credentials }
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'with partial configuration' do
|
107
|
+
let(:config_block) do
|
108
|
+
lambda do |config|
|
109
|
+
config.debug = true
|
110
|
+
config.username = 'foo'
|
111
|
+
config.password = 'bar'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it { should == test_module }
|
116
|
+
|
117
|
+
it { should be_debug }
|
118
|
+
its(:logger) { should be_an_instance_of(Logger) }
|
119
|
+
its(:username) { should == 'foo' }
|
120
|
+
its(:password) { should == 'bar' }
|
121
|
+
its(:client_id){ should == G5AuthenticationClient::DEFAULT_CLIENT_ID }
|
122
|
+
its(:client_secret){ should == G5AuthenticationClient::DEFAULT_CLIENT_SECRET }
|
123
|
+
its(:redirect_uri){ should == G5AuthenticationClient::DEFAULT_REDIRECT_URI }
|
124
|
+
its(:endpoint){ should == G5AuthenticationClient::DEFAULT_ENDPOINT}
|
125
|
+
its(:authorization_code){ should be_nil}
|
126
|
+
its(:access_token) { should be_nil }
|
127
|
+
|
128
|
+
context 'when there is an env variable default' do
|
129
|
+
|
130
|
+
let(:access_token_value) { 'test' }
|
131
|
+
|
132
|
+
before do
|
133
|
+
ENV['G5_AUTH_ACCESS_TOKEN']=access_token_value
|
134
|
+
end
|
135
|
+
|
136
|
+
after do
|
137
|
+
ENV['G5_AUTH_ACCESS_TOKEN']=nil
|
138
|
+
end
|
139
|
+
|
140
|
+
its(:access_token) { should eq(access_token_value) }
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it { should respond_to(:reset) }
|
147
|
+
|
148
|
+
describe '.reset' do
|
149
|
+
before do
|
150
|
+
test_module.configure do |config|
|
151
|
+
config.debug = true
|
152
|
+
config.logger = logger
|
153
|
+
config.username = 'foo'
|
154
|
+
config.password = 'bar'
|
155
|
+
config.endpoint = 'blah'
|
156
|
+
config.client_id = 'blah'
|
157
|
+
config.client_secret = 'blah'
|
158
|
+
config.redirect_uri = 'blah'
|
159
|
+
config.authorization_code = 'blah'
|
160
|
+
config.access_token = 'blah'
|
161
|
+
config.allow_password_credentials = 'false'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
subject { test_module.reset;test_module }
|
166
|
+
|
167
|
+
its(:username) {should be_nil}
|
168
|
+
its(:password) {should be_nil}
|
169
|
+
its(:endpoint) {should == G5AuthenticationClient::DEFAULT_ENDPOINT}
|
170
|
+
its(:client_id) {should == G5AuthenticationClient::DEFAULT_CLIENT_ID}
|
171
|
+
its(:client_secret) {should == G5AuthenticationClient::DEFAULT_CLIENT_SECRET}
|
172
|
+
its(:redirect_uri) {should == G5AuthenticationClient::DEFAULT_REDIRECT_URI}
|
173
|
+
its(:debug?){ should be_false }
|
174
|
+
its(:logger){ should be_instance_of(Logger) }
|
175
|
+
its(:access_token) { should be_nil }
|
176
|
+
its(:allow_password_credentials) { should == 'true' }
|
177
|
+
end
|
178
|
+
|
179
|
+
describe '.options' do
|
180
|
+
before do
|
181
|
+
test_module.configure do |config|
|
182
|
+
config.debug = true
|
183
|
+
config.logger = logger
|
184
|
+
config.username = username
|
185
|
+
config.password = password
|
186
|
+
config.endpoint = endpoint
|
187
|
+
config.client_id = client_id
|
188
|
+
config.client_secret = client_secret
|
189
|
+
config.redirect_uri = redirect_uri
|
190
|
+
config.authorization_code = authorization_code
|
191
|
+
config.access_token = access_token
|
192
|
+
config.allow_password_credentials = allow_password_credentials
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
subject { test_module.options }
|
197
|
+
|
198
|
+
its([:debug]) { should be_true }
|
199
|
+
its([:logger]) { should == logger }
|
200
|
+
its([:username]) { should == username }
|
201
|
+
its([:password]) { should == password }
|
202
|
+
its([:endpoint]) { should == endpoint }
|
203
|
+
its([:client_id]) { should == client_id }
|
204
|
+
its([:client_secret]) { should == client_secret }
|
205
|
+
its([:redirect_uri]) { should == redirect_uri}
|
206
|
+
its([:authorization_code]){ should == authorization_code }
|
207
|
+
its([:access_token]) { should == access_token }
|
208
|
+
its([:allow_password_credentials]) { should == allow_password_credentials }
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe G5AuthenticationClient::TokenInfo do
|
4
|
+
subject { token_info }
|
5
|
+
let(:token_info) { described_class.new(attributes) }
|
6
|
+
|
7
|
+
let(:attributes) do
|
8
|
+
{
|
9
|
+
resource_owner_id: resource_owner_id,
|
10
|
+
scopes: scopes,
|
11
|
+
expires_in_seconds: expires_in_seconds,
|
12
|
+
application: { uid: application_uid }
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:resource_owner_id) { 42 }
|
17
|
+
let(:scopes) { ['leads','calls'] }
|
18
|
+
let(:expires_in_seconds) { '3600' }
|
19
|
+
let(:application_uid) { 'application-uid-42' }
|
20
|
+
|
21
|
+
context 'with default initialization' do
|
22
|
+
let(:attributes) {}
|
23
|
+
|
24
|
+
its(:resource_owner_id) { should be_nil }
|
25
|
+
its(:scopes) { should be_empty }
|
26
|
+
its(:expires_in_seconds) { should be_nil }
|
27
|
+
its(:application_uid) { should be_nil }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with full initialization' do
|
31
|
+
its(:resource_owner_id) { should == resource_owner_id.to_s }
|
32
|
+
its(:scopes) { should == scopes }
|
33
|
+
its(:expires_in_seconds) { should == expires_in_seconds.to_i }
|
34
|
+
its(:application_uid) { should == application_uid }
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe G5AuthenticationClient::User do
|
4
|
+
subject { user }
|
5
|
+
let(:user){G5AuthenticationClient::User.new(attributes)}
|
6
|
+
|
7
|
+
let(:attributes) do
|
8
|
+
{email: email,
|
9
|
+
password: password,
|
10
|
+
password_confirmation: password_confirmation,
|
11
|
+
id: id
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:email) { 'foo@blah.com' }
|
16
|
+
let(:password) { 'foobarbaz' }
|
17
|
+
let(:password_confirmation) { 'notamatch' }
|
18
|
+
let(:id) {1}
|
19
|
+
|
20
|
+
context 'with default initialization' do
|
21
|
+
let(:attributes){}
|
22
|
+
|
23
|
+
its(:email) { should be_nil}
|
24
|
+
its(:password) { should be_nil}
|
25
|
+
its(:id){ should be_nil}
|
26
|
+
its(:password_confirmation) { should be_nil }
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with full initialization' do
|
30
|
+
its(:email) { should == email }
|
31
|
+
its(:password){ should == password }
|
32
|
+
its(:password_confirmation) { should == password_confirmation }
|
33
|
+
its(:id) { should == id}
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#validate!' do
|
37
|
+
subject(:validate!) { user.validate! }
|
38
|
+
|
39
|
+
context 'without email' do
|
40
|
+
let(:email){}
|
41
|
+
|
42
|
+
it 'should raise an error' do
|
43
|
+
expect { validate! }.to raise_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'without password' do
|
48
|
+
let(:password){}
|
49
|
+
|
50
|
+
it 'should not raise an error' do
|
51
|
+
expect { validate! }.to_not raise_error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'without id' do
|
56
|
+
let(:id){}
|
57
|
+
|
58
|
+
it 'should not raise an error' do
|
59
|
+
expect { validate! }.to_not raise_error
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'without password_confirmation' do
|
64
|
+
let(:password_confirmation) {}
|
65
|
+
|
66
|
+
it 'should not raise an error' do
|
67
|
+
expect { validate! }.to_not raise_error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#validate_for_create!' do
|
73
|
+
subject(:validate_for_create) {user.validate_for_create!}
|
74
|
+
|
75
|
+
context 'without a password' do
|
76
|
+
let(:password){}
|
77
|
+
|
78
|
+
it 'should be invalid' do
|
79
|
+
expect { validate_for_create }.to raise_error
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'without an email' do
|
84
|
+
let(:email){}
|
85
|
+
let(:password){'foo'}
|
86
|
+
|
87
|
+
it 'should be invalid' do
|
88
|
+
expect { validate_for_create }.to raise_error
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start 'test_frameworks'
|
3
|
+
|
4
|
+
require 'codeclimate-test-reporter'
|
5
|
+
CodeClimate::TestReporter.start
|
6
|
+
|
7
|
+
require 'rspec'
|
8
|
+
|
9
|
+
require 'webmock/rspec'
|
10
|
+
require 'fakefs/spec_helpers'
|
11
|
+
|
12
|
+
Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each { |f| require f }
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.include FakeFS::SpecHelpers
|
16
|
+
|
17
|
+
# We need to explicitly disable webmock to report
|
18
|
+
# coverage data to Code Climate
|
19
|
+
config.after(:suite) { WebMock.disable! }
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'g5_authentication_client'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'a module configured attribute' do |attribute_name,default_value|
|
4
|
+
|
5
|
+
describe "##{attribute_name.to_s}=" do
|
6
|
+
subject do
|
7
|
+
client.send "#{attribute_name.to_s}=", new_value
|
8
|
+
client
|
9
|
+
end
|
10
|
+
|
11
|
+
context "with nil #{attribute_name.to_s}" do
|
12
|
+
let(:new_value){nil}
|
13
|
+
|
14
|
+
context "with module configured #{attribute_name}" do
|
15
|
+
let(:configured_value){'other thing'}
|
16
|
+
|
17
|
+
before do
|
18
|
+
G5AuthenticationClient.configure do |t|
|
19
|
+
t.send "#{attribute_name.to_s}=", configured_value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
its(attribute_name){ should == configured_value }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'without module configured #{attribute_name}' do
|
27
|
+
its(attribute_name){ should == default_value }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with new #{attribute_name.to_s}' do
|
32
|
+
let(:new_value){ 'userdude' }
|
33
|
+
|
34
|
+
its(attribute_name){ should == new_value }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Requires the following to be defined in the surrounding context
|
4
|
+
# access_token_value
|
5
|
+
# token_type
|
6
|
+
# client_id
|
7
|
+
# client_secret
|
8
|
+
# authorization_code
|
9
|
+
# redirect_uri
|
10
|
+
# username
|
11
|
+
# password
|
12
|
+
shared_examples_for 'an oauth protected resource' do |resource_type|
|
13
|
+
let(:oauth_access_token) do
|
14
|
+
{
|
15
|
+
'access_token' => access_token_value,
|
16
|
+
'token_type' => token_type,
|
17
|
+
'expires_in' => 7200,
|
18
|
+
'refresh_token' => 'refresh_token'
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when there is an access token' do
|
23
|
+
let(:authorization_code) { nil }
|
24
|
+
let(:username) { nil }
|
25
|
+
let(:password) { nil }
|
26
|
+
|
27
|
+
it { should be_an_instance_of resource_type }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when there is an authorization code' do
|
31
|
+
let(:access_token) { nil }
|
32
|
+
let(:username) { nil }
|
33
|
+
let(:password) { nil }
|
34
|
+
|
35
|
+
let(:token_request_by_auth_code) do
|
36
|
+
{
|
37
|
+
'client_id' => client_id,
|
38
|
+
'client_secret' => client_secret,
|
39
|
+
'code' => authorization_code,
|
40
|
+
'grant_type' => 'authorization_code',
|
41
|
+
'redirect_uri' => redirect_uri
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
before do
|
46
|
+
stub_request(:post, "#{endpoint}/oauth/token").
|
47
|
+
with(body: token_request_by_auth_code).
|
48
|
+
to_return(status: 200,
|
49
|
+
body: oauth_access_token.to_json,
|
50
|
+
headers: {'Content-Type' => 'application/json'})
|
51
|
+
end
|
52
|
+
|
53
|
+
it { should be_an_instance_of resource_type }
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when there is a username and password' do
|
57
|
+
let(:access_token) { nil }
|
58
|
+
let(:authorization_code) { nil }
|
59
|
+
let(:allow_password_credentials) {'true'}
|
60
|
+
|
61
|
+
let(:token_request_by_password) do
|
62
|
+
{
|
63
|
+
'client_id' => client_id,
|
64
|
+
'client_secret' => client_secret,
|
65
|
+
'grant_type' => 'password',
|
66
|
+
'username' => username,
|
67
|
+
'password' => password
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
before do
|
72
|
+
stub_request(:post, "#{endpoint}/oauth/token").
|
73
|
+
with(body: token_request_by_password).
|
74
|
+
to_return(status: 200,
|
75
|
+
body: oauth_access_token.to_json,
|
76
|
+
headers: {'Content-Type' => 'application/json'})
|
77
|
+
end
|
78
|
+
|
79
|
+
it { should be_an_instance_of resource_type }
|
80
|
+
end
|
81
|
+
end
|