rdstation-ruby-client 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: adcf1abef180f5dd333152cc6956191fd637f09e
4
- data.tar.gz: 22ad74012fcef08e888ef1d72fb73989f84ee651
2
+ SHA256:
3
+ metadata.gz: 6ade7306767c00b8d39afdeb149d4aaebe84dfd35b389e2bf1435e623dfabfb7
4
+ data.tar.gz: 3bdc3dc84ff1395fa65dc86e172b5ca967696e88b60bf9774723fcd33c785fbe
5
5
  SHA512:
6
- metadata.gz: ad4409d04b424d90f74bab2a3d5264b7a0fe1b74b233840befff8e21a8597c40cb1cd99767292322b65a3ee309d809ad9a00ec8a851855476471fc89bb1a240c
7
- data.tar.gz: 54f42eac6c63524bdacfb2c00548f3e9fdc5b0b63554c9c3ceca15f0afc24c800339506582127ebcc21b59e2b39f15ba5b3e20fe3eca9a658d0a258c9b380b5c
6
+ metadata.gz: fddd4b51c76c965cbd44bda5e36712f26f694fbabd59a7c0b008174cfcacd4225b73ce7640b32e9aeaed2495950ff0c19b70a555b5d8bf0dab79eaf2ce060136
7
+ data.tar.gz: 90d96ef3c8d917deb7adbfe0aff6e2625b7f4f1d925d6b54e806df9aa3fd3de6378358521bbfce024eb32af06695f0974ca0f0dd8b9684ed1c537f2d228c97de
@@ -1,3 +1,48 @@
1
+ ## 2.2.0
2
+
3
+ ### Additions
4
+
5
+ #### Configuration
6
+
7
+ Now it is possible to configure global params like client_id and client_secret only once, so you don't need to provide them to `RDStation::Authentication` every time.
8
+
9
+ This can be done in the following way:
10
+
11
+ ```ruby
12
+ RDStation.configure do |config|
13
+ config.client_id = YOUR_CLIENT_ID
14
+ config.client_secret = YOUR_CLIENT_SECRET
15
+ end
16
+ ```
17
+
18
+ If you're using Rails, this can be done in `config/initializers`.
19
+
20
+ #### Automatic refresh of access_tokens
21
+
22
+ When an access_token expires, a new one will be obtained automatically and the request will be made again.
23
+
24
+ For this to work, you have to use `RDStation.configure` as described above, and provide the refresh token when instantiating `RDStation::Client` (ex: RDStation::Client.new(access_token: MY_ACCESS_TOKEN, refresh_token: MY_REFRESH_TOKEN).
25
+
26
+ You can keep track of access_token changes, by providing a callback block inconfiguration. This block will be called with an `RDStation::Authorization` object, which contains the updated `access_token` and `refresh_token`. For example:
27
+
28
+ ```ruby
29
+ RDStation.configure do |config|
30
+ config.on_access_token_refresh do |authorization|
31
+ MyStoredAuth.where(refresh_token: authorization.refresh_token).update_all(access_token: authorization.access_token)
32
+ end
33
+ end
34
+ ```
35
+
36
+ ### Deprecations
37
+
38
+ Providing `client_id` and `client_secret` directly to `RDStation::Authentication.new` is deprecated and will be removed in future versions. Use `RDStation.configure` instead.
39
+
40
+ Specifying refresh_token in `RDStation::Client.new(access_token: 'at', refresh_token: 'rt')` is optional right now, but will be mandatory in future versions.
41
+
42
+ ## 2.1.1
43
+
44
+ - Fixed a bug in error handling (issue [#47](https://github.com/ResultadosDigitais/rdstation-ruby-client/issues/47))
45
+
1
46
  ## 2.1.0
2
47
 
3
48
  ### Additions
@@ -54,6 +99,8 @@ In cause of Unahtorized (401), the following specific errors may be raised (thos
54
99
  - `RDStation::Error::ExpiredCodeGrant`
55
100
  - `RDStation::Error::InvalidCredentials`
56
101
 
102
+ The specific message and the http code are now returned by the `details` method.
103
+
57
104
  ### Dependencies
58
105
 
59
106
  `rdstation-ruby-client` now requires `ruby >= 2.0.0`.
data/README.md CHANGED
@@ -10,12 +10,13 @@ Upgrading? Check the [migration guide](#Migration-guide) before bumping to a new
10
10
 
11
11
  1. [Installation](#Installation)
12
12
  2. [Usage](#Usage)
13
- 1. [Authentication](#Authentication)
14
- 2. [Contacts](#Contacts)
15
- 3. [Events](#Events)
16
- 4. [Fields](#Fields)
17
- 5. [Webhooks](#Webhooks)
18
- 6. [Errors](#Errors)
13
+ 1. [Configuration](#Configuration)
14
+ 2. [Authentication](#Authentication)
15
+ 3. [Contacts](#Contacts)
16
+ 4. [Events](#Events)
17
+ 5. [Fields](#Fields)
18
+ 6. [Webhooks](#Webhooks)
19
+ 7. [Errors](#Errors)
19
20
  3. [Changelog](#Changelog)
20
21
  4. [Migration guide](#Migration-guide)
21
22
  1. [Upgrading from 1.2.x to 2.0.0](#Upgrading-from-1.2.x-to-2.0.0)
@@ -39,6 +40,19 @@ Or install it yourself as:
39
40
 
40
41
  ## Usage
41
42
 
43
+ ### Configuration
44
+
45
+ Before getting youre credentials, you need to configure client_id and client_secret as following:
46
+
47
+ ```ruby
48
+ RDStation.configure do |config|
49
+ config.client_id = YOUR_CLIENT_ID
50
+ config.client_secret = YOUR_CLIENT_SECRET
51
+ end
52
+ ```
53
+
54
+ For details on what `client_id` and `client_secret` are, check the [developers portal](https://developers.rdstation.com/en/authentication).
55
+
42
56
  ### Authentication
43
57
 
44
58
  For more details, check the [developers portal](https://developers.rdstation.com/en/authentication).
@@ -46,7 +60,7 @@ For more details, check the [developers portal](https://developers.rdstation.com
46
60
  #### Getting authentication URL
47
61
 
48
62
  ```ruby
49
- rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret')
63
+ rdstation_authentication = RDStation::Authentication.new
50
64
 
51
65
  redirect_url = 'https://yourapp.org/auth/callback'
52
66
  rdstation_authentication.auth_url(redirect_url)
@@ -57,17 +71,35 @@ rdstation_authentication.auth_url(redirect_url)
57
71
  You will need the code param that is returned from RD Station to your application after the user confirms the access at the authorization dialog.
58
72
 
59
73
  ```ruby
60
- rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret')
74
+ rdstation_authentication = RDStation::Authentication.new
61
75
  rdstation_authentication.authenticate(code_returned_from_rdstation)
76
+ # => { 'access_token' => '54321', 'expires_in' => 86_400, 'refresh_token' => 'refresh' }
62
77
  ```
63
78
 
64
- #### Updating access_token
79
+ #### Updating an expired access_token
65
80
 
66
81
  ```ruby
67
- rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret')
82
+ rdstation_authentication = RDStation::Authentication.new
68
83
  rdstation_authentication.update_access_token('refresh_token')
69
84
  ```
70
85
 
86
+ **NOTE**: This is done automatically when a request fails due to access_token expiration. To keep track of the new token, you have to provide a callback block in configuration. For example:
87
+
88
+ ```ruby
89
+ RDStation.configure do |config|
90
+ config.client_id = YOUR_CLIENT_ID
91
+ config.client_secret = YOUR_CLIENT_SECRET
92
+ config.on_access_token_refresh do |authorization|
93
+ # authorization.access_token_expires_in is the time (in seconds for with the token is valid)
94
+ # authorization.access_token is the new token
95
+ # authorization.refresh_token is the existing refresh_token
96
+ #
97
+ # If you are using ActiveRecord, you may want to update the stored access_token, like in the following code:
98
+ MyStoredAuth.where(refresh_token: authorization.refresh_token).update_all(access_token: authorization.access_token)
99
+ end
100
+ end
101
+ ```
102
+
71
103
  #### Revoking an access_token
72
104
 
73
105
  ```ruby
@@ -83,7 +115,7 @@ Note: this will completely remove your credentials from RD Station (`update_acce
83
115
  Returns data about a specific Contact
84
116
 
85
117
  ```ruby
86
- client = RDStation::Client.new(access_token: 'access_token')
118
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
87
119
  client.contacts.by_uuid('uuid')
88
120
  ```
89
121
 
@@ -94,7 +126,7 @@ More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodGetDe
94
126
  Returns data about a specific Contact
95
127
 
96
128
  ```ruby
97
- client = RDStation::Client.new(access_token: 'access_token')
129
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
98
130
  client.contacts.by_email('email')
99
131
  ```
100
132
 
@@ -109,7 +141,7 @@ contact_info = {
109
141
  name: "Joe Foo"
110
142
  }
111
143
 
112
- client = RDStation::Client.new(access_token: 'access_token')
144
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
113
145
  client.contacts.update('uuid', contact_info)
114
146
  ```
115
147
  Contact Default Parameters
@@ -139,7 +171,7 @@ contact_info = {
139
171
  identifier = "email"
140
172
  identifier_value = "joe@foo.bar"
141
173
 
142
- client = RDStation::Client.new(access_token: 'access_token')
174
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
143
175
  client.contacts.upsert(identifier, identifier_value, contact_info)
144
176
  ```
145
177
 
@@ -159,7 +191,7 @@ This creates a new event on RDSM:
159
191
 
160
192
  ```ruby
161
193
  payload = {} # hash representing the payload
162
- client = RDStation::Client.new(access_token: 'access_token')
194
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
163
195
  client.events.create(payload)
164
196
  ```
165
197
 
@@ -170,7 +202,7 @@ Endpoints to [manage Contact Fields](https://developers.rdstation.com/en/referen
170
202
  #### List all fields
171
203
 
172
204
  ```ruby
173
- client = RDStation::Client.new(access_token: 'access_token')
205
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
174
206
  client.fields.all
175
207
  ```
176
208
 
@@ -183,14 +215,14 @@ Choose to receive data based on certain actions, re-cast or marked as an opportu
183
215
  #### List all webhooks
184
216
 
185
217
  ```ruby
186
- client = RDStation::Client.new(access_token: 'access_token')
218
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
187
219
  client.webhooks.all
188
220
  ```
189
221
 
190
222
  #### Getting a webhook by UUID
191
223
 
192
224
  ```ruby
193
- client = RDStation::Client.new(access_token: 'access_token')
225
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
194
226
  client.webhooks.by_uuid('WEBHOOK_UUID')
195
227
  ```
196
228
 
@@ -198,7 +230,7 @@ client.webhooks.by_uuid('WEBHOOK_UUID')
198
230
 
199
231
  ```ruby
200
232
  payload = {} # payload representing a webhook
201
- client = RDStation::Client.new(access_token: 'access_token')
233
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
202
234
  client.webhooks.create(payload)
203
235
  ```
204
236
 
@@ -208,7 +240,7 @@ The required strucutre of the payload is [described here](https://developers.rds
208
240
 
209
241
  ```ruby
210
242
  payload = {} # payload representing a webhook
211
- client = RDStation::Client.new(access_token: 'access_token')
243
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
212
244
  client.webhooks.create('WEBHOOK_UUID', payload)
213
245
  ```
214
246
 
@@ -217,7 +249,7 @@ The required strucutre of the payload is [described here](https://developers.rds
217
249
  #### Deleting a webhook
218
250
 
219
251
  ```ruby
220
- client = RDStation::Client.new(access_token: 'access_token')
252
+ client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token')
221
253
  client.webhooks.delete('WEBHOOK_UUID')
222
254
  ```
223
255
 
@@ -249,6 +281,8 @@ In cause of Unauthorized (401), the following specific errors may be raised (tho
249
281
  - `RDStation::Error::ExpiredCodeGrant`
250
282
  - `RDStation::Error::InvalidCredentials`
251
283
 
284
+ Any error class has a `details` method which returns the specific error message and the http_status.
285
+
252
286
  ## Changelog
253
287
 
254
288
  See [CHANGELOG.md](CHANGELOG.md)
@@ -263,7 +297,7 @@ So, here is a step-by-step guide on how to upgrade your app:
263
297
  - Ensure you're using `ruby >= 2.0.0`.
264
298
  - Remove every direct instantiation of `RDStation::Contacts`, `RDStation::Events`, `RDStation::Fields` and `RDStation::Webhooks` and use `RDStation::Client` to get them instead.
265
299
  - Replace any call of `RDStation::Client#create_lead`, `RDStation::Client#change_lead` or `RDStation::Client#change_lead_status` with the equivalent method in the [Contacts API](#Contacts).
266
- - Review your error handling, as [more options](CHANGELOG.md#Error-handling) are available now.
300
+ - Review your error handling, as [more options](CHANGELOG.md#Error-handling) are available now. `http_status` method will always return nil. To get the status now use `error.details[:http_status]` or check the type of the class.
267
301
 
268
302
  ## Contributing
269
303
 
@@ -4,8 +4,10 @@ require 'httparty'
4
4
  require 'rdstation/api_response'
5
5
 
6
6
  # API requests
7
+ require 'rdstation'
8
+ require 'rdstation/retryable_request'
7
9
  require 'rdstation/authentication'
8
- require 'rdstation/authorization_header'
10
+ require 'rdstation/authorization'
9
11
  require 'rdstation/client'
10
12
  require 'rdstation/contacts'
11
13
  require 'rdstation/events'
@@ -0,0 +1,19 @@
1
+ module RDStation
2
+ class << self
3
+ attr_accessor :configuration
4
+
5
+ def configure
6
+ self.configuration ||= Configuration.new
7
+ yield(configuration)
8
+ end
9
+ end
10
+
11
+ class Configuration
12
+ attr_accessor :client_id, :client_secret
13
+ attr_reader :access_token_refresh_callback
14
+
15
+ def on_access_token_refresh(&block)
16
+ @access_token_refresh_callback = block
17
+ end
18
+ end
19
+ end
@@ -1,8 +1,7 @@
1
1
  module RDStation
2
2
  module ApiResponse
3
3
  def self.build(response)
4
- response_body = JSON.parse(response.body)
5
- return response_body if response.code.between?(200, 299)
4
+ return JSON.parse(response.body) if response.code.between?(200, 299)
6
5
 
7
6
  RDStation::ErrorHandler.new(response).raise_error
8
7
  end
@@ -7,9 +7,10 @@ module RDStation
7
7
  DEFAULT_HEADERS = { 'Content-Type' => 'application/json' }.freeze
8
8
  REVOKE_URL = 'https://api.rd.services/auth/revoke'.freeze
9
9
 
10
- def initialize(client_id, client_secret)
11
- @client_id = client_id
12
- @client_secret = client_secret
10
+ def initialize(client_id = nil, client_secret = nil)
11
+ warn_deprecation if client_id || client_secret
12
+ @client_id = client_id || RDStation.configuration&.client_id
13
+ @client_secret = client_secret || RDStation.configuration&.client_secret
13
14
  end
14
15
 
15
16
  #
@@ -83,5 +84,9 @@ module RDStation
83
84
  headers: DEFAULT_HEADERS
84
85
  )
85
86
  end
87
+
88
+ def warn_deprecation
89
+ warn "DEPRECATION WARNING: Providing client_id and client_secret directly to RDStation::Authentication.new is deprecated and will be removed in future versions. Use RDStation.configure instead."
90
+ end
86
91
  end
87
92
  end
@@ -1,21 +1,24 @@
1
1
  module RDStation
2
- class AuthorizationHeader
3
-
4
- def initialize(access_token:)
2
+ class Authorization
3
+ attr_reader :refresh_token
4
+ attr_accessor :access_token, :access_token_expires_in
5
+ def initialize(access_token:, refresh_token: nil, access_token_expires_in: nil)
5
6
  @access_token = access_token
7
+ @refresh_token = refresh_token
8
+ @access_token_expires_in = access_token_expires_in
6
9
  validate_access_token access_token
7
10
  end
8
-
9
- def to_h
11
+
12
+ def headers
10
13
  { "Authorization" => "Bearer #{@access_token}", "Content-Type" => "application/json" }
11
14
  end
12
-
15
+
13
16
  private
14
-
17
+
15
18
  def validate_access_token(access_token)
16
19
  access_token_msg = ':access_token is required'
17
20
  raise ArgumentError, access_token_msg unless access_token
18
21
  end
19
-
22
+
20
23
  end
21
24
  end
@@ -1,23 +1,33 @@
1
1
  module RDStation
2
2
  class Client
3
- def initialize(access_token:)
4
- @authorization_header = AuthorizationHeader.new(access_token: access_token)
3
+ def initialize(access_token:, refresh_token: nil)
4
+ warn_deprecation unless refresh_token
5
+ @authorization = Authorization.new(
6
+ access_token: access_token,
7
+ refresh_token: refresh_token
8
+ )
5
9
  end
6
-
10
+
7
11
  def contacts
8
- @contacts ||= RDStation::Contacts.new(authorization_header: @authorization_header)
12
+ @contacts ||= RDStation::Contacts.new(authorization: @authorization)
9
13
  end
10
14
 
11
15
  def events
12
- @events ||= RDStation::Events.new(authorization_header: @authorization_header)
16
+ @events ||= RDStation::Events.new(authorization: @authorization)
13
17
  end
14
18
 
15
19
  def fields
16
- @fields ||= RDStation::Fields.new(authorization_header: @authorization_header)
20
+ @fields ||= RDStation::Fields.new(authorization: @authorization)
17
21
  end
18
22
 
19
23
  def webhooks
20
- @webhooks ||= RDStation::Webhooks.new(authorization_header: @authorization_header)
24
+ @webhooks ||= RDStation::Webhooks.new(authorization: @authorization)
25
+ end
26
+
27
+ private
28
+
29
+ def warn_deprecation
30
+ warn "DEPRECATION WARNING: Specifying refresh_token in RDStation::Client.new(access_token: 'at', refresh_token: 'rt') is optional right now, but will be mandatory in future versions. "
21
31
  end
22
32
  end
23
33
  end
@@ -3,9 +3,10 @@ module RDStation
3
3
  # More info: https://developers.rdstation.com/pt-BR/reference/contacts
4
4
  class Contacts
5
5
  include HTTParty
6
-
7
- def initialize(authorization_header:)
8
- @authorization_header = authorization_header
6
+ include ::RDStation::RetryableRequest
7
+
8
+ def initialize(authorization:)
9
+ @authorization = authorization
9
10
  end
10
11
 
11
12
  #
@@ -13,13 +14,17 @@ module RDStation
13
14
  # The unique uuid associated to each RD Station Contact.
14
15
  #
15
16
  def by_uuid(uuid)
16
- response = self.class.get(base_url(uuid), headers: @authorization_header.to_h)
17
- ApiResponse.build(response)
17
+ retryable_request(@authorization) do |authorization|
18
+ response = self.class.get(base_url(uuid), headers: authorization.headers)
19
+ ApiResponse.build(response)
20
+ end
18
21
  end
19
22
 
20
23
  def by_email(email)
21
- response = self.class.get(base_url("email:#{email}"), headers: @authorization_header.to_h)
22
- ApiResponse.build(response)
24
+ retryable_request(@authorization) do |authorization|
25
+ response = self.class.get(base_url("email:#{email}"), headers: authorization.headers)
26
+ ApiResponse.build(response)
27
+ end
23
28
  end
24
29
 
25
30
  # The Contact hash may contain the following parameters:
@@ -34,8 +39,10 @@ module RDStation
34
39
  # :website
35
40
  # :tags
36
41
  def update(uuid, contact_hash)
37
- response = self.class.patch(base_url(uuid), :body => contact_hash.to_json, :headers => @authorization_header.to_h)
38
- ApiResponse.build(response)
42
+ retryable_request(@authorization) do |authorization|
43
+ response = self.class.patch(base_url(uuid), :body => contact_hash.to_json, :headers => authorization.headers)
44
+ ApiResponse.build(response)
45
+ end
39
46
  end
40
47
 
41
48
  #
@@ -47,14 +54,16 @@ module RDStation
47
54
  # Contact data
48
55
  #
49
56
  def upsert(identifier, identifier_value, contact_hash)
50
- path = "#{identifier}:#{identifier_value}"
51
- response = self.class.patch(base_url(path), body: contact_hash.to_json, headers: @authorization_header.to_h)
52
- ApiResponse.build(response)
57
+ retryable_request(@authorization) do |authorization|
58
+ path = "#{identifier}:#{identifier_value}"
59
+ response = self.class.patch(base_url(path), body: contact_hash.to_json, headers: authorization.headers)
60
+ ApiResponse.build(response)
61
+ end
53
62
  end
54
63
 
55
64
  private
56
65
 
57
- def base_url(path = "")
66
+ def base_url(path = '')
58
67
  "https://api.rd.services/platform/contacts/#{path}"
59
68
  end
60
69
  end