class Genba::Client

Genba API Client

Constants

PRODUCTION_API_URL
SANDBOX_API_URL

Attributes

customer_account_id[RW]
max_retry[RW]
open_timeout[RW]
read_timeout[RW]
retry_delay[RW]

Public Class Methods

new(resource:, account_id:, cert:, key:, sandbox: false, options: {}) click to toggle source

Desribe the behaviour of the method

Attributes

  • config - Genba API credential attribute

Options

# File lib/genba/client.rb, line 22
def initialize(resource:, account_id:, cert:, key:, sandbox: false, options: {})
  @api_url = sandbox ? SANDBOX_API_URL : PRODUCTION_API_URL
  @resource = resource
  @account_id = account_id
  @cert = cert
  @key = key
  @tenant = 'aad.genbadigital.io'
  @authority_url = "https://login.microsoftonline.com/#{@tenant}"
  @client_id = "https://aad-snd.genbadigital.io/#{@account_id}"

  @open_timeout = options[:open_timeout] || 15
  @read_timeout = options[:read_timeout] || 60
  @max_retry = options[:max_retry] || 0
  @retry_delay = options[:retry_delay] || 2
end

Public Instance Methods

direct_entitlement() click to toggle source
# File lib/genba/client.rb, line 175
def direct_entitlement
  DirectEntitlement.new(self)
end
execute_request(method:, url:, payload: {}, headers: {}, options: {}) click to toggle source
# File lib/genba/client.rb, line 96
def execute_request(method:, url:, payload: {}, headers: {}, options: {})
  request_opts = {
    headers: headers,
    method: method,
    payload: payload,
    url: url
  }
  other_opts = {
    open_timeout: options[:open_timeout] || @open_timeout,
    read_timeout: options[:read_timeout] || @read_timeout,
    max_retry: options[:max_retry] || @max_retry
  }

  Genba::Util.log_debug "API Headers: #{headers.inspect}"
  Genba::Util.log_debug "Options: #{other_opts}"
  Genba::Util.log_info "#{method.upcase}: #{url}"
  Genba::Util.log_info "payload: #{payload}" if payload.present?

  request_opts.merge! other_opts
  execute_request_with_rescues(request_opts, other_opts[:max_retry])
end
execute_request_with_rescues(request_opts, max_retry) click to toggle source
# File lib/genba/client.rb, line 118
def execute_request_with_rescues(request_opts, max_retry)
  num_try = 0
  begin
    response = RestClient::Request.execute(request_opts)
  rescue RestClient::Exception, SocketError, Errno::ECONNREFUSED, NoMethodError => e
    if e.class.parent == RestClient && valid_json?(e.http_body)
      Genba::Util.log_error "#{e.class} => #{e.message}\n#{e.http_body}"
      raise e
      # response = OpenStruct.new(code: e.http_code, body: e.http_body, headers: {})
      # return response
    end
    Genba::Util.log_error "#{e.class} => #{e.message}"

    num_try += 1
    sleep @retry_delay

    if num_try <= max_retry
      Genba::Util.log_error "retry ====> #{num_try}"
      retry
    end

    raise e
  end
  response
end
generate_token() click to toggle source
# File lib/genba/client.rb, line 38
def generate_token
  unless token_valid?
    certificate = OpenSSL::X509::Certificate.new File.open(@cert)
    x5t = Base64.encode64 OpenSSL::Digest::SHA1.new(certificate.to_der).digest
    payload = {
      exp: (Time.now + 60*60*24).to_i,
      aud: "#{@authority_url}/oauth2/token",
      iss: @client_id,
      sub: @client_id,
    }
    rsa_private = OpenSSL::PKey::RSA.new File.open(@key)
    token = JWT.encode payload, rsa_private, 'RS256', { x5t: x5t }

    body = {
      resource: @resource,
      client_id: @client_id,
      grant_type: 'client_credentials',
      scope: 'https://graph.microsoft.com/.default',
      client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
      client_assertion: token,
      tenant: @tenant
    }

    response = RestClient.post(
      "#{@authority_url}/oauth2/token",
      body,
      headers: { accept: 'application/json', 'Content-Type': 'application/json' }
    )
    parsed_response = decode_json(response.body)
    @id_token = parsed_response['access_token']
    @expires_on = Time.at(parsed_response['expires_on'].to_i)
  end
  raw_token
end
orders() click to toggle source
# File lib/genba/client.rb, line 171
def orders
  Orders.new(self)
end
ping() click to toggle source
# File lib/genba/client.rb, line 151
def ping
  Ping.new(self)
end
prices() click to toggle source
# File lib/genba/client.rb, line 159
def prices
  Prices.new(self)
end
products() click to toggle source
# File lib/genba/client.rb, line 155
def products
  Products.new(self)
end
promotions() click to toggle source
# File lib/genba/client.rb, line 163
def promotions
  Promotions.new(self)
end
reservations() click to toggle source
# File lib/genba/client.rb, line 167
def reservations
  Reservations.new(self)
end
rest_get_with_token(path, query_params = {}, headers = {}, options = {}) click to toggle source
# File lib/genba/client.rb, line 73
def rest_get_with_token(path, query_params = {}, headers = {}, options = {})
  genba_headers = token.merge(headers)
  api_url = "#{@api_url}#{path}"
  api_url += "?#{query_params.to_query}" unless query_params.empty?
  response = execute_request(method: :get, url: api_url,
                             headers: genba_headers, options: options)
  from_rest_client_response(response)
end
rest_post_with_token(path, body = {}, headers = {}, options = {}) click to toggle source
# File lib/genba/client.rb, line 89
def rest_post_with_token(path, body = {}, headers = {}, options = {})
  genba_headers = token.merge(headers)
  response = execute_request(method: :post, url: "#{@api_url}#{path}",
                             payload: encode_json(body), headers: genba_headers, options: options)
  from_rest_client_response(response)
end
rest_put_with_token(path, body = {}, headers = {}, options = {}) click to toggle source
# File lib/genba/client.rb, line 82
def rest_put_with_token(path, body = {}, headers = {}, options = {})
  genba_headers = token.merge(headers)
  response = execute_request(method: :put, url: "#{@api_url}#{path}",
                             payload: encode_json(body), headers: genba_headers, options: options)
  from_rest_client_response(response)
end
valid_json?(json) click to toggle source
# File lib/genba/client.rb, line 144
def valid_json?(json)
  JSON.parse(json)
  return true
rescue JSON::ParserError => e
  return false
end

Private Instance Methods

decode_json(json) click to toggle source
# File lib/genba/client.rb, line 185
def decode_json(json)
  Oj.load(json)
end
encode_json(data) click to toggle source
# File lib/genba/client.rb, line 181
def encode_json(data)
  Oj.dump(data, mode: :compat)
end
from_rest_client_response(response) click to toggle source
# File lib/genba/client.rb, line 210
def from_rest_client_response(response)
  if response.code < 200
    Genba::Util.log_error "Invalid response object from API: #{response.body}" \
        "(HTTP response code was #{response.code})"
    raise "Invalid response object from API: #{response.body}" \
          "(HTTP response code was #{response.code})"
  end
  # default decode by json
  return decode_json(response.body) unless response.headers[:content_type]
  if (response.headers[:content_type] =~ %r{application\/json}) >= 0
    Genba::Util.log_info "response body\n#{response.body}"
    decode_json(response.body)
  end
end
raw_token() click to toggle source
# File lib/genba/client.rb, line 189
def raw_token
  if token_valid?
    {
      Authorization: "Bearer #{@id_token}",
      accept: 'application/json',
      'Content-Type': 'application/json'
    }
  else
    {}
  end
end
token() click to toggle source
# File lib/genba/client.rb, line 201
def token
  generate_token unless token_valid?
  raw_token
end
token_valid?() click to toggle source
# File lib/genba/client.rb, line 206
def token_valid?
  @id_token && @expires_on > Time.now
end