module Base class APIClient class ClientSecret AUTH_URI = Apis::API_HOST / Apis::API_VERSION / 'oauth/authorize' TOKEN_URI = Apis::API_HOST / Apis::API_VERSION / 'oauth/token' SCOPES = %w(read_items read_orders read_savings read_users read_users_mail write_items write_orders).join(' ').freeze attr_accessor \ :access_token, :client_id, :client_secret, :code, :expires_at, :grant_type, :redirect_uri, :refresh_token, :search_client_id, :search_client_secret def initialize(&block) app_info = load_file update!(&block) if block_given? @client_id ||= app_info['client_id'] @client_secret ||= app_info['client_secret'] @code ||= app_info['code'] @redirect_uri ||= app_info['redirect_uri'] @search_client_id ||= app_info['search']['client_id'] @search_client_secret ||= app_info['search']['client_secret'] end def update! yield(self) end def header_parameter { 'Authorization' => "Bearer #{@access_token}" } end def my_info uri = URI.join(Apis::API_HOST.to_s, "#{Apis::API_VERSION}/users/me") request = Net::HTTP::Get.new(uri, header_parameter) Net::HTTP.start( uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(request) } end def my_items # https://github.com/baseinc/api-docs/blob/master/base_api_v1_items.md # # { order: 'list_order or created', # sort: 'asc or desc', # limit: 1..100, # offset: 0 } request_parameters = block_given? ? yield : {} uri = URI( [Apis::API_HOST, "/#{Apis::API_VERSION}/items/?", URI.encode_www_form(request_parameters)].join) request = Net::HTTP::Get.new(uri, header_parameter) Net::HTTP.start( uri.hostname, uri.port, use_ssl: uri.scheme == 'https') { |http| http.request(request) } end def generate_code system(command, [AUTH_URI, generate_authorize_parameters].join) end def set_tokens! response = fetch_token @access_token = response['access_token'] @refresh_token = response['refresh_token'] @code = nil @expires_at = to_expires_at(response['expires_in']) to_hash end private def load_file file = Apis::CONFIG[:DEFAULT][:CLIENT_SECRET][:PATH] MultiJson.load(File.open(file, 'r').read) end def to_hash { client_id: client_id, client_secret: client_secret, code: code, expires_at: expires_at, redirect_uri: redirect_uri, access_token: access_token, refresh_token: refresh_token, search_client_id: search_client_id, search_client_secret: search_client_secret } end def to_json MultiJson.dump(to_hash) end def generate_authorize_parameters '?' + [ ['client_id', client_id], ['redirect_uri', redirect_uri], ['state', ''], %w(response_type code), ['scope', SCOPES]] .inject([]) do |memo, arr| memo << arr.join('=') end.join('&') end def command if OS.linux? 'sensible-browser' elsif OS.mac? 'open' end end def grant_type @grant_type = if code && redirect_uri 'authorization_code' elsif refresh_token 'refresh_token' end end def fetch_token request_parameters = to_hash.merge(grant_type: grant_type) uri = URI.parse(TOKEN_URI.to_s) response = Net::HTTP.post_form(uri, request_parameters) JSON.parse response.body end def to_expires_at(expires_in) Time.now + expires_in end end end end