diff --git a/README.md b/README.md
index 53dfd07..0261d4a 100644
--- a/README.md
+++ b/README.md
@@ -73,14 +73,20 @@ to run the tests
require 'ruby-bandwidth-iris'
# Using directly
-client = BandwidthIris::Client.new('accountId', 'userName', 'password')
+client = BandwidthIris::Client.new('accountId', 'userName', 'password') # Basic Auth
+client = BandwidthIris::Client.new({access_token: 'accessToken'}) # Bearer Token Auth
+client = BandwidthIris::Client.new({client_id: 'clientId', client_secret: 'clientSecret'}) # OAuth 2 using Client Credentials
sites = BandwidthIris::Site.list(client)
# Or you can use default client instance (do this only once)
BandwidthIris::Client.global_options = {
:account_id => 'accountId',
:username => 'userName',
- :password => 'password'
+ :password => 'password',
+ :access_token => 'accessToken',
+ :access_token_expiration => Time.now + 3600
+ :client_id => 'client_id',
+ :client_secret => 'client_secret'
}
# Now you can call any functions without first arg 'client'
diff --git a/lib/bandwidth-iris/client.rb b/lib/bandwidth-iris/client.rb
index 84185de..62e2e54 100644
--- a/lib/bandwidth-iris/client.rb
+++ b/lib/bandwidth-iris/client.rb
@@ -19,8 +19,12 @@ def initialize (account_id = nil, user_name = nil, password = nil, options = nil
end
options = options || @@global_options
account_id = options[:account_id] unless account_id
- user_name = options[:user_name] || options[:username] unless user_name
+ user_name = options[:user_name] || options[:username] unless user_name
password = options[:password] unless password
+ @access_token = options[:access_token]
+ @access_token_expiration = options[:access_token_expiration] || Time.now + 3600
+ @client_id = options[:client_id]
+ @client_secret = options[:client_secret]
options[:api_endpoint] = @@global_options[:api_endpoint] unless options[:api_endpoint]
options[:api_version] = @@global_options[:api_version] unless options[:api_version]
api_endpoint = options[:api_endpoint] || "https://dashboard.bandwidth.com"
@@ -31,8 +35,15 @@ def initialize (account_id = nil, user_name = nil, password = nil, options = nil
@create_connection = lambda{||
Faraday.new(api_endpoint) { |faraday|
# To make this gem compatible with Faraday v1 and v2, the basic_auth middleware can't be used because it was removed in v2
- faraday.request :authorization, 'Basic', Base64.strict_encode64("#{user_name}:#{password}")
- #faraday.response :logger
+ if @access_token && @access_token_expiration > Time.now + 60
+ faraday.request :authorization, 'Bearer', @access_token
+ elsif @client_id && @client_secret
+ refresh_auth_token
+ faraday.request :authorization, 'Bearer', @access_token
+ else
+ faraday.request :authorization, 'Basic', Base64.strict_encode64("#{user_name}:#{password}")
+ end
+ # faraday.response :logger
faraday.headers['Accept'] = 'application/xml'
faraday.headers['user-agent'] = 'Ruby-Bandwidth-Iris'
faraday.response :follow_redirects # use Faraday::FollowRedirects::Middleware
@@ -67,9 +78,24 @@ def Client.get_id_from_location_header(location)
items.last
end
+ def refresh_auth_token
+ token_url = 'https://api.bandwidth.com/api/v1/oauth2/token'
+ response = Faraday.new do |faraday|
+ faraday.request :url_encoded
+ faraday.request :authorization, :basic, @client_id, @client_secret
+ @set_adapter.call(faraday)
+ end.post(token_url, {grant_type: 'client_credentials'})
+ if response.status >= 400
+ raise Errors::GenericError.new(response.status, response.reason_phrase, response.headers, response.body)
+ end
+ body = JSON.parse(response.body)
+ @access_token = body['access_token']
+ @access_token_expiration = Time.now + body['expires_in']
+ end
+
# Make HTTP request to IRIS API
# @param method [Symbol] http method to make
- # @param path [string] path of url (exclude api verion and endpoint) to make call
+ # @param path [string] path of url (exclude api version and endpoint) to make call
# @param data [Hash] data which will be sent with request (for :get and :delete request they will be sent with query in url)
# @return [Array] array with 2 elements: parsed data of response and response headers
def make_request(method, path, data = {})
@@ -89,7 +115,7 @@ def make_request(method, path, data = {})
# Makes an HTTP request for file uploads
# @param method [Symbol] http method to make
- # @param path [string] path of url (exclude api verion and endpoint) to make call
+ # @param path [string] path of url (exclude api version and endpoint) to make call
# @param data [string] the raw binary string representing the file to upload
# @param content_type [string] the content type of the request
# @return [Array] array with 2 elements: parsed data of response and response headers
@@ -102,7 +128,7 @@ def make_request_file_upload(method, path, data, content_type)
# Makes an HTTP request for a file download
# @param method [Symbol] http method to make
- # @param path [string] path of url (exclude api verion and endpoint) to make call
+ # @param path [string] path of url (exclude api version and endpoint) to make call
# @param data [Hash] data which will be sent with request (for :get and :delete request they will be sent with query in url)
# @return [string] raw response from the API
def make_request_file_download(method, path, data = {})
diff --git a/lib/bandwidth-iris/site.rb b/lib/bandwidth-iris/site.rb
index d6cb2c0..770ba59 100644
--- a/lib/bandwidth-iris/site.rb
+++ b/lib/bandwidth-iris/site.rb
@@ -39,7 +39,7 @@ def delete()
def get_sip_peer(peer_id)
item = @client.make_request(:get, "#{@client.concat_account_path(SITE_PATH)}/#{id}/sippeers/#{peer_id}")[0][:sip_peer]
item[:site_id] = id
- puts item
+ # puts item
item
end
diff --git a/lib/bandwidth-iris/version.rb b/lib/bandwidth-iris/version.rb
index 38f8315..ae7d4d7 100644
--- a/lib/bandwidth-iris/version.rb
+++ b/lib/bandwidth-iris/version.rb
@@ -1,4 +1,4 @@
module BandwidthIris
# Version of this gem
- VERSION = "7.3.2"
+ VERSION = "7.4.0"
end
diff --git a/spec/bandwidth-iris/client_spec.rb b/spec/bandwidth-iris/client_spec.rb
index a75e41b..03622d1 100644
--- a/spec/bandwidth-iris/client_spec.rb
+++ b/spec/bandwidth-iris/client_spec.rb
@@ -20,8 +20,8 @@
expect(Client.get_id_from_location_header('http://localhost/path1/path2/id')).to eql('id')
end
it 'should raise error if location is missing or nil' do
- expect{Client.get_id_from_location_header('')}.to raise_error
- expect{Client.get_id_from_location_header(nil)}.to raise_error
+ expect{Client.get_id_from_location_header('')}.to raise_error(StandardError)
+ expect{Client.get_id_from_location_header(nil)}.to raise_error(StandardError)
end
end
@@ -51,12 +51,22 @@
describe '#make_request' do
client = nil
+ token_client = nil
+ expired_token_client = nil
+ client_credentials_client = nil
+
before :each do
client = Helper.get_client()
+ token_client = Helper.get_token_client()
+ expired_token_client = Helper.get_expired_token_client()
+ client_credentials_client = Helper.get_client_credentials_client()
end
after :each do
client.stubs.verify_stubbed_calls()
+ token_client.stubs.verify_stubbed_calls()
+ expired_token_client.stubs.verify_stubbed_calls()
+ client_credentials_client.stubs.verify_stubbed_calls()
end
it 'should pass basic auth headers' do
@@ -65,6 +75,29 @@
expect(client.make_request(:get, '/test-auth')).to eql([{:echoed_auth=>"Basic #{Base64.strict_encode64('username:password')}"}, {}])
end
+ it 'should pass bearer auth header using token' do
+ token_client.stubs.get('/v1.0/test-auth-token') { |env| [200, {}, "#{env[:request_headers]['Authorization']}"] }
+ expect(token_client.make_request(:get, '/test-auth-token')).to eql([{:echoed_auth=>"Bearer accessToken"}, {}])
+ expect(token_client.instance_variable_get(:@access_token)).to eql('accessToken')
+ expect(token_client.instance_variable_get(:@access_token_expiration)).to be_a(Time)
+ end
+
+ it 'should refresh expired token and pass bearer auth header' do
+ expired_token_client.stubs.post('https://api.bandwidth.com/api/v1/oauth2/token') { |env| [200, {}, '{"access_token":"newAccessToken","expires_in":3600}'] }
+ expired_token_client.stubs.get('/v1.0/test-auth-expired-token') { |env| [200, {}, "#{env[:request_headers]['Authorization']}"] }
+ expect(expired_token_client.make_request(:get, '/test-auth-expired-token')).to eql([{:echoed_auth=>"Bearer newAccessToken"}, {}])
+ expect(expired_token_client.instance_variable_get(:@access_token)).to eql('newAccessToken')
+ expect(expired_token_client.instance_variable_get(:@access_token_expiration)).to be_a(Time)
+ end
+
+ it 'should use client credentials to get token and pass bearer auth header' do
+ client_credentials_client.stubs.post('https://api.bandwidth.com/api/v1/oauth2/token') { |env| [200, {}, '{"access_token":"clientCredentialsAccessToken","expires_in":3600}'] }
+ client_credentials_client.stubs.get('/v1.0/test-auth-client-credentials') { |env| [200, {}, "#{env[:request_headers]['Authorization']}"] }
+ expect(client_credentials_client.make_request(:get, '/test-auth-client-credentials')).to eql([{:echoed_auth=>"Bearer clientCredentialsAccessToken"}, {}])
+ expect(client_credentials_client.instance_variable_get(:@access_token)).to eql('clientCredentialsAccessToken')
+ expect(client_credentials_client.instance_variable_get(:@access_token_expiration)).to be_a(Time)
+ end
+
it 'should make GET request and return xml data' do
client.stubs.get('/v1.0/path1') { |env| [200, {}, 'data'] }
client.stubs.get('/v1.0/path2?testField=10') { |env| [200, {'Location'=>'url'}, '1012truefalse2015-05-29T01:02:03Z'] }
diff --git a/spec/helper.rb b/spec/helper.rb
index eccfee3..cb47f4c 100644
--- a/spec/helper.rb
+++ b/spec/helper.rb
@@ -30,6 +30,23 @@ def self.get_client()
Client.new('accountId', 'username', 'password')
end
+ def self.get_token_client()
+ Client.new({access_token: 'accessToken'})
+ end
+
+ def self.get_expired_token_client()
+ Client.new({
+ access_token: 'expiredAccessToken',
+ access_token_expiration: Time.now - 3600,
+ client_id: 'clientId',
+ client_secret: 'clientSecret'
+ })
+ end
+
+ def self.get_client_credentials_client()
+ Client.new({client_id: 'clientId', client_secret: 'clientSecret'})
+ end
+
def self.setup_environment()
Client.global_options[:account_id] = 'accountId'
Client.global_options[:username] = 'username'