rdstation-ruby-client 2.1.0 → 2.2.0

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 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