-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #49 from ResultadosDigitais/retryable-client
[Hackathon 2019 Q4] Refresh access tokens after expiration and retry requests
- Loading branch information
Showing
23 changed files
with
575 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,12 +10,13 @@ Upgrading? Check the [migration guide](#Migration-guide) before bumping to a new | |
|
||
1. [Installation](#Installation) | ||
2. [Usage](#Usage) | ||
1. [Authentication](#Authentication) | ||
2. [Contacts](#Contacts) | ||
3. [Events](#Events) | ||
4. [Fields](#Fields) | ||
5. [Webhooks](#Webhooks) | ||
6. [Errors](#Errors) | ||
1. [Configuration](#Configuration) | ||
2. [Authentication](#Authentication) | ||
3. [Contacts](#Contacts) | ||
4. [Events](#Events) | ||
5. [Fields](#Fields) | ||
6. [Webhooks](#Webhooks) | ||
7. [Errors](#Errors) | ||
3. [Changelog](#Changelog) | ||
4. [Migration guide](#Migration-guide) | ||
1. [Upgrading from 1.2.x to 2.0.0](#Upgrading-from-1.2.x-to-2.0.0) | ||
|
@@ -39,14 +40,27 @@ Or install it yourself as: | |
|
||
## Usage | ||
|
||
### Configuration | ||
|
||
Before getting youre credentials, you need to configure client_id and client_secret as following: | ||
|
||
```ruby | ||
RDStation.configure do |config| | ||
config.client_id = YOUR_CLIENT_ID | ||
config.client_secret = YOUR_CLIENT_SECRET | ||
end | ||
``` | ||
|
||
For details on what `client_id` and `client_secret` are, check the [developers portal](https://developers.rdstation.com/en/authentication). | ||
|
||
### Authentication | ||
|
||
For more details, check the [developers portal](https://developers.rdstation.com/en/authentication). | ||
|
||
#### Getting authentication URL | ||
|
||
```ruby | ||
rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret') | ||
rdstation_authentication = RDStation::Authentication.new | ||
|
||
redirect_url = 'https://yourapp.org/auth/callback' | ||
rdstation_authentication.auth_url(redirect_url) | ||
|
@@ -57,17 +71,35 @@ rdstation_authentication.auth_url(redirect_url) | |
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. | ||
|
||
```ruby | ||
rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret') | ||
rdstation_authentication = RDStation::Authentication.new | ||
rdstation_authentication.authenticate(code_returned_from_rdstation) | ||
# => { 'access_token' => '54321', 'expires_in' => 86_400, 'refresh_token' => 'refresh' } | ||
``` | ||
|
||
#### Updating access_token | ||
#### Updating an expired access_token | ||
|
||
```ruby | ||
rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret') | ||
rdstation_authentication = RDStation::Authentication.new | ||
rdstation_authentication.update_access_token('refresh_token') | ||
``` | ||
|
||
**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: | ||
|
||
```ruby | ||
RDStation.configure do |config| | ||
config.client_id = YOUR_CLIENT_ID | ||
config.client_secret = YOUR_CLIENT_SECRET | ||
config.on_access_token_refresh do |authorization| | ||
# authorization.access_token_expires_in is the time (in seconds for with the token is valid) | ||
# authorization.access_token is the new token | ||
# authorization.refresh_token is the existing refresh_token | ||
# | ||
# If you are using ActiveRecord, you may want to update the stored access_token, like in the following code: | ||
MyStoredAuth.where(refresh_token: authorization.refresh_token).update_all(access_token: authorization.access_token) | ||
end | ||
end | ||
``` | ||
|
||
#### Revoking an access_token | ||
|
||
```ruby | ||
|
@@ -83,7 +115,7 @@ Note: this will completely remove your credentials from RD Station (`update_acce | |
Returns data about a specific Contact | ||
|
||
```ruby | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.contacts.by_uuid('uuid') | ||
``` | ||
|
||
|
@@ -94,7 +126,7 @@ More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodGetDe | |
Returns data about a specific Contact | ||
|
||
```ruby | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.contacts.by_email('email') | ||
``` | ||
|
||
|
@@ -109,7 +141,7 @@ contact_info = { | |
name: "Joe Foo" | ||
} | ||
|
||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.contacts.update('uuid', contact_info) | ||
``` | ||
Contact Default Parameters | ||
|
@@ -139,7 +171,7 @@ contact_info = { | |
identifier = "email" | ||
identifier_value = "[email protected]" | ||
|
||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.contacts.upsert(identifier, identifier_value, contact_info) | ||
``` | ||
|
||
|
@@ -159,7 +191,7 @@ This creates a new event on RDSM: | |
|
||
```ruby | ||
payload = {} # hash representing the payload | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.events.create(payload) | ||
``` | ||
|
||
|
@@ -170,7 +202,7 @@ Endpoints to [manage Contact Fields](https://developers.rdstation.com/en/referen | |
#### List all fields | ||
|
||
```ruby | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.fields.all | ||
``` | ||
|
||
|
@@ -183,22 +215,22 @@ Choose to receive data based on certain actions, re-cast or marked as an opportu | |
#### List all webhooks | ||
|
||
```ruby | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.webhooks.all | ||
``` | ||
|
||
#### Getting a webhook by UUID | ||
|
||
```ruby | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.webhooks.by_uuid('WEBHOOK_UUID') | ||
``` | ||
|
||
#### Creating a webhook | ||
|
||
```ruby | ||
payload = {} # payload representing a webhook | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.webhooks.create(payload) | ||
``` | ||
|
||
|
@@ -208,7 +240,7 @@ The required strucutre of the payload is [described here](https://developers.rds | |
|
||
```ruby | ||
payload = {} # payload representing a webhook | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.webhooks.create('WEBHOOK_UUID', payload) | ||
``` | ||
|
||
|
@@ -217,7 +249,7 @@ The required strucutre of the payload is [described here](https://developers.rds | |
#### Deleting a webhook | ||
|
||
```ruby | ||
client = RDStation::Client.new(access_token: 'access_token') | ||
client = RDStation::Client.new(access_token: 'access_token', refresh_token: 'refresh_token') | ||
client.webhooks.delete('WEBHOOK_UUID') | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
module RDStation | ||
class << self | ||
attr_accessor :configuration | ||
|
||
def configure | ||
self.configuration ||= Configuration.new | ||
yield(configuration) | ||
end | ||
end | ||
|
||
class Configuration | ||
attr_accessor :client_id, :client_secret | ||
attr_reader :access_token_refresh_callback | ||
|
||
def on_access_token_refresh(&block) | ||
@access_token_refresh_callback = block | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 11 additions & 8 deletions
19
lib/rdstation/authorization_header.rb → lib/rdstation/authorization.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,24 @@ | ||
module RDStation | ||
class AuthorizationHeader | ||
|
||
def initialize(access_token:) | ||
class Authorization | ||
attr_reader :refresh_token | ||
attr_accessor :access_token, :access_token_expires_in | ||
def initialize(access_token:, refresh_token: nil, access_token_expires_in: nil) | ||
@access_token = access_token | ||
@refresh_token = refresh_token | ||
@access_token_expires_in = access_token_expires_in | ||
validate_access_token access_token | ||
end | ||
def to_h | ||
|
||
def headers | ||
{ "Authorization" => "Bearer #{@access_token}", "Content-Type" => "application/json" } | ||
end | ||
|
||
private | ||
|
||
def validate_access_token(access_token) | ||
access_token_msg = ':access_token is required' | ||
raise ArgumentError, access_token_msg unless access_token | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,33 @@ | ||
module RDStation | ||
class Client | ||
def initialize(access_token:) | ||
@authorization_header = AuthorizationHeader.new(access_token: access_token) | ||
def initialize(access_token:, refresh_token: nil) | ||
warn_deprecation unless refresh_token | ||
@authorization = Authorization.new( | ||
access_token: access_token, | ||
refresh_token: refresh_token | ||
) | ||
end | ||
|
||
def contacts | ||
@contacts ||= RDStation::Contacts.new(authorization_header: @authorization_header) | ||
@contacts ||= RDStation::Contacts.new(authorization: @authorization) | ||
end | ||
|
||
def events | ||
@events ||= RDStation::Events.new(authorization_header: @authorization_header) | ||
@events ||= RDStation::Events.new(authorization: @authorization) | ||
end | ||
|
||
def fields | ||
@fields ||= RDStation::Fields.new(authorization_header: @authorization_header) | ||
@fields ||= RDStation::Fields.new(authorization: @authorization) | ||
end | ||
|
||
def webhooks | ||
@webhooks ||= RDStation::Webhooks.new(authorization_header: @authorization_header) | ||
@webhooks ||= RDStation::Webhooks.new(authorization: @authorization) | ||
end | ||
|
||
private | ||
|
||
def warn_deprecation | ||
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. " | ||
end | ||
end | ||
end |
Oops, something went wrong.