rdstation-ruby-client 1.2.1 → 2.0.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 +4 -4
- data/.github/ISSUE_TEMPLATE/rdsm-ruby-client-issue-template.md +49 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +59 -0
- data/README.md +154 -45
- data/lib/rdstation-ruby-client.rb +1 -0
- data/lib/rdstation/api_response.rb +3 -2
- data/lib/rdstation/authorization_header.rb +21 -0
- data/lib/rdstation/client.rb +11 -78
- data/lib/rdstation/contacts.rb +7 -11
- data/lib/rdstation/error.rb +22 -15
- data/lib/rdstation/error_handler.rb +27 -26
- data/lib/rdstation/error_handler/bad_request.rb +30 -0
- data/lib/rdstation/error_handler/unauthorized.rb +17 -9
- data/lib/rdstation/events.rb +4 -11
- data/lib/rdstation/fields.rb +4 -9
- data/lib/rdstation/version.rb +1 -1
- data/lib/rdstation/webhooks.rb +8 -12
- data/rdstation-ruby-client.gemspec +2 -0
- data/spec/lib/rdstation-ruby-client_spec.rb +1 -1
- data/spec/lib/rdstation/authorization_header_spec.rb +24 -0
- data/spec/lib/rdstation/client_spec.rb +37 -0
- data/spec/lib/rdstation/contacts_spec.rb +34 -41
- data/spec/lib/rdstation/error_handler/unauthorized_spec.rb +0 -29
- data/spec/lib/rdstation/error_handler_spec.rb +142 -29
- data/spec/lib/rdstation/events_spec.rb +15 -9
- data/spec/lib/rdstation/fields_spec.rb +5 -3
- data/spec/lib/rdstation/webhooks_spec.rb +16 -13
- metadata +12 -9
- data/lib/rdstation/error_handler/default.rb +0 -15
- data/lib/rdstation/error_handler/resource_not_found.rb +0 -24
- data/spec/lib/rdstation/error_handler/default_spec.rb +0 -14
- data/spec/lib/rdstation/error_handler/resource_not_found_spec.rb +0 -54
data/lib/rdstation/contacts.rb
CHANGED
@@ -3,9 +3,9 @@ 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(
|
8
|
-
@
|
6
|
+
|
7
|
+
def initialize(authorization_header:)
|
8
|
+
@authorization_header = authorization_header
|
9
9
|
end
|
10
10
|
|
11
11
|
#
|
@@ -13,12 +13,12 @@ module RDStation
|
|
13
13
|
# The unique uuid associated to each RD Station Contact.
|
14
14
|
#
|
15
15
|
def by_uuid(uuid)
|
16
|
-
response = self.class.get(base_url(uuid), headers:
|
16
|
+
response = self.class.get(base_url(uuid), headers: @authorization_header.to_h)
|
17
17
|
ApiResponse.build(response)
|
18
18
|
end
|
19
19
|
|
20
20
|
def by_email(email)
|
21
|
-
response = self.class.get(base_url("email:#{email}"), headers:
|
21
|
+
response = self.class.get(base_url("email:#{email}"), headers: @authorization_header.to_h)
|
22
22
|
ApiResponse.build(response)
|
23
23
|
end
|
24
24
|
|
@@ -34,7 +34,7 @@ module RDStation
|
|
34
34
|
# :website
|
35
35
|
# :tags
|
36
36
|
def update(uuid, contact_hash)
|
37
|
-
response = self.class.patch(base_url(uuid), :body => contact_hash.to_json, :headers =>
|
37
|
+
response = self.class.patch(base_url(uuid), :body => contact_hash.to_json, :headers => @authorization_header.to_h)
|
38
38
|
ApiResponse.build(response)
|
39
39
|
end
|
40
40
|
|
@@ -48,7 +48,7 @@ module RDStation
|
|
48
48
|
#
|
49
49
|
def upsert(identifier, identifier_value, contact_hash)
|
50
50
|
path = "#{identifier}:#{identifier_value}"
|
51
|
-
response = self.class.patch(base_url(path), body: contact_hash.to_json, headers:
|
51
|
+
response = self.class.patch(base_url(path), body: contact_hash.to_json, headers: @authorization_header.to_h)
|
52
52
|
ApiResponse.build(response)
|
53
53
|
end
|
54
54
|
|
@@ -57,9 +57,5 @@ module RDStation
|
|
57
57
|
def base_url(path = "")
|
58
58
|
"https://api.rd.services/platform/contacts/#{path}"
|
59
59
|
end
|
60
|
-
|
61
|
-
def required_headers
|
62
|
-
{ "Authorization" => "Bearer #{@auth_token}", "Content-Type" => "application/json" }
|
63
|
-
end
|
64
60
|
end
|
65
61
|
end
|
data/lib/rdstation/error.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module RDStation
|
2
|
-
|
3
2
|
class Error < StandardError
|
4
3
|
attr_reader :details, :http_status, :headers, :body
|
5
4
|
|
@@ -8,23 +7,31 @@ module RDStation
|
|
8
7
|
message = details['error_message']
|
9
8
|
raise ArgumentError, 'The details hash must contain an error message' unless message
|
10
9
|
|
11
|
-
# Those three arguments are kept only for compatibility reasons.
|
12
|
-
# They aren't needed since we can get them directly in the details hash.
|
13
|
-
# Consider removing them when update the major version.
|
14
|
-
@http_status = details['http_status']
|
15
|
-
@headers = details['headers']
|
16
|
-
@body = details['body']
|
17
|
-
|
18
10
|
super(message)
|
19
11
|
end
|
20
12
|
|
21
|
-
class
|
22
|
-
class Default < Error; end
|
23
|
-
class ExpiredAccessToken < Error; end
|
24
|
-
class ExpiredCodeGrant < Error; end
|
25
|
-
class InvalidCredentials < Error; end
|
26
|
-
class InvalidEventType < Error; end
|
27
|
-
class ResourceNotFound < Error; end
|
13
|
+
class BadRequest < Error; end
|
28
14
|
class Unauthorized < Error; end
|
15
|
+
class Forbidden < Error; end
|
16
|
+
class NotFound < Error; end
|
17
|
+
class MethodNotAllowed < Error; end
|
18
|
+
class NotAcceptable < Error; end
|
19
|
+
class Conflict < Error; end
|
20
|
+
class UnsupportedMediaType < Error; end
|
21
|
+
class UnprocessableEntity < Error; end
|
22
|
+
class InternalServerError < Error; end
|
23
|
+
class NotImplemented < Error; end
|
24
|
+
class BadGateway < Error; end
|
25
|
+
class ServiceUnavailable < Error; end
|
26
|
+
class ServerError < Error; end
|
27
|
+
|
28
|
+
# 400 - Bad Request
|
29
|
+
class ConflictingField < BadRequest; end
|
30
|
+
class InvalidEventType < BadRequest; end
|
31
|
+
|
32
|
+
# 401 - Unauthorized
|
33
|
+
class ExpiredAccessToken < Unauthorized; end
|
34
|
+
class ExpiredCodeGrant < Unauthorized; end
|
35
|
+
class InvalidCredentials < Unauthorized; end
|
29
36
|
end
|
30
37
|
end
|
@@ -1,37 +1,42 @@
|
|
1
1
|
require_relative 'error/formatter'
|
2
|
-
require_relative 'error_handler/
|
3
|
-
require_relative 'error_handler/default'
|
4
|
-
require_relative 'error_handler/expired_access_token'
|
5
|
-
require_relative 'error_handler/expired_code_grant'
|
6
|
-
require_relative 'error_handler/invalid_credentials'
|
7
|
-
require_relative 'error_handler/invalid_event_type'
|
8
|
-
require_relative 'error_handler/resource_not_found'
|
2
|
+
require_relative 'error_handler/bad_request'
|
9
3
|
require_relative 'error_handler/unauthorized'
|
10
4
|
|
11
5
|
module RDStation
|
12
6
|
class ErrorHandler
|
13
|
-
ERROR_TYPES = [
|
14
|
-
ErrorHandler::ConflictingField,
|
15
|
-
ErrorHandler::ExpiredAccessToken,
|
16
|
-
ErrorHandler::ExpiredCodeGrant,
|
17
|
-
ErrorHandler::InvalidCredentials,
|
18
|
-
ErrorHandler::InvalidEventType,
|
19
|
-
ErrorHandler::ResourceNotFound,
|
20
|
-
ErrorHandler::Unauthorized,
|
21
|
-
ErrorHandler::Default
|
22
|
-
].freeze
|
23
|
-
|
24
7
|
def initialize(response)
|
25
8
|
@response = response
|
9
|
+
@code = response.code
|
26
10
|
end
|
27
11
|
|
28
|
-
def
|
29
|
-
|
12
|
+
def raise_error
|
13
|
+
raise error_class, array_of_errors.first if error_class < RDStation::Error
|
14
|
+
|
15
|
+
error_class.new(array_of_errors).raise_error
|
30
16
|
end
|
31
17
|
|
32
18
|
private
|
33
19
|
|
34
|
-
attr_reader :response
|
20
|
+
attr_reader :response, :code
|
21
|
+
|
22
|
+
def error_class
|
23
|
+
case code
|
24
|
+
when 400 then RDStation::ErrorHandler::BadRequest
|
25
|
+
when 401 then RDStation::ErrorHandler::Unauthorized
|
26
|
+
when 403 then RDStation::Error::Forbidden
|
27
|
+
when 404 then RDStation::Error::NotFound
|
28
|
+
when 405 then RDStation::Error::MethodNotAllowed
|
29
|
+
when 406 then RDStation::Error::NotAcceptable
|
30
|
+
when 409 then RDStation::Error::Conflict
|
31
|
+
when 415 then RDStation::Error::UnsupportedMediaType
|
32
|
+
when 422 then RDStation::Error::UnprocessableEntity
|
33
|
+
when 500 then RDStation::Error::InternalServerError
|
34
|
+
when 501 then RDStation::Error::NotImplemented
|
35
|
+
when 502 then RDStation::Error::BadGateway
|
36
|
+
when 503 then RDStation::Error::ServiceUnavailable
|
37
|
+
when 500..599 then RDStation::Error::ServerError
|
38
|
+
end
|
39
|
+
end
|
35
40
|
|
36
41
|
def array_of_errors
|
37
42
|
error_formatter.to_array.map do |error|
|
@@ -39,10 +44,6 @@ module RDStation
|
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
42
|
-
def error_types
|
43
|
-
ERROR_TYPES.map { |error_type| error_type.new(array_of_errors) }
|
44
|
-
end
|
45
|
-
|
46
47
|
def response_errors
|
47
48
|
JSON.parse(response.body)
|
48
49
|
end
|
@@ -55,7 +56,7 @@ module RDStation
|
|
55
56
|
{
|
56
57
|
'headers' => response.headers,
|
57
58
|
'body' => JSON.parse(response.body),
|
58
|
-
'http_status' => response.code
|
59
|
+
'http_status' => response.code,
|
59
60
|
}
|
60
61
|
end
|
61
62
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'conflicting_field'
|
2
|
+
require_relative 'invalid_event_type'
|
3
|
+
|
4
|
+
module RDStation
|
5
|
+
class ErrorHandler
|
6
|
+
class BadRequest
|
7
|
+
BAD_REQUEST_ERRORS = [
|
8
|
+
ErrorHandler::ConflictingField,
|
9
|
+
ErrorHandler::InvalidEventType,
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
def initialize(array_of_errors)
|
13
|
+
@array_of_errors = array_of_errors
|
14
|
+
end
|
15
|
+
|
16
|
+
def raise_error
|
17
|
+
error_classes.each(&:raise_error)
|
18
|
+
raise RDStation::Error::BadRequest, @array_of_errors.first
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def error_classes
|
24
|
+
BAD_REQUEST_ERRORS.map do |error|
|
25
|
+
error.new(@array_of_errors)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,23 +1,31 @@
|
|
1
|
+
require_relative 'expired_access_token'
|
2
|
+
require_relative 'expired_code_grant'
|
3
|
+
require_relative 'invalid_credentials'
|
4
|
+
|
1
5
|
module RDStation
|
2
6
|
class ErrorHandler
|
3
7
|
class Unauthorized
|
4
|
-
|
5
|
-
|
6
|
-
|
8
|
+
UNAUTHORIZED_ERRORS = [
|
9
|
+
ErrorHandler::ExpiredAccessToken,
|
10
|
+
ErrorHandler::ExpiredCodeGrant,
|
11
|
+
ErrorHandler::InvalidCredentials,
|
12
|
+
].freeze
|
7
13
|
|
8
|
-
def initialize(
|
9
|
-
@
|
14
|
+
def initialize(array_of_errors)
|
15
|
+
@array_of_errors = array_of_errors
|
10
16
|
end
|
11
17
|
|
12
18
|
def raise_error
|
13
|
-
|
14
|
-
raise RDStation::Error::Unauthorized,
|
19
|
+
error_classes.each(&:raise_error)
|
20
|
+
raise RDStation::Error::Unauthorized, @array_of_errors.first
|
15
21
|
end
|
16
22
|
|
17
23
|
private
|
18
24
|
|
19
|
-
def
|
20
|
-
|
25
|
+
def error_classes
|
26
|
+
UNAUTHORIZED_ERRORS.map do |error|
|
27
|
+
error.new(@array_of_errors)
|
28
|
+
end
|
21
29
|
end
|
22
30
|
end
|
23
31
|
end
|
data/lib/rdstation/events.rb
CHANGED
@@ -4,15 +4,15 @@ module RDStation
|
|
4
4
|
|
5
5
|
EVENTS_ENDPOINT = 'https://api.rd.services/platform/events'.freeze
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(authorization_header:)
|
8
|
+
@authorization_header = authorization_header
|
9
9
|
end
|
10
10
|
|
11
11
|
def create(payload)
|
12
|
-
response = self.class.post(EVENTS_ENDPOINT, headers:
|
12
|
+
response = self.class.post(EVENTS_ENDPOINT, headers: @authorization_header.to_h, body: payload.to_json)
|
13
13
|
response_body = JSON.parse(response.body)
|
14
14
|
return response_body unless errors?(response_body)
|
15
|
-
RDStation::ErrorHandler.new(response).
|
15
|
+
RDStation::ErrorHandler.new(response).raise_error
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
@@ -20,12 +20,5 @@ module RDStation
|
|
20
20
|
def errors?(response_body)
|
21
21
|
response_body.is_a?(Array) || response_body['errors']
|
22
22
|
end
|
23
|
-
|
24
|
-
def required_headers
|
25
|
-
{
|
26
|
-
'Authorization' => "Bearer #{@auth_token}",
|
27
|
-
'Content-Type' => 'application/json'
|
28
|
-
}
|
29
|
-
end
|
30
23
|
end
|
31
24
|
end
|
data/lib/rdstation/fields.rb
CHANGED
@@ -5,20 +5,15 @@ module RDStation
|
|
5
5
|
include HTTParty
|
6
6
|
|
7
7
|
BASE_URL = 'https://api.rd.services/platform/contacts/fields'.freeze
|
8
|
-
|
9
|
-
def initialize(
|
10
|
-
@
|
8
|
+
|
9
|
+
def initialize(authorization_header:)
|
10
|
+
@authorization_header = authorization_header
|
11
11
|
end
|
12
12
|
|
13
13
|
def all
|
14
|
-
response = self.class.get(BASE_URL, headers:
|
14
|
+
response = self.class.get(BASE_URL, headers: @authorization_header.to_h)
|
15
15
|
ApiResponse.build(response)
|
16
16
|
end
|
17
17
|
|
18
|
-
private
|
19
|
-
|
20
|
-
def required_headers
|
21
|
-
{ "Authorization" => "Bearer #{@auth_token}", "Content-Type" => "application/json" }
|
22
|
-
end
|
23
18
|
end
|
24
19
|
end
|
data/lib/rdstation/version.rb
CHANGED
data/lib/rdstation/webhooks.rb
CHANGED
@@ -2,34 +2,34 @@ module RDStation
|
|
2
2
|
class Webhooks
|
3
3
|
include HTTParty
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(authorization_header:)
|
6
|
+
@authorization_header = authorization_header
|
7
7
|
end
|
8
8
|
|
9
9
|
def all
|
10
|
-
response = self.class.get(base_url, headers:
|
10
|
+
response = self.class.get(base_url, headers: @authorization_header.to_h)
|
11
11
|
ApiResponse.build(response)
|
12
12
|
end
|
13
13
|
|
14
14
|
def by_uuid(uuid)
|
15
|
-
response = self.class.get(base_url(uuid), headers:
|
15
|
+
response = self.class.get(base_url(uuid), headers: @authorization_header.to_h)
|
16
16
|
ApiResponse.build(response)
|
17
17
|
end
|
18
18
|
|
19
19
|
def create(payload)
|
20
|
-
response = self.class.post(base_url, headers:
|
20
|
+
response = self.class.post(base_url, headers: @authorization_header.to_h, body: payload.to_json)
|
21
21
|
ApiResponse.build(response)
|
22
22
|
end
|
23
23
|
|
24
24
|
def update(uuid, payload)
|
25
|
-
response = self.class.put(base_url(uuid), headers:
|
25
|
+
response = self.class.put(base_url(uuid), headers: @authorization_header.to_h, body: payload.to_json)
|
26
26
|
ApiResponse.build(response)
|
27
27
|
end
|
28
28
|
|
29
29
|
def delete(uuid)
|
30
|
-
response = self.class.delete(base_url(uuid), headers:
|
30
|
+
response = self.class.delete(base_url(uuid), headers: @authorization_header.to_h)
|
31
31
|
return webhook_deleted_message unless response.body
|
32
|
-
RDStation::ErrorHandler.new(response).
|
32
|
+
RDStation::ErrorHandler.new(response).raise_error
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
@@ -41,9 +41,5 @@ module RDStation
|
|
41
41
|
def base_url(path = '')
|
42
42
|
"https://api.rd.services/integrations/webhooks/#{path}"
|
43
43
|
end
|
44
|
-
|
45
|
-
def required_headers
|
46
|
-
{ 'Authorization' => "Bearer #{@auth_token}", 'Content-Type' => 'application/json' }
|
47
|
-
end
|
48
44
|
end
|
49
45
|
end
|
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.required_ruby_version = '>= 2.0.0'
|
22
|
+
|
21
23
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
24
|
spec.add_development_dependency "rake"
|
23
25
|
spec.add_development_dependency 'rspec'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RDStation::AuthorizationHeader do
|
4
|
+
|
5
|
+
describe ".initialize" do
|
6
|
+
context "when access_token is nil" do
|
7
|
+
it "raises an error" do
|
8
|
+
expect do
|
9
|
+
described_class.new(access_token: nil)
|
10
|
+
end.to raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#to_h" do
|
16
|
+
let(:access_token) { 'access_token' }
|
17
|
+
|
18
|
+
it "generates the correct header" do
|
19
|
+
header = described_class.new(access_token: access_token).to_h
|
20
|
+
expect(header['Authorization']).to eq "Bearer #{access_token}"
|
21
|
+
expect(header['Content-Type']).to eq "application/json"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RDStation::Client do
|
4
|
+
context "when access_token is given" do
|
5
|
+
let(:access_token) { 'access_token' }
|
6
|
+
let(:client) { described_class.new(access_token: access_token) }
|
7
|
+
let(:mock_authorization_header) { double(RDStation::AuthorizationHeader) }
|
8
|
+
|
9
|
+
before { allow(RDStation::AuthorizationHeader).to receive(:new).and_return mock_authorization_header }
|
10
|
+
|
11
|
+
it 'returns Contacts endpoint' do
|
12
|
+
expect(RDStation::Contacts).to receive(:new).with({ authorization_header: mock_authorization_header }).and_call_original
|
13
|
+
expect(client.contacts).to be_instance_of RDStation::Contacts
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns Events endpoint' do
|
17
|
+
expect(RDStation::Events).to receive(:new).with({ authorization_header: mock_authorization_header }).and_call_original
|
18
|
+
expect(client.events).to be_instance_of RDStation::Events
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns Fields endpoint' do
|
22
|
+
expect(RDStation::Fields).to receive(:new).with({ authorization_header: mock_authorization_header }).and_call_original
|
23
|
+
expect(client.fields).to be_instance_of RDStation::Fields
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns Webhooks endpoint' do
|
27
|
+
expect(RDStation::Webhooks).to receive(:new).with({ authorization_header: mock_authorization_header }).and_call_original
|
28
|
+
expect(client.webhooks).to be_instance_of RDStation::Webhooks
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when access_token isn't given" do
|
33
|
+
it "raises an ArgumentError exception" do
|
34
|
+
expect{ described_class.new(access_token: nil) }.to raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|