vivialconnect 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 828c9a5c3422698044222a0d637bf1993c27014e
4
+ data.tar.gz: ac62e677b700bb6a7a653ea44d0fcf76933001c8
5
+ SHA512:
6
+ metadata.gz: f2a45113770f5c43391cef5484983713f24ecd6f69717c1f2b88c2844ad72bc49fc85ca030c9c651446c6ad36669808eecef8c200dc3c952314bcc31fccdb816
7
+ data.tar.gz: 3363eb281a9da8c0bfe760843b80ace6d0705138fa136ef64502dd27a7e53a1bc2489f539cb494f72af7180b5aae7fb2343f7237aaf0b92110934b9967003bba
@@ -0,0 +1,14 @@
1
+ require 'json'
2
+ require 'vivialconnect/version'
3
+ require 'vivialconnect/client'
4
+ require 'vivialconnect/resource'
5
+ require 'vivialconnect/message'
6
+ require 'vivialconnect/account'
7
+ require 'vivialconnect/user'
8
+ require 'vivialconnect/attachment'
9
+ require 'vivialconnect/configuration'
10
+ require 'vivialconnect/number'
11
+ require 'vivialconnect/log'
12
+ require 'vivialconnect/contact'
13
+ require 'vivialconnect/vivial_connect_error'
14
+
@@ -0,0 +1,278 @@
1
+ module VivialConnect
2
+ ##
3
+ #=== .add_main_contact_to_subaccount(options={})
4
+ #
5
+ #Creates a new contact and adds it as the main contact to a subaccount.
6
+ #
7
+ # Required parameters:
8
+ #
9
+ # account_id | Fixnum | 123456 (subaccount id)
10
+ # company_name | String | "App Developer Inc."
11
+ # first_name | String | "Bob"
12
+ # last_name | String | "Tester"
13
+ # email | String | "btester@vivialconnect"
14
+ #
15
+ #
16
+ # Optional parameters:
17
+ #
18
+ # address1 | String | "500 Office Building Ln"
19
+ # address2 | String | "Suite 300"
20
+ # address3 | String | "c/o Front Desk"
21
+ # city | String | "Columbia Heights"
22
+ # country | String | "United States"
23
+ # state | String | "Minnesota"
24
+ # postal_code | String | "55421"
25
+ # title | String | "CMO"
26
+ # work_phone | String | "+1XXXXXXXXXX"
27
+ # mobile_phone | String | "+1XXXXXXXXXX"
28
+ # fax | String | "+1XXXXXXXXXX"
29
+ #
30
+ # Example Usage
31
+ #
32
+ #
33
+ # VivialConnect::Account.add_main_contact_to_subaccount(email: "btester@vivialconnect", contact_type:"main", company_name: "Acme")
34
+ # => #<VivialConnect::Contact account_id=1XXXX, active=true, address1=nil, address2=nil, address3=nil, city=nil, company_name="Acme", contact_type="main", country="United States", date_created="2017-04-21T10:51:50-04:00", date_modified="2017-04-21T10:51:50-04:00", email="btester@vivialconnect", fax=nil, first_name="Bob", id=89, last_name="Tester", mobile_phone=nil, postal_code="55421", state=nil, title=nil, work_phone="+1XXXXXXXXXX">
35
+ #
36
+ #
37
+ ##
38
+ #=== .add_user_to_subaccount(options={})
39
+ #
40
+ #Creates a new User and adds it to a subaccount.
41
+ #
42
+ #
43
+ # Required parameters:
44
+ #
45
+ #
46
+ # first_name | String | "Bob"
47
+ # last_name | String | "Tester"
48
+ # email | String | "btester@vivialconnect"
49
+ # username | String | "btester"
50
+ # password | String | "dlrowolleh"
51
+ #
52
+ #
53
+ # Example Usage
54
+ #
55
+ #
56
+ # VivialConnect::Account.add_user_to_subaccount(account_id: 1XXXX, email: "btester@vivialconnect.net", username: "btester", first_name: "Bob", last_name: "Tester", password: "XXXXXXX")
57
+ # => #<VivialConnect::User account_id=1XXXX, active=true, api_key="XYZYXZYXYZXYXZYXZYXYZYXYZYXYZYXYZYX", date_created="2017-04-21T11:27:16-04:00", date_modified="2017-04-21T11:27:16-04:00", email="btester@vivialconnect.net", first_name="Bob", id=10093, last_name="Tester", roles=[{"active"=>true, "date_created"=>"2016-09-30T19:42:59-04:00", "date_modified"=>"2016-09-30T19:42:59-04:00", "description"=>"User role", "id"=>4, "name"=>"User", "role_type"=>"client"}], timezone="US/Eastern", username="btester", verified=false>
58
+ #
59
+ # Note: This method triggers an email to the created user's account. They need to answer this confirmation email before they will be able to log in.
60
+ ##
61
+ #=== .all
62
+ #
63
+ #Returns an array containing ruby objects corresponding to all Account resources associated with your account i.e. main account and associated subaccounts
64
+ #
65
+ #
66
+ # Example usage:
67
+ #
68
+ #
69
+ # VivialConnect::Account.all
70
+ # => [#<VivialConnect::Account>, #<VivialConnect::Account>, #<VivialConnect::Account>]
71
+ #
72
+ #
73
+ #=== .count
74
+ #
75
+ #Returns the amount of Accounts associated with your account
76
+ #
77
+ # Example usage:
78
+ #
79
+ #
80
+ # VivialConnect::Account.count
81
+ # => 5
82
+ #
83
+ #
84
+ ##
85
+ #=== .create(options={})
86
+ #
87
+ #Creates a subaccount tied to your main account
88
+ #
89
+ #
90
+ # Required parameters:
91
+ #
92
+ #
93
+ # company_name | String | "App Developer Inc."
94
+ #
95
+ #
96
+ # Example Usage
97
+ #
98
+ #
99
+ # VivialConnect::Account.create(company_name: "App Developer Inc.")
100
+ # => #<VivialConnect::Account account_id=1XXXX, accounts=[], active=true, company_name="App Developer Inc.", contacts=[], date_created="2017-04-20T17:07:08-04:00", date_modified="2017-04-20T17:07:08-04:00", id=10086, services=[{"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"SMS service", "id"=>1, "name"=>"sms", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Account service", "id"=>2, "name"=>"accounts", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Public service", "id"=>3, "name"=>"public", "service_type"=>"client"}]>
101
+ #
102
+ #
103
+ # Note: When creating subaccounts, the `id` refers to the subaccount id, whereas the `account_id` refers to the main account.
104
+ #
105
+ #
106
+ ##
107
+ #=== .find(id)
108
+ #
109
+ #Returns the a Account object referenced by the `id` value.
110
+ #
111
+ # Required parameter:
112
+ #
113
+ # id | Fixnum | the id of the account you would like to retrieve
114
+ #
115
+ #
116
+ # Example usage:
117
+ #
118
+ #
119
+ # VivialConnect::Account.find(10086)
120
+ # => #<VivialConnect::Account account_id=1XXXX, accounts=[], active=true, company_name="App Developer Inc.", contacts=[], date_created="2017-04-20T17:07:08-04:00", date_modified="2017-04-20T17:07:08-04:00", id=10086, services=[{"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"SMS service", "id"=>1, "name"=>"sms", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Account service", "id"=>2, "name"=>"accounts", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Public service", "id"=>3, "name"=>"public", "service_type"=>"client"}]>
121
+ #
122
+ #
123
+ ##
124
+ #=== .find_each(start: 1, finish: nil, batch_size: 150)
125
+ #
126
+ #Iterates through all Account objects on your account in N sized batches beginning at the `start: value` and ending at the `finish: value`.
127
+ #
128
+ #
129
+ # When a block is given this method yields an individual Account object.
130
+ # Without a block, this method returns an Enumerator.
131
+ #
132
+ #
133
+ # By default, it will begin at the first Account and end at the last Account
134
+ #
135
+ #
136
+ # With default batch_size: 150, if you wanted to get your records from
137
+ # 150 to 300 you would start at 2 and finish at 2.
138
+ #
139
+ # Returns an Array of objects corresponding to the `start` and `finish` values. Default is all objects.
140
+ #
141
+ # Optional parameters:
142
+ #
143
+ # start | Fixnum | batch to start with
144
+ # finish | Fixnum | batch to end with
145
+ # batch_size | Fixnum | between 1..150
146
+ #
147
+ #
148
+ # Example usage:
149
+ #
150
+ #
151
+ # VivialConnect::Account.find_each {|account| puts account.company_name }
152
+ # App Developer Inc.
153
+ # => [#<VivialConnect::Account>]
154
+ #
155
+ #
156
+ #
157
+ #
158
+ ##
159
+ #=== .find_in_batches(start: 1, finish: nil, batch_size: 150)
160
+ #
161
+ #Iterates through all of the Account objects on your account in N sized batches beginning at the `start: value` and ending at the `finish: value`.
162
+ #
163
+ #
164
+ # When a block is given this method yields an array of batch_size Account objects.
165
+ # Without a block, it returns an Enumerator.
166
+ #
167
+ #
168
+ # By default, it will begin at the first Account and end at the last Account
169
+ #
170
+ #
171
+ # With default batch_size: 150, if you wanted to get your records from
172
+ # 150 to 300 you would start at 2 and finish at 2.
173
+ #
174
+ #
175
+ #
176
+ # Returns an Array of objects corresponding to the `start` and `finish` values. Default is all objects.
177
+ #
178
+ #
179
+ # Optional parameters:
180
+ #
181
+ # start | Fixnum | batch to start with
182
+ # finish | Fixnum | batch to end with
183
+ # batch_size | Fixnum | between 1..150
184
+ #
185
+ #
186
+ # Example usage:
187
+ #
188
+ #
189
+ # VivialConnect::Account.find_in_batches {|batch| do_something_with_an_array(batch)}
190
+ # => [#<VivialConnect::Account>]
191
+ #
192
+ #
193
+ ##
194
+ #=== .subaccounts
195
+ #
196
+ #Returns an array containing ruby objects containing all associated subaccounts
197
+ #
198
+ #
199
+ # Example usage:
200
+ #
201
+ #
202
+ # VivialConnect::Account.subaccounts
203
+ # => [#<VivialConnect::Account>, #<VivialConnect::Account>, #<VivialConnect::Account>]
204
+ #
205
+ #
206
+ ##
207
+ #=== .update(id, options={})
208
+ #
209
+ # Required parameters:
210
+ #
211
+ # id | Fixnum | 10000
212
+ # company_name | String | "New Name"
213
+ #
214
+ # Example usage:
215
+ #
216
+ #
217
+ # VivialConnect::Account.update(1000, company_name: "New Name")
218
+ # => #<VivialConnect::Account account_id=1XXXX, accounts=[], active=true, company_name="New Name", contacts=[], date_created="2017-04-20T17:07:08-04:00", date_modified="2017-04-20T17:07:08-04:00", id=10086, services=[{"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"SMS service", "id"=>1, "name"=>"sms", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Account service", "id"=>2, "name"=>"accounts", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Public service", "id"=>3, "name"=>"public", "service_type"=>"client"}]>
219
+ #
220
+ #
221
+ ##
222
+ #=== \#save
223
+ #
224
+ # Creates a subaccount associated with your main account or updates an existing one
225
+ #
226
+ #
227
+ # Example usage:
228
+ #
229
+ # account = VivialConnect::Account.new
230
+ # account.company_name = "B Tester QA Inc."
231
+ # account.save
232
+ # => #<VivialConnect::Account account_id=1XXXX, accounts=[], active=true, company_name="B Tester QA Inc.", contacts=[], date_created="2017-04-20T17:07:08-04:00", date_modified="2017-04-20T17:07:08-04:00", id=10086, services=[{"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"SMS service", "id"=>1, "name"=>"sms", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Account service", "id"=>2, "name"=>"accounts", "service_type"=>"client"}, {"active"=>true, "date_created"=>"2016-09-30T19:42:58-04:00", "date_modified"=>"2016-09-30T19:42:58-04:00", "description"=>"Public service", "id"=>3, "name"=>"public", "service_type"=>"client"}]>
233
+ #
234
+ #
235
+ class Account < Resource
236
+
237
+ def self.subaccounts # :nodoc:
238
+ uri = '/subaccounts.json'
239
+ VivialConnect::Client.instance.make_request('GET', uri)
240
+ end
241
+
242
+ def self.add_main_contact_to_subaccount(options={}) # :nodoc:
243
+ raise VivialConnectClientError, "you must include an account_id parameter" if !options.keys.include?(:account_id)
244
+
245
+ # This call must be made from the subaccount, so the client's account_id has to be updated
246
+ main_account_id = VivialConnect::Client.instance.account_id
247
+
248
+ VivialConnect::Client.instance.account_id = options[:account_id]
249
+ uri = '/contacts.json'
250
+ options[:contact_type] = 'main'
251
+ data = {}
252
+ data[:contact] = options
253
+ data = data.to_json
254
+
255
+ begin
256
+ response = VivialConnect::Client.instance.make_request('POST', uri, data)
257
+ ensure
258
+ # client's account_id must be set back for future calls to work
259
+ VivialConnect::Client.instance.account_id = main_account_id
260
+ end
261
+
262
+ response
263
+ end
264
+
265
+ def self.add_user_to_subaccount(options={}) # :nodoc:
266
+ raise VivialConnectClientError, "you must include an account_id parameter" if !options.keys.include?(:account_id)
267
+ uri = '/users/register.json'
268
+ options[:role] = 'User'
269
+ data = {}
270
+ data[:user] = options
271
+ data = data.to_json
272
+ response = VivialConnect::Client.instance.make_request('POST', uri, data)
273
+ end
274
+
275
+ end
276
+ end
277
+
278
+
@@ -0,0 +1,74 @@
1
+ module VivialConnect
2
+ ##
3
+ #=== .count_by_message_id(message_id)
4
+ #
5
+ #Returns the number of attachments related to the message_id passed.
6
+ #
7
+ #
8
+ # Example usage:
9
+ #
10
+ #
11
+ # VivialConnect::Attachment.count_by_message_id(844)
12
+ # => 1
13
+ #
14
+ #
15
+ ##
16
+ #=== .delete(message_id, attachment_id)
17
+ #
18
+ #Deletes Attachment related to the `message_id` passed
19
+ #
20
+ #
21
+ # Example usage:
22
+ #
23
+ #
24
+ # VivialConnect::Attachment.delete(844, 190)
25
+ # => true
26
+ #
27
+ #
28
+ ##
29
+ #=== .find(message_id, attachment_id)
30
+ #
31
+ #Returns an Attachment corresponding to the `message_id` and `attachment_id` passed
32
+ #
33
+ #
34
+ # Example usage:
35
+ #
36
+ #
37
+ # VivialConnect::Attachment.find(844, 190)
38
+ # => [#<VivialConnect::Attachment account_id=1XXXX, content_type="image/jpeg", date_created="2017-04-19T11:18:16-04:00", date_modified="2017-04-19T11:18:16-04:00", file_name="great-dane.jpg", id=190, key_name="mms/50/e9aa5a6970498352a399ebdf798b86bb801b5b/great-dane.jpg", message_id=844, size=110805>]
39
+ #
40
+ #
41
+ ##
42
+ #=== .find_all_by_message_id(message_id)
43
+ #
44
+ #Returns an array containing ruby objects corresponding to all attachment resources related to the `message_id` passed
45
+ #
46
+ #
47
+ # Example usage:
48
+ #
49
+ #
50
+ # VivialConnect::Attachment.find_all_by_message_id(844)
51
+ # => [#<VivialConnect::Attachment account_id=1XXXX, content_type="image/jpeg", date_created="2017-04-19T11:18:16-04:00", date_modified="2017-04-19T11:18:16-04:00", file_name="great-dane.jpg", id=190, key_name="mms/50/e9aa5a6970498352a399ebdf798b86bb801b5b/great-dane.jpg", message_id=844, size=110805>]
52
+ #
53
+ #
54
+
55
+ class Attachment < Resource
56
+
57
+ def self.find_all_by_message_id(message_id) #:nodoc:
58
+ VivialConnect::Client.instance.make_request('GET', "/messages/#{message_id}/attachments.json")
59
+ end
60
+
61
+ def self.find(message_id, attachment_id) #:nodoc:
62
+ VivialConnect::Client.instance.make_request('GET', "/messages/#{message_id}/attachments/#{attachment_id}.json")
63
+ end
64
+
65
+ def self.count_by_message_id(message_id) #:nodoc:
66
+ VivialConnect::Client.instance.make_request('GET', "/messages/#{message_id}/attachments/count.json")
67
+ end
68
+
69
+ def self.delete(message_id, attachment_id) #:nodoc:
70
+ VivialConnect::Client.instance.make_request('DELETE', "/messages/#{message_id}/attachments/#{attachment_id}.json")
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,326 @@
1
+ require 'faraday'
2
+ require 'addressable'
3
+ require 'digest'
4
+ require 'openssl'
5
+ require 'singleton'
6
+
7
+ module VivialConnect
8
+
9
+ ##
10
+ #=== .configure(api_key, api_secret, account_id, host="https://api.vivialconnect.net/api/", api_version="v1.0" )
11
+ #
12
+ #Configures the client with your `api_key`, `api_secret`, `account_id`, `host`, and `api_version`
13
+ #
14
+ #
15
+ # Required parameters:
16
+ #
17
+ # api_key | String | "YOURAPIKEY"
18
+ # api_secret | String | "YOURAPISECRET"
19
+ # account_id | Fixnum | 100000
20
+ #
21
+ #
22
+ # Optional parameters:
23
+ #
24
+ # host | String | "baseapiurl"
25
+ # api_version | String | "v1.9"
26
+ #
27
+ # NOTE: default host is "https://api.vivialconnect.net/api/" and default version is "v1.0"
28
+ #
29
+ #
30
+ # Example usage:
31
+ #
32
+ #
33
+ # VivialConnect::Client.configure(API_KEY, API_SECRET, ACCOUNT_ID)
34
+ # => true
35
+ #
36
+ # NOTE: .configure does not check if your credentials are good, it merely checks that you have entered values for them
37
+ #=== .reset
38
+ #
39
+ #Resets all of the configuration values to nil. This gives you a blank slate client to call .configure on.
40
+ #
41
+ #
42
+ # Example usage
43
+ #
44
+ #
45
+ # VivialConnect::Client.reset
46
+ # => true
47
+ #
48
+ #
49
+ #=== \#reset_api_base_path(new_host, new_api_version)
50
+ #
51
+ #Resets the api base path (host + api_version) on an instantiated client instance
52
+ #
53
+ # Required paramters:
54
+ #
55
+ # new_host | String | "https://api.vivialconnect.net/api/"
56
+ # new_api_version | String | "v1.1"
57
+ #
58
+ #
59
+ # Example usage
60
+ #
61
+ # VivialConnect::Client.instance.reset_api_base_path("https://api.vivialconnect.net/api/", "v1.1" )
62
+ # => true
63
+
64
+ class Client
65
+
66
+ #:nodoc:
67
+
68
+ include Singleton
69
+
70
+ @@configured = false
71
+
72
+ def initialize
73
+ begin
74
+ @base_api_path = host + "#{api_version}/"
75
+ connection
76
+ rescue NameError => e
77
+ raise VivialConnectClientError, "Please configure client before making requests. You can do this like so: .configure(api_key, api_secret, account_id) to "
78
+ end
79
+ end
80
+
81
+ def self.configure(api_key, api_secret, account_id, host="https://api.vivialconnect.net/api/", api_version="v1.0" )
82
+ @@api_key= api_key
83
+ @@api_secret = api_secret
84
+ @@account_id = account_id
85
+ @@host = host
86
+ @@api_version = api_version
87
+ @@configured = true
88
+ true
89
+ end
90
+
91
+ def self.reset
92
+ @@api_key= nil
93
+ @@api_secret = nil
94
+ @@account_id = nil
95
+ @@host = nil
96
+ @@api_version = nil
97
+ @@configured = false
98
+ @base_api_path = nil
99
+ true
100
+ end
101
+
102
+ def host
103
+ @@host
104
+ end
105
+
106
+ def account_id
107
+ @@account_id
108
+ end
109
+
110
+ def account_id=(id)
111
+ @@account_id = id
112
+ end
113
+
114
+ def reset_api_base_path(new_host, new_api_version)
115
+ @base_api_path = new_host + "#{new_api_version}/"
116
+ connection
117
+ true
118
+ end
119
+
120
+
121
+ def api_version
122
+ @@api_version
123
+ end
124
+
125
+ def base_api_path
126
+ @base_api_path
127
+ end
128
+
129
+
130
+ def self.configured?
131
+ @@configured == true
132
+ end
133
+
134
+
135
+ def set_request_timestamp
136
+ @request_timestamp = Time.now.utc.strftime('%Y%m%dT%H%M%SZ')
137
+ end
138
+
139
+
140
+ def request_timestamp
141
+ @request_timestamp
142
+ end
143
+
144
+
145
+ def set_date_for_date_header
146
+ @date_for_date_header = Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
147
+ end
148
+
149
+
150
+ def date_for_date_header
151
+ @date_for_date_header
152
+ end
153
+
154
+
155
+ def api_key
156
+ @@api_key
157
+ end
158
+
159
+
160
+ def api_secret
161
+ @@api_secret
162
+ end
163
+
164
+
165
+ def set_hmac_sha256(canonical_request)
166
+ @hmac_sha256 = OpenSSL::HMAC.hexdigest('SHA256', api_secret, canonical_request)
167
+ end
168
+
169
+
170
+ def hmac_sha256
171
+ @hmac_sha256
172
+ end
173
+
174
+ def build_canonical_request(http_verb, url, request_timestamp, canonicalized_headers, canonicalized_header_names, data={})
175
+ canonical_request = http_verb + "\n" + request_timestamp + "\n" + Addressable::URI.encode(url.path) +
176
+ "\n" + get_canonicalized_query_string(url) + "\n" + canonicalized_headers + "\n" +
177
+ canonicalized_header_names + "\n" + Digest::SHA256.hexdigest(data.to_s)
178
+ end
179
+
180
+
181
+ def sign_request(http_verb, url, data={})
182
+ set_request_timestamp
183
+ set_date_for_date_header
184
+ canonicalized_headers = "accept:application/json" + "\n" + "date:#{date_for_date_header}" + "\n" +"host:api.vivialconnect.net"
185
+ canonicalized_header_names = "accept;date;host"
186
+ canonical_request = build_canonical_request(http_verb, url, request_timestamp, canonicalized_headers, canonicalized_header_names, data)
187
+ set_hmac_sha256(canonical_request)
188
+ end
189
+
190
+
191
+ def get_canonicalized_query_string(url)
192
+ return "" unless url.query_values
193
+ sorted_params = url.query_values.sort
194
+ # gsub because Addressable encodes an empty space as + in parameters
195
+ # and vivial connect api requires spaces to be %20 encoded
196
+ # http://stackoverflow.com/questions/2824126/whats-the-difference-between-uri-escape-and-cgi-escape
197
+ encoded_sorted_params = Addressable::URI.form_encode(sorted_params).gsub('+', '%20')
198
+ end
199
+
200
+
201
+ def connection
202
+ @conn = Faraday.new(:url => base_api_path)
203
+ end
204
+
205
+ def make_request(request_method, url, data={})
206
+ raise VivialConnectClientError, "invalid request method" unless ['GET', 'POST', 'PUT', 'DELETE'].include?(request_method)
207
+ 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?
208
+
209
+ url = get_request_path(url)
210
+ sign_request(request_method, url, data)
211
+ headers = create_request_headers
212
+ request_method = request_method.downcase.to_sym
213
+ response = connection.run_request(request_method, url, data.to_s, headers)
214
+ process_api_response(response, url)
215
+ end
216
+
217
+
218
+ def create_request_headers
219
+ headers = {}
220
+ headers['Content-Type'] = 'application/json'
221
+ headers['Host'] = 'api.vivialconnect.net'
222
+ headers['X-Auth-Date'] = request_timestamp
223
+ headers['X-Auth-SignedHeaders'] = 'accept;date;host'
224
+ headers['Authorization'] = "HMAC" + " " + api_key + ":" + hmac_sha256
225
+ headers['Date'] = date_for_date_header
226
+ headers['Accept'] = 'application/json'
227
+ headers
228
+ end
229
+
230
+
231
+ def no_account_number_endpoints
232
+ ['accounts.json', '/accounts/count.json', 'registration/register.json']
233
+ end
234
+
235
+
236
+ def account_regex_match?(url)
237
+ m = /accounts\/[0-9]+.json/.match(url)
238
+ return !m.nil?
239
+ end
240
+
241
+
242
+ def account_query_match?(url)
243
+ url.include?("accounts.json?")
244
+ end
245
+
246
+
247
+ def get_request_path(url)
248
+ if no_account_number_endpoints.include?(url) || account_regex_match?(url) || account_query_match?(url)
249
+ base_path = base_api_path
250
+ Addressable::URI.parse(base_path + url)
251
+ else
252
+ base_path = base_api_path + "accounts/#{account_id}"
253
+ Addressable::URI.parse(base_path + url)
254
+ end
255
+ end
256
+
257
+ def process_api_response(response, url)
258
+ # make API response into appropriate object and return it
259
+ api_response = {}
260
+ raise VivialConnectClientError, JSON.parse(response.body)['message'] ? JSON.parse(response.body)['message'] : response.body if response.status >= 400
261
+ response_class = choose_response_class(url.path)
262
+ if response.body == "" || response.body.include?("{}")
263
+ return true if response.status.between?(200, 299)
264
+ false
265
+ else
266
+ api_response = JSON.parse(response.body)
267
+ if api_response[api_response.keys.first].is_a?(Array)
268
+ #return an array of resource objects
269
+ response_array = api_response[api_response.keys.first]
270
+ api_response = process_array(response_array, response_class)
271
+ elsif url.path.split("/")[-1] == "subaccounts.json"
272
+ #handle subaccounts array
273
+ response_array = api_response[api_response.keys.first]['accounts']
274
+ api_response = process_array(response_array, response_class)
275
+ elsif api_response[api_response.keys[1]].is_a?(Array)
276
+ #handle Log resource, return last key and an array full of log objects
277
+ last_key = api_response['last_key']
278
+ response_array = api_response['log_items']
279
+ processed_array = process_array(response_array, response_class)
280
+ [last_key, processed_array]
281
+ elsif api_response[api_response.keys.first].is_a?(Fixnum)
282
+ # json is only one level deep for .count response, so no need to delete the json root
283
+ # return the number
284
+ api_response['count']
285
+ else
286
+ if response_class == VivialConnect::Log
287
+ # json is only one level deep for Log response, so no need to delete the json root
288
+ response_class.new(api_response)
289
+ else
290
+ # remove json root, these resources return nested info
291
+ api_response = api_response[api_response.keys.first]
292
+ response_class.new(api_response)
293
+ end
294
+ end
295
+
296
+ end
297
+ end
298
+
299
+ def process_array(array, response_class)
300
+ final_array = []
301
+ array.each {|index| final_array << response_class.new(index)}
302
+ final_array
303
+ end
304
+
305
+ def choose_response_class(url)
306
+ url = url.gsub('.json', '').split('/')
307
+ if (url.count <= 5 )|| (url.count == 6 && url[5] == 'count')
308
+ return Account
309
+ elsif url.include?('attachments')
310
+ return Attachment
311
+ elsif url.include?('subaccounts')
312
+ return Account
313
+ else
314
+ api_resource = url[5]
315
+ #exceptions needed for resources requiring camelcase
316
+ klass = api_resource.capitalize
317
+ #takes off pluralization -- may have to be updated to match self.pluralize(string) in Resource, or use library if necessary
318
+ klass = klass[0..-2]
319
+ return VivialConnect.const_get(klass)
320
+ end
321
+ end
322
+
323
+
324
+ end
325
+ end
326
+