rdstation-ruby-client 0.1.1 → 1.0.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
2
  SHA1:
3
- metadata.gz: 49d611a1dd83c95db29c6fd6abaf5e174d0cfaab
4
- data.tar.gz: 47644e5e101c69feeacd833935dae34764a915e5
3
+ metadata.gz: c632e94efb06e81ab00f5272d042b0c5b26cf55f
4
+ data.tar.gz: c947e738844beb8671118a0d76df0468f8361528
5
5
  SHA512:
6
- metadata.gz: f9d6ddc90bab5f0ba6a9403a10f4cd6efad29f31c2998f2ea1cbac80996caf1e97bcccc6c59a27a3723c311ba505b7f4fef3f45685fe7fd1d99115b64736731f
7
- data.tar.gz: 628b0e48df49f7082784d6a84e4d6a31590237f9140198bed8206d7e1a12c545f87dfcb0512f418af785735b10719fee8f4736391ad4ffebdf6a5c2d5827b975
6
+ metadata.gz: edc33857fcf8af5535d2446da9d0cd3327cd2a092b47d722cb1107887ff649f127a65c301cb80e45c4fae9997713e568eb88b81cfe72498971bbc348f07e6a4e
7
+ data.tar.gz: cd2315fe944d7790336f50586ad68ef9240092550ca75e2b8327863f880d59ba36ccb8a0012cf9d9fefda4901d2d2ab348a033a51812488136d38c463f7d94de
data/Gemfile.lock CHANGED
@@ -1,23 +1,24 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rdstation-ruby-client (0.0.5)
4
+ rdstation-ruby-client (1.0.0)
5
5
  httparty (~> 0.12)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- addressable (2.3.7)
10
+ addressable (2.5.2)
11
+ public_suffix (>= 2.0.2, < 4.0)
11
12
  ansi (1.5.0)
12
- crack (0.4.2)
13
+ crack (0.4.3)
13
14
  safe_yaml (~> 1.0.0)
14
15
  diff-lcs (1.2.5)
15
- httparty (0.13.5)
16
- json (~> 1.8)
16
+ hashdiff (0.3.7)
17
+ httparty (0.16.2)
17
18
  multi_xml (>= 0.5.2)
18
- json (1.8.3)
19
19
  minitest (4.7.5)
20
- multi_xml (0.5.5)
20
+ multi_xml (0.6.0)
21
+ public_suffix (3.0.2)
21
22
  rake (10.1.0)
22
23
  rspec (3.1.0)
23
24
  rspec-core (~> 3.1.0)
@@ -35,10 +36,10 @@ GEM
35
36
  turn (0.9.7)
36
37
  ansi
37
38
  minitest (~> 4)
38
- vcr (2.9.3)
39
- webmock (1.20.4)
39
+ webmock (2.3.2)
40
40
  addressable (>= 2.3.6)
41
41
  crack (>= 0.3.2)
42
+ hashdiff
42
43
 
43
44
  PLATFORMS
44
45
  ruby
@@ -49,8 +50,7 @@ DEPENDENCIES
49
50
  rdstation-ruby-client!
50
51
  rspec
51
52
  turn
52
- vcr
53
- webmock
53
+ webmock (~> 2.1)
54
54
 
55
55
  BUNDLED WITH
56
- 1.13.2
56
+ 1.16.1
data/README.md CHANGED
@@ -49,7 +49,7 @@ rdstation_client.change_lead_status(email: 'joe@foo.bar', status: 'won', value:
49
49
 
50
50
  ### Authentication
51
51
 
52
- #### Getting authentication URL
52
+ #### Getting authentication URL
53
53
 
54
54
  ```ruby
55
55
  rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret')
@@ -58,7 +58,7 @@ redirect_url = 'https://yourapp.org/auth/callback'
58
58
  rdstation_authentication.auth_url(redirect_url)
59
59
  ```
60
60
 
61
- #### Getting access_token
61
+ #### Getting access_token
62
62
 
63
63
  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.
64
64
 
@@ -67,7 +67,7 @@ rdstation_authentication = RDStation::Authentication.new('client_id', 'client_se
67
67
  rdstation_authentication.authenticate(code_returned_from_rdstation)
68
68
  ```
69
69
 
70
- #### Updating access_token
70
+ #### Updating access_token
71
71
 
72
72
  ```ruby
73
73
  rdstation_authentication = RDStation::Authentication.new('client_id', 'client_secret')
@@ -81,8 +81,8 @@ rdstation_authentication.update_access_token('refresh_token')
81
81
  Returns data about a specific Contact
82
82
 
83
83
  ```ruby
84
- rdstation_contacts = RDStation::Contacts.new('auth_token')
85
- rdstation_contacts.get_contact('uuid')
84
+ contact = RDStation::Contacts.new('auth_token')
85
+ contact.by_uuid('uuid')
86
86
  ```
87
87
 
88
88
  More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodGetDetailsuuid
@@ -92,23 +92,23 @@ More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodGetDe
92
92
  Returns data about a specific Contact
93
93
 
94
94
  ```ruby
95
- rdstation_contacts = RDStation::Contacts.new('auth_token')
96
- rdstation_contacts.get_contact_by_email('email')
95
+ contact = RDStation::Contacts.new('auth_token')
96
+ contact.by_email('email')
97
97
  ```
98
98
 
99
99
  More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodGetDetailsemail
100
100
 
101
101
  #### Update a Contact by UUID
102
102
 
103
- Updates the properties of a Contact.
103
+ Updates the properties of a Contact.
104
104
 
105
105
  ```ruby
106
106
  contact_info = {
107
107
  name: "Joe Foo"
108
108
  }
109
109
 
110
- rdstation_contacts = RDStation::Contacts.new('auth_token')
111
- rdstation_contacts.update_contact('uuid', contact_info)
110
+ contact = RDStation::Contacts.new('auth_token')
111
+ contact.update('uuid', contact_info)
112
112
  ```
113
113
  Contact Default Parameters
114
114
  - email
@@ -127,7 +127,7 @@ More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodPatch
127
127
 
128
128
  #### Upsert a Contact by identifier and value
129
129
 
130
- With an UPSERT like behavior, this method is capable of both updating the properties of a Contact or creating a new Contact. Whatever is used as an identifier cannot appear in the request payload as a field. This will result in a [BAD_REQUEST error](https://developers.rdstation.com/pt-BR/error-states#conflicting).
130
+ With an UPSERT like behavior, this method is capable of both updating the properties of a Contact or creating a new Contact. Whatever is used as an identifier cannot appear in the request payload as a field. This will result in a [BAD_REQUEST error](https://developers.rdstation.com/pt-BR/error-states#conflicting).
131
131
 
132
132
  ```ruby
133
133
  contact_info = {
@@ -137,8 +137,8 @@ contact_info = {
137
137
  identifier = "email"
138
138
  identifier_value = "joe@foo.bar"
139
139
 
140
- rdstation_contacts = RDStation::Contacts.new('auth_token')
141
- rdstation_contacts.upsert_contact(identifier, identifier_value, contact_info)
140
+ contact = RDStation::Contacts.new('auth_token')
141
+ contact.upsert(identifier, identifier_value, contact_info)
142
142
  ```
143
143
 
144
144
  More info: https://developers.rdstation.com/pt-BR/reference/contacts#methodPatchUpsertDetails
@@ -1,4 +1,11 @@
1
- require "httparty"
2
- require "rdstation/client"
3
- require "rdstation/contacts"
4
- require "rdstation/authentication"
1
+ require 'httparty'
2
+
3
+ # API requests
4
+ require 'rdstation/authentication'
5
+ require 'rdstation/client'
6
+ require 'rdstation/contacts'
7
+ require 'rdstation/fields'
8
+
9
+ # Error handling
10
+ require 'rdstation/error'
11
+ require 'rdstation/error_handler'
@@ -3,6 +3,9 @@ module RDStation
3
3
  class Authentication
4
4
  include HTTParty
5
5
 
6
+ AUTH_TOKEN_URL = 'https://api.rd.services/auth/token'.freeze
7
+ DEFAULT_HEADERS = { 'Content-Type' => 'application/json' }.freeze
8
+
6
9
  def initialize(client_id, client_secret)
7
10
  @client_id = client_id
8
11
  @client_secret = client_secret
@@ -11,44 +14,54 @@ module RDStation
11
14
  #
12
15
  # param redirect_url
13
16
  # URL that the user will be redirected
14
- # after confirming application authorization
17
+ # after confirming application authorization
15
18
  #
16
19
  def auth_url(redirect_url)
17
20
  "https://api.rd.services/auth/dialog?client_id=#{@client_id}&redirect_url=#{redirect_url}"
18
21
  end
19
22
 
23
+ # Public: Get the credentials from RD Station API
24
+ #
25
+ # code - The code String sent by RDStation after the user confirms authorization.
26
+ #
27
+ # Examples
20
28
  #
21
- # param code
22
- # parameter sent by RDStation after user confirms authorization
29
+ # authenticate("123")
30
+ # # => { 'access_token' => '54321', 'expires_in' => 86_400, 'refresh_token' => 'refresh' }
23
31
  #
32
+ # Returns the credentials Hash.
33
+ # Raises RDStation::Error::ExpiredCodeGrant if the code has expired
34
+ # Raises RDStation::Error::InvalidCredentials if the client_id, client_secret
35
+ # or code is invalid.
24
36
  def authenticate(code)
25
- post_to_auth_endpoint({ :code => code })
37
+ response = post_to_auth_endpoint(code: code)
38
+ parsed_body = JSON.parse(response.body)
39
+ return parsed_body unless parsed_body['errors']
40
+ RDStation::ErrorHandler.new(response).raise_errors
26
41
  end
27
42
 
28
43
  #
29
44
  # param refresh_token
30
- # parameter sent by RDStation after authenticate
45
+ # parameter sent by RDStation after authenticate
31
46
  #
32
47
  def update_access_token(refresh_token)
33
- post_to_auth_endpoint({ :refresh_token => refresh_token })
48
+ response = post_to_auth_endpoint(refresh_token: refresh_token)
49
+ parsed_body = JSON.parse(response.body)
50
+ return parsed_body unless parsed_body['errors']
51
+ RDStation::ErrorHandler.new(response).raise_errors
34
52
  end
35
53
 
36
54
  private
37
55
 
38
- def auth_token_url
39
- "https://api.rd.services/auth/token"
40
- end
41
-
42
- def post_to_auth_endpoint(params)
43
- default_body = { :client_id => @client_id, :client_secret => @client_secret }
44
-
45
- self.class.post(
46
- auth_token_url,
47
- :headers => {
48
- "Accept-Encoding": "identity"
49
- },
50
- :body => default_body.merge(params)
51
- )
52
- end
56
+ def post_to_auth_endpoint(params)
57
+ default_body = { client_id: @client_id, client_secret: @client_secret }
58
+ body = default_body.merge(params)
59
+
60
+ self.class.post(
61
+ AUTH_TOKEN_URL,
62
+ body: body.to_json,
63
+ headers: DEFAULT_HEADERS
64
+ )
65
+ end
53
66
  end
54
67
  end
@@ -12,12 +12,18 @@ module RDStation
12
12
  # param uuid:
13
13
  # The unique uuid associated to each RD Station Contact.
14
14
  #
15
- def get_contact(uuid)
16
- self.class.get(base_url(uuid), :headers => required_headers)
15
+ def by_uuid(uuid)
16
+ response = self.class.get(base_url(uuid), headers: required_headers)
17
+ response_body = JSON.parse(response.body)
18
+ return response_body unless response_body['errors']
19
+ RDStation::ErrorHandler.new(response).raise_errors
17
20
  end
18
21
 
19
- def get_contact_by_email(email)
20
- self.class.get(base_url("email:#{email}"), :headers => required_headers)
22
+ def by_email(email)
23
+ response = self.class.get(base_url("email:#{email}"), headers: required_headers)
24
+ response_body = JSON.parse(response.body)
25
+ return response_body unless response_body['errors']
26
+ RDStation::ErrorHandler.new(response).raise_errors
21
27
  end
22
28
 
23
29
  # The Contact hash may contain the following parameters:
@@ -31,8 +37,11 @@ module RDStation
31
37
  # :mobile_phone
32
38
  # :website
33
39
  # :tags
34
- def update_contact(uuid, contact_hash)
35
- self.class.patch(base_url(uuid), :body => contact_hash.to_json, :headers => required_headers)
40
+ def update(uuid, contact_hash)
41
+ response = self.class.patch(base_url(uuid), :body => contact_hash.to_json, :headers => required_headers)
42
+ response_body = JSON.parse(response.body)
43
+ return response_body unless response_body['errors']
44
+ RDStation::ErrorHandler.new(response).raise_errors
36
45
  end
37
46
 
38
47
  #
@@ -43,19 +52,22 @@ module RDStation
43
52
  # param contact_hash:
44
53
  # Contact data
45
54
  #
46
- def upsert_contact(identifier, identifier_value, contact_hash)
55
+ def upsert(identifier, identifier_value, contact_hash)
47
56
  path = "#{identifier}:#{identifier_value}"
48
- self.class.patch(base_url(path), :body => contact_hash.to_json, :headers => required_headers)
57
+ response = self.class.patch(base_url(path), body: contact_hash.to_json, headers: required_headers)
58
+ response_body = JSON.parse(response.body)
59
+ return response_body unless response_body['errors']
60
+ RDStation::ErrorHandler.new(response).raise_errors
49
61
  end
50
62
 
51
63
  private
52
64
 
53
- def base_url(path = "")
54
- "https://api.rd.services/platform/contacts/#{path}"
55
- end
65
+ def base_url(path = "")
66
+ "https://api.rd.services/platform/contacts/#{path}"
67
+ end
56
68
 
57
- def required_headers
58
- { "Authorization" => "Bearer #{@auth_token}", "Content-Type" => "application/json" }
59
- end
69
+ def required_headers
70
+ { "Authorization" => "Bearer #{@auth_token}", "Content-Type" => "application/json" }
71
+ end
60
72
  end
61
73
  end
@@ -0,0 +1,21 @@
1
+ module RDStation
2
+
3
+ class Error < StandardError
4
+ attr_reader :http_status, :headers, :body
5
+
6
+ def initialize(message, api_response_error)
7
+ @http_status = api_response_error.code
8
+ @headers = api_response_error.headers
9
+ @body = JSON.parse(api_response_error.body)
10
+ super(message)
11
+ end
12
+
13
+ class ConflictingField < Error; end
14
+ class Default < Error; end
15
+ class ExpiredAccessToken < Error; end
16
+ class ExpiredCodeGrant < Error; end
17
+ class InvalidCredentials < Error; end
18
+ class ResourceNotFound < Error; end
19
+ class Unauthorized < Error; end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'error_handler/conflicting_field'
2
+ require_relative 'error_handler/default'
3
+ require_relative 'error_handler/expired_access_token'
4
+ require_relative 'error_handler/expired_code_grant'
5
+ require_relative 'error_handler/invalid_credentials'
6
+ require_relative 'error_handler/resource_not_found'
7
+ require_relative 'error_handler/unauthorized'
8
+
9
+ module RDStation
10
+ class ErrorHandler
11
+ ERROR_TYPES = [
12
+ ErrorHandler::ConflictingField,
13
+ ErrorHandler::ExpiredAccessToken,
14
+ ErrorHandler::ExpiredCodeGrant,
15
+ ErrorHandler::InvalidCredentials,
16
+ ErrorHandler::ResourceNotFound,
17
+ ErrorHandler::Unauthorized,
18
+ ErrorHandler::Default
19
+ ].freeze
20
+
21
+ def initialize(response)
22
+ @response = response
23
+ end
24
+
25
+ def raise_errors
26
+ errors.each(&:raise_error)
27
+ # Raise only the exception message when the error is not recognized
28
+ unrecognized_error = @response['errors']
29
+ raise unrecognized_error['error_message']
30
+ end
31
+
32
+ private
33
+
34
+ def errors
35
+ ERROR_TYPES.map { |error| error.new(@response) }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ module RDStation
2
+ class ErrorHandler
3
+ class ConflictingField
4
+ attr_reader :api_response, :response_body, :error
5
+
6
+ ERROR_CODE = 'CONFLICTING_FIELD'.freeze
7
+ EXCEPTION_CLASS = RDStation::Error::ConflictingField
8
+
9
+ def initialize(api_response)
10
+ @api_response = api_response
11
+ @error = JSON.parse(api_response.body)['errors']
12
+ end
13
+
14
+ def raise_error
15
+ return unless conflicting_field?
16
+ raise EXCEPTION_CLASS.new(error['error_message'], api_response)
17
+ end
18
+
19
+ private
20
+
21
+ def conflicting_field?
22
+ error['error_type'] == ERROR_CODE
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ module RDStation
2
+ class ErrorHandler
3
+ class Default
4
+ attr_reader :api_response
5
+ EXCEPTION_CLASS = RDStation::Error::Default
6
+
7
+ def initialize(api_response)
8
+ @api_response = api_response
9
+ end
10
+
11
+ def raise_error
12
+ raise RDStation::Error::Default.new(
13
+ 'An unrecognized error has occurred.',
14
+ api_response
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module RDStation
2
+ class ErrorHandler
3
+ class ExpiredAccessToken
4
+ attr_reader :api_response, :response_headers, :error
5
+
6
+ EXCEPTION_CLASS = RDStation::Error::ExpiredAccessToken
7
+
8
+ def initialize(api_response)
9
+ @api_response = api_response
10
+ @error = JSON.parse(api_response.body)['errors']
11
+ @response_headers = api_response.headers
12
+ end
13
+
14
+ def raise_error
15
+ return unless expired_token?
16
+ raise EXCEPTION_CLASS.new(error['error_message'], api_response)
17
+ end
18
+
19
+ private
20
+
21
+ def expired_token?
22
+ auth_header = response_headers['x-amzn-remapped-www-authenticate'] ||
23
+ response_headers['www-authenticate']
24
+
25
+ return unless auth_header
26
+ auth_header.include?('error="expired_token"')
27
+ end
28
+ end
29
+ end
30
+ end