Class: VivialConnect::Client

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/vivialconnect/client.rb

Overview

.configure(api_key, api_secret, account_id, host=“api.vivialconnect.net/api/”, api_version=“v1.0” )

Configures the client with your ‘api_key`, `api_secret`, `account_id`, `host`, and `api_version`

Required parameters:

api_key | String | “YOURAPIKEY” api_secret | String | “YOURAPISECRET” account_id | Fixnum | 100000

Optional parameters:

host | String | “baseapiurl” api_version | String | “v1.9”

NOTE: default host is “api.vivialconnect.net/api/” and default version is “v1.0”

Example usage:

VivialConnect::Client.configure(API_KEY, API_SECRET, ACCOUNT_ID)

> true

NOTE: .configure does not check if your credentials are good, it merely checks that you have entered values for them

#reset

Resets all of the configuration values to nil. This gives you a blank slate client to call .configure on.

Example usage

VivialConnect::Client.instance.reset

> true

#reset_api_base_path(new_host, new_api_version)

Resets the api base path (host + api_version) on an instantiated client instance

Required paramters:

new_host | String | “api.vivialconnect.net/api/” new_api_version | String | “v1.1”

Example usage

VivialConnect::Client.instance.reset_api_base_path(“api.vivialconnect.net/api/”, “v1.1” )

> true

Constant Summary collapse

@@configured =
false

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.configure(api_key, api_secret, account_id, host = "https://api.vivialconnect.net/api/", api_version = "v1.0") ⇒ Object



72
73
74
75
76
77
78
79
80
# File 'lib/vivialconnect/client.rb', line 72

def self.configure(api_key, api_secret, , host="https://api.vivialconnect.net/api/", api_version="v1.0" )
  @@api_key= api_key
  @@api_secret = api_secret
  @@account_id = 
  @@host = host
  @@api_version = api_version
  @@configured = true
  true
end

.configured?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'lib/vivialconnect/client.rb', line 131

def self.configured?
  @@configured == true
end

Instance Method Details

#account_idObject



103
104
105
# File 'lib/vivialconnect/client.rb', line 103

def 
  @@account_id
end

#account_id=(id) ⇒ Object



107
108
109
# File 'lib/vivialconnect/client.rb', line 107

def (id)
   @@account_id = id
end

#account_query_match?(url) ⇒ Boolean

Returns:

  • (Boolean)


228
229
230
# File 'lib/vivialconnect/client.rb', line 228

def (url)
  url.include?("accounts.json?")
end

#account_regex_match?(url) ⇒ Boolean

Returns:

  • (Boolean)


223
224
225
226
# File 'lib/vivialconnect/client.rb', line 223

def (url)
  m =  /accounts\/[0-9]+.json/.match(url)
  return !m.nil? 
end

#api_keyObject



151
152
153
# File 'lib/vivialconnect/client.rb', line 151

def api_key
  @@api_key
end

#api_secretObject



155
156
157
# File 'lib/vivialconnect/client.rb', line 155

def api_secret
  @@api_secret
end

#api_versionObject



119
120
121
# File 'lib/vivialconnect/client.rb', line 119

def api_version
  @@api_version
end

#base_api_pathObject



127
128
129
# File 'lib/vivialconnect/client.rb', line 127

def base_api_path
  @base_api_path = host + "#{api_version}/"
end

#build_canonical_request(http_verb, url, request_timestamp, canonicalized_headers, canonicalized_header_names, data = {}) ⇒ Object



167
168
169
170
171
# File 'lib/vivialconnect/client.rb', line 167

def build_canonical_request(http_verb, url, request_timestamp, canonicalized_headers, canonicalized_header_names, data={})
  canonical_request = http_verb + "\n" + request_timestamp + "\n" + Addressable::URI.encode(url.path) + 
                      "\n" + get_canonicalized_query_string(url) + "\n" + canonicalized_headers + "\n" +
                       canonicalized_header_names +  "\n" + Digest::SHA256.hexdigest(data.to_s)
end

#choose_response_class(url) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/vivialconnect/client.rb', line 286

def choose_response_class(url)
  url = url.gsub('.json', '').split('/')
  if (url.count <= 5 )|| (url.count == 6 && url[5] == 'count')  
    return  
  elsif url.include?('attachments')
    return Attachment
  else
    api_resource = url[5]
    #exceptions needed for resources requiring camelcase
    klass = api_resource.capitalize
    #takes off pluralization -- may have to be updated to match self.pluralize(string) in Resource, or use library if necessary
    klass = klass[0..-2]
    return VivialConnect.const_get(klass) 
  end 
end

#connectionObject



191
192
193
# File 'lib/vivialconnect/client.rb', line 191

def connection
  @conn = Faraday.new(:url => base_api_path) 
end

#create_request_headersObject



207
208
209
210
211
212
213
214
215
216
217
# File 'lib/vivialconnect/client.rb', line 207

def create_request_headers
  headers = {}
  headers['Content-Type'] = 'application/json'
  headers['Host'] = 'api.vivialconnect.net'
  headers['X-Auth-Date'] = request_timestamp
  headers['X-Auth-SignedHeaders'] = 'accept;date;host'
  headers['Authorization'] = "HMAC" + " " + api_key + ":" + hmac_sha256
  headers['Date'] = date_for_date_header
  headers['Accept'] = 'application/json'
  headers
end

#date_for_date_headerObject



147
148
149
# File 'lib/vivialconnect/client.rb', line 147

def date_for_date_header
  @date_for_date_header 
end

#get_canonicalized_query_string(url) ⇒ Object



182
183
184
185
186
187
188
189
# File 'lib/vivialconnect/client.rb', line 182

def get_canonicalized_query_string(url)
  return "" unless url.query_values
  sorted_params = url.query_values.sort
  # gsub because Addressable encodes an empty space as + in parameters
  # and vivial connect api requires spaces to be %20 encoded
  # http://stackoverflow.com/questions/2824126/whats-the-difference-between-uri-escape-and-cgi-escape
  encoded_sorted_params = Addressable::URI.form_encode(sorted_params).gsub('+', '%20') 
end

#get_request_path(url) ⇒ Object



232
233
234
235
236
237
238
239
240
# File 'lib/vivialconnect/client.rb', line 232

def get_request_path(url)
  if .include?(url) || (url) || (url)
    base_path = base_api_path
    Addressable::URI.parse(base_path + url)
  else
    base_path = base_api_path + "accounts/#{account_id}"
    Addressable::URI.parse(base_path + url)
  end
end

#hmac_sha256Object



163
164
165
# File 'lib/vivialconnect/client.rb', line 163

def hmac_sha256
  @hmac_sha256 
end

#hostObject



95
96
97
# File 'lib/vivialconnect/client.rb', line 95

def host
  @@host
end

#make_request(request_method, url, data = {}) ⇒ Object



195
196
197
198
199
200
201
202
203
204
205
# File 'lib/vivialconnect/client.rb', line 195

def make_request(request_method, url, data={})
  raise VivialConnectClientError, "invalid request method" unless ['GET', 'POST', 'PUT', 'DELETE'].include?(request_method)
  raise VivialConnectClientError, "Please configure client before making requests. You can do this like so: .configure(api_key, api_secret, account_id) to " if !VivialConnect::Client.configured?

  url = get_request_path(url)
  sign_request(request_method, url, data)
  headers = create_request_headers
  request_method = request_method.downcase.to_sym
  response = connection.run_request(request_method, url, data.to_s, headers)
  process_api_response(response, url, request_method)
end

#no_account_number_endpointsObject



219
220
221
# File 'lib/vivialconnect/client.rb', line 219

def 
  ['accounts.json', '/accounts/count.json', 'registration/register.json'] 
end

#process_api_response(response, url, request_method) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/vivialconnect/client.rb', line 242

def process_api_response(response, url, request_method)
  # make API response into appropriate object and return it
  api_response = {}
    raise VivialConnectClientError, JSON.parse(response.body)['message'] ? JSON.parse(response.body)['message'] : response.body if response.status >= 400
    response_class = choose_response_class(url.path)
    if request_method == :delete || response.body == "" || response.body.include?("{}")
      return true if response.status.between?(200, 299)
      false
      api_response = JSON.parse(response.body)
    else
      api_response = JSON.parse(response.body)
      if api_response[api_response.keys.first].is_a?(Array)
        #return an array of resource objects for typical .all requests
        response_array = api_response[api_response.keys.first]
        api_response = process_array(response_array, response_class)
      elsif api_response[api_response.keys[1]].is_a?(Array)
        #handle Log resource, return last key and an array full of log objects
        last_key = api_response['last_key']
        response_array = api_response['log_items']
        processed_array = process_array(response_array, response_class)
        [last_key, processed_array]
      elsif api_response[api_response.keys.first].is_a?(Fixnum)
        # json is only one level deep for .count response, so no need to delete the json root
        # return the number
        api_response['count']
      else
        if response_class == VivialConnect::Log 
          # json is only one level deep for Log response, so no need to delete the json root
          response_class.new(api_response)
        else
          # remove json root, these resources return nested info
          api_response = api_response[api_response.keys.first]
          response_class.new(api_response)
        end
      end
  end
end

#process_array(array, response_class) ⇒ Object



280
281
282
283
284
# File 'lib/vivialconnect/client.rb', line 280

def process_array(array, response_class)
  final_array = []
  array.each {|index| final_array << response_class.new(index)}
  final_array
end

#request_timestampObject



139
140
141
# File 'lib/vivialconnect/client.rb', line 139

def request_timestamp
  @request_timestamp
end

#resetObject



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/vivialconnect/client.rb', line 82

def reset
  @@api_key= nil
  @@api_secret = nil
  @@account_id = nil
  @@host = nil
  @@api_version = nil
  @@configured = false
  self.instance_variables.each do |ivar|
    self.remove_instance_variable(ivar)
  end
  true
end

#reset_api_base_path(new_host, new_api_version) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/vivialconnect/client.rb', line 111

def reset_api_base_path(new_host, new_api_version)
  set_host(new_host)
  set_api_version(new_api_version)
  @base_api_path = host + api_version
  connection
  true
end

#set_api_version(api_version) ⇒ Object



123
124
125
# File 'lib/vivialconnect/client.rb', line 123

def set_api_version(api_version)
  @@api_version = api_version
end

#set_date_for_date_headerObject



143
144
145
# File 'lib/vivialconnect/client.rb', line 143

def set_date_for_date_header
  @date_for_date_header = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
end

#set_hmac_sha256(canonical_request) ⇒ Object



159
160
161
# File 'lib/vivialconnect/client.rb', line 159

def set_hmac_sha256(canonical_request)
  @hmac_sha256 = OpenSSL::HMAC.hexdigest('SHA256', api_secret, canonical_request)
end

#set_host(host) ⇒ Object



99
100
101
# File 'lib/vivialconnect/client.rb', line 99

def set_host(host)
  @@host = host
end

#set_request_timestampObject



135
136
137
# File 'lib/vivialconnect/client.rb', line 135

def set_request_timestamp 
  @request_timestamp = Time.now.utc.strftime('%Y%m%dT%H%M%SZ')
end

#sign_request(http_verb, url, data = {}) ⇒ Object



173
174
175
176
177
178
179
180
# File 'lib/vivialconnect/client.rb', line 173

def sign_request(http_verb, url, data={})
  set_request_timestamp 
  set_date_for_date_header
  canonicalized_headers = "accept:application/json" + "\n" + "date:#{date_for_date_header}" + "\n" +"host:api.vivialconnect.net"
  canonicalized_header_names = "accept;date;host"
  canonical_request = build_canonical_request(http_verb, url, request_timestamp, canonicalized_headers, canonicalized_header_names, data)
  set_hmac_sha256(canonical_request)
end