rdstation-ruby-client 1.2.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|