teamsupport 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +12 -0
- data/CHANGELOG.md +11 -0
- data/CONTRIBUTING.md +47 -0
- data/LICENSE.md +26 -0
- data/README.md +132 -0
- data/lib/teamsupport.rb +21 -0
- data/lib/teamsupport/arguments.rb +26 -0
- data/lib/teamsupport/base.rb +173 -0
- data/lib/teamsupport/client.rb +86 -0
- data/lib/teamsupport/creatable.rb +31 -0
- data/lib/teamsupport/customer.rb +66 -0
- data/lib/teamsupport/customer_product.rb +14 -0
- data/lib/teamsupport/error.rb +135 -0
- data/lib/teamsupport/headers.rb +51 -0
- data/lib/teamsupport/identity.rb +43 -0
- data/lib/teamsupport/null_object.rb +52 -0
- data/lib/teamsupport/product.rb +14 -0
- data/lib/teamsupport/rest/api.rb +19 -0
- data/lib/teamsupport/rest/client.rb +25 -0
- data/lib/teamsupport/rest/customers.rb +156 -0
- data/lib/teamsupport/rest/products.rb +113 -0
- data/lib/teamsupport/rest/request.rb +116 -0
- data/lib/teamsupport/rest/tickets.rb +134 -0
- data/lib/teamsupport/rest/utils.rb +325 -0
- data/lib/teamsupport/ticket.rb +81 -0
- data/lib/teamsupport/ticket_action.rb +16 -0
- data/lib/teamsupport/utils.rb +33 -0
- data/lib/teamsupport/version.rb +73 -0
- data/teamsupport.gemspec +27 -0
- metadata +158 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'teamsupport/error'
|
2
|
+
require 'teamsupport/utils'
|
3
|
+
require 'teamsupport/version'
|
4
|
+
|
5
|
+
module Teamsupport
|
6
|
+
class Client
|
7
|
+
# Provide api_key and api_secret methods for accessing Client API values
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# teamsupport_client = Teamsupport::Client.new(api_key: 'AK', api_secret: 'AS')
|
11
|
+
# teamsupport_client.api_key
|
12
|
+
# teamsupport_client.api_secret
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
#
|
16
|
+
# @api public
|
17
|
+
attr_accessor :api_key, :api_secret
|
18
|
+
|
19
|
+
# Provide user_agent method for overriding default Client user_agent value
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# teamsupport_client = Teamsupport::Client.new(api_key: 'AK', api_secret: 'AS')
|
23
|
+
# teamsupport_client.user_agent = 'MyTeamsupportClient/1.0.0'
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
attr_writer :user_agent
|
29
|
+
|
30
|
+
# Initializes a new Client object
|
31
|
+
#
|
32
|
+
# @param options [Hash]
|
33
|
+
#
|
34
|
+
# @return [Teamsupport::Client]
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
def initialize(options = {})
|
38
|
+
options.each do |key, value|
|
39
|
+
instance_variable_set("@#{key}", value)
|
40
|
+
end
|
41
|
+
yield(self) if block_given?
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns user agent string for the Client
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# teamsupport_client = Teamsupport::Client.new(api_key: 'AK', api_secret: 'AS')
|
48
|
+
# teamsupport_client.user_agent
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
#
|
52
|
+
# @api public
|
53
|
+
def user_agent
|
54
|
+
@user_agent ||= "TeamsupportRubyGem/#{Teamsupport::Version}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns authentication hash for the Client
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# teamsupport_client = Teamsupport::Client.new(api_key: 'AK', api_secret: 'AS')
|
61
|
+
# teamsupport_client.auth
|
62
|
+
#
|
63
|
+
# @return [Hash]
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def auth
|
67
|
+
{
|
68
|
+
user: api_key,
|
69
|
+
password: api_secret,
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
# Checks for the existence of an authentication hash on the Client
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# teamsupport_client = Teamsupport::Client.new(api_key: 'AK', api_secret: 'AS')
|
77
|
+
# teamsupport_client.auth?
|
78
|
+
#
|
79
|
+
# @return [Boolean]
|
80
|
+
#
|
81
|
+
# @api public
|
82
|
+
def auth?
|
83
|
+
auth.values.all?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Teamsupport
|
4
|
+
module Creatable
|
5
|
+
# Time when object was created on TeamSupport
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# teamsupport_object = Teamsupport::Creatable.new(DateCreated: '4/4/2015 9:45 AM')
|
9
|
+
# teamsupport_object.DateCreated
|
10
|
+
#
|
11
|
+
# @return [Time]
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def DateCreated # rubocop:disable Style/MethodName
|
15
|
+
Time.strptime(@attrs[:DateCreated], '%m/%d/%Y %l:%M %p').utc unless @attrs[:DateCreated].nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
# Time when object was last modified on TeamSupport
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# teamsupport_object = Teamsupport::Creatable.new(DateModified: '4/4/2015 10:00 AM')
|
22
|
+
# teamsupport_object.DateModified
|
23
|
+
#
|
24
|
+
# @return [Time]
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
def DateModified # rubocop:disable Style/MethodName
|
28
|
+
Time.strptime(@attrs[:DateModified], '%m/%d/%Y %l:%M %p').utc unless @attrs[:DateModified].nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'teamsupport/base'
|
2
|
+
require 'teamsupport/creatable'
|
3
|
+
require 'teamsupport/identity'
|
4
|
+
|
5
|
+
module Teamsupport
|
6
|
+
class Customer < Teamsupport::Identity
|
7
|
+
include Teamsupport::Creatable
|
8
|
+
|
9
|
+
# @return [Integer]
|
10
|
+
attr_reader :ID, :PrimaryUserID, :CreatorID, :ModifierID, :SlaLevelID, :DefaultSupportGroupID, :DefaultSupportUserID, :SupportHoursMonth, :SupportHoursUsed, :SupportHoursRemaining
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :Name, :Description, :Website, :InActiveReason, :PrimaryContact, :Domains, :CreatedBy, :LastModifiedBy, :SlaName, :CRMLinkId, :DefaultWikiArticle, :DefaultSupportGroup, :DefaultSupportUser
|
13
|
+
|
14
|
+
# Boolean indicating whether a Customer is active on Teamsupport
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# teamsupport_customer = Teamsupport::Customer.new(IsActive: true)
|
18
|
+
# teamsupport_customer.IsActive
|
19
|
+
#
|
20
|
+
# @return [Boolean]
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
def IsActive # rubocop:disable Style/MethodName
|
24
|
+
@attrs[:IsActive] == 'True' ? true : false
|
25
|
+
end
|
26
|
+
|
27
|
+
# Boolean indicating whether a Customer has portal access on Teamsupport
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# teamsupport_customer = Teamsupport::Customer.new(HasPortalAccess: true)
|
31
|
+
# teamsupport_customer.HasPortalAccess
|
32
|
+
#
|
33
|
+
# @return [Boolean]
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def HasPortalAccess # rubocop:disable Style/MethodName
|
37
|
+
@attrs[:HasPortalAccess] == 'True' ? true : false
|
38
|
+
end
|
39
|
+
|
40
|
+
# Boolean indicating whether a Customer needs indexing on Teamsupport
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# teamsupport_customer = Teamsupport::Customer.new(NeedsIndexing: true)
|
44
|
+
# teamsupport_customer.NeedsIndexing
|
45
|
+
#
|
46
|
+
# @return [Boolean]
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
def NeedsIndexing # rubocop:disable Style/MethodName
|
50
|
+
@attrs[:NeedsIndexing] == 'True' ? true : false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Time when the Customer's Service Agreement expires on Teamsupport
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# teamsupport_customer = Teamsupport::Customer.new(SAExpirationDate: '4/4/2015 10:15 AM')
|
57
|
+
# teamsupport_customer.SAExpirationDate
|
58
|
+
#
|
59
|
+
# @return [Time]
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
def SAExpirationDate # rubocop:disable Style/MethodName
|
63
|
+
Time.strptime(@attrs[:SAExpirationDate], '%m/%d/%Y %l:%M %p').utc unless @attrs[:SAExpirationDate].nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'teamsupport/base'
|
2
|
+
require 'teamsupport/creatable'
|
3
|
+
require 'teamsupport/product'
|
4
|
+
|
5
|
+
module Teamsupport
|
6
|
+
class CustomerProduct < Teamsupport::Product
|
7
|
+
include Teamsupport::Creatable
|
8
|
+
|
9
|
+
# @return [Integer]
|
10
|
+
attr_reader :ID, :CreatorID, :ModifierID, :OrganizationID, :ProductID
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :Name, :Description
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Teamsupport
|
2
|
+
# Custom error class for rescuing from all Teamsupport errors
|
3
|
+
class Error < StandardError
|
4
|
+
# Provide a code method for reading HTTP status code from Error
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# teamsupport_error = Teamsupport::Error.new(code: 404)
|
8
|
+
# teamsupport_error.code
|
9
|
+
#
|
10
|
+
# @return [Integer]
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
attr_reader :code
|
14
|
+
|
15
|
+
# Raised when Teamsupport returns a 4xx HTTP status code
|
16
|
+
ClientError = Class.new(self)
|
17
|
+
|
18
|
+
# Raised when Teamsupport returns the HTTP status code 400
|
19
|
+
BadRequest = Class.new(ClientError)
|
20
|
+
|
21
|
+
# Raised when Teamsupport returns the HTTP status code 401
|
22
|
+
Unauthorized = Class.new(ClientError)
|
23
|
+
|
24
|
+
# Raised when Teamsupport returns the HTTP status code 403
|
25
|
+
Forbidden = Class.new(ClientError)
|
26
|
+
|
27
|
+
# Raised when Teamsupport returns the HTTP status code 404
|
28
|
+
NotFound = Class.new(ClientError)
|
29
|
+
|
30
|
+
# Raised when Teamsupport returns the HTTP status code 406
|
31
|
+
NotAcceptable = Class.new(ClientError)
|
32
|
+
|
33
|
+
# Raised when Teamsupport returns the HTTP status code 422
|
34
|
+
UnprocessableEntity = Class.new(ClientError)
|
35
|
+
|
36
|
+
# Raised when Teamsupport returns the HTTP status code 429
|
37
|
+
TooManyRequests = Class.new(ClientError)
|
38
|
+
|
39
|
+
# Raised when Teamsupport returns a 5xx HTTP status code
|
40
|
+
ServerError = Class.new(self)
|
41
|
+
|
42
|
+
# Raised when Teamsupport returns the HTTP status code 500
|
43
|
+
InternalServerError = Class.new(ServerError)
|
44
|
+
|
45
|
+
# Raised when Teamsupport returns the HTTP status code 502
|
46
|
+
BadGateway = Class.new(ServerError)
|
47
|
+
|
48
|
+
# Raised when Teamsupport returns the HTTP status code 503
|
49
|
+
ServiceUnavailable = Class.new(ServerError)
|
50
|
+
|
51
|
+
# Raised when Teamsupport returns the HTTP status code 504
|
52
|
+
GatewayTimeout = Class.new(ServerError)
|
53
|
+
|
54
|
+
ERRORS = {
|
55
|
+
400 => Teamsupport::Error::BadRequest,
|
56
|
+
401 => Teamsupport::Error::Unauthorized,
|
57
|
+
403 => Teamsupport::Error::Forbidden,
|
58
|
+
404 => Teamsupport::Error::NotFound,
|
59
|
+
406 => Teamsupport::Error::NotAcceptable,
|
60
|
+
422 => Teamsupport::Error::UnprocessableEntity,
|
61
|
+
429 => Teamsupport::Error::TooManyRequests,
|
62
|
+
500 => Teamsupport::Error::InternalServerError,
|
63
|
+
502 => Teamsupport::Error::BadGateway,
|
64
|
+
503 => Teamsupport::Error::ServiceUnavailable,
|
65
|
+
504 => Teamsupport::Error::GatewayTimeout,
|
66
|
+
}.freeze
|
67
|
+
|
68
|
+
class << self
|
69
|
+
# Create a new error from an HTTP response
|
70
|
+
#
|
71
|
+
# @example
|
72
|
+
# teamsupport_error = Teamsupport::Error::ERRORS[code]
|
73
|
+
# teamsupport_error.from_response(body, headers) unless klass.nil?
|
74
|
+
#
|
75
|
+
# @param body [String]
|
76
|
+
# @param headers [Hash]
|
77
|
+
#
|
78
|
+
# @return [Teamsupport::Error]
|
79
|
+
#
|
80
|
+
# @api public
|
81
|
+
def from_response(body, _headers)
|
82
|
+
message, code = parse_error(body)
|
83
|
+
new(message, code)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Parses response body for errors
|
89
|
+
#
|
90
|
+
# @param body [String]
|
91
|
+
#
|
92
|
+
# @return [Array, nil]
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
def parse_error(body)
|
96
|
+
if body.nil? || body.empty?
|
97
|
+
['', nil]
|
98
|
+
elsif body[:error]
|
99
|
+
[body[:error], nil]
|
100
|
+
elsif body[:errors]
|
101
|
+
extract_message_from_errors(body)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Extracts error messages from response body
|
106
|
+
#
|
107
|
+
# @param body [String]
|
108
|
+
#
|
109
|
+
# @return [Array]
|
110
|
+
#
|
111
|
+
# @api private
|
112
|
+
def extract_message_from_errors(body)
|
113
|
+
first = Array(body[:errors]).first
|
114
|
+
if first.is_a?(Hash)
|
115
|
+
[first[:message].chomp, first[:code]]
|
116
|
+
else
|
117
|
+
[first.chomp, nil]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Initializes a new Error object
|
123
|
+
#
|
124
|
+
# @param message [Exception, String]
|
125
|
+
# @param code [Integer]
|
126
|
+
#
|
127
|
+
# @return [Teamsupport::Error]
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
def initialize(message = '', code = nil)
|
131
|
+
super(message)
|
132
|
+
@code = code
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Teamsupport
|
5
|
+
class Headers
|
6
|
+
# Initializes a new Headers object
|
7
|
+
#
|
8
|
+
# @param client [Teamsupport::Client]
|
9
|
+
# @param request_method [String]
|
10
|
+
# @param url [String]
|
11
|
+
# @param options [Hash]
|
12
|
+
#
|
13
|
+
# @return [Teamsupport::Headers]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
def initialize(client, request_method, url, options = {})
|
17
|
+
@client = client
|
18
|
+
@request_method = request_method.to_sym
|
19
|
+
@uri = Addressable::URI.parse(url)
|
20
|
+
@options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns HTTP request headers for the client
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# teamsupport_client = Teamsupport::Client.new(api_key: 'AK', api_secret: 'AS')
|
27
|
+
# teamsupport_headers = Teamsupport::Headers.new(teamsupport_client, :get, 'https://app.teamsupport.com')
|
28
|
+
# teamsupport_headers.request_headers
|
29
|
+
#
|
30
|
+
# @return [Hash]
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
def request_headers
|
34
|
+
headers = {'Content-Type' => 'application/json'}
|
35
|
+
headers[:user_agent] = @client.user_agent
|
36
|
+
headers[:authorization] = auth_header
|
37
|
+
headers
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Generates authentication header for TeamSupport API's basic auth
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
def auth_header
|
48
|
+
"Basic #{Base64.strict_encode64("#{@client.api_key}:#{@client.api_secret}")}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'equalizer'
|
2
|
+
require 'teamsupport/base'
|
3
|
+
|
4
|
+
module Teamsupport
|
5
|
+
class Identity < Teamsupport::Base
|
6
|
+
include Equalizer.new(:ID)
|
7
|
+
# @return [Integer]
|
8
|
+
|
9
|
+
# Method for reading the TeamSupport ID of an object
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# teamsupport_object = Teamsupport::Identity.new(ID: 1)
|
13
|
+
# teamsupport_object.ID
|
14
|
+
#
|
15
|
+
# @return [Integer]
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
attr_reader :ID
|
19
|
+
|
20
|
+
# Initializes a new object
|
21
|
+
#
|
22
|
+
# @param attrs [Hash]
|
23
|
+
#
|
24
|
+
# @raise [ArgumentError] Error raised when supplied argument is missing an :ID key.
|
25
|
+
#
|
26
|
+
# @return [Teamsupport::Identity]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
def initialize(attrs = {})
|
30
|
+
# Workaround for dealing with TeamSupport API inconsistently sending ID for objects
|
31
|
+
unless attrs[:ID]
|
32
|
+
attrs[:ID] = attrs.fetch(:OrganizationID) if attrs[:OrganizationID]
|
33
|
+
|
34
|
+
attrs[:ID] = attrs.fetch(:ProductID) if attrs[:ProductID]
|
35
|
+
|
36
|
+
attrs[:ID] = attrs.fetch(:TicketID) if attrs[:TicketID]
|
37
|
+
end
|
38
|
+
|
39
|
+
attrs.fetch(:ID)
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'naught'
|
2
|
+
|
3
|
+
module Teamsupport
|
4
|
+
NullObject = Naught.build do |config|
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
config.black_hole
|
8
|
+
config.define_explicit_conversions
|
9
|
+
config.define_implicit_conversions
|
10
|
+
config.predicates_return false
|
11
|
+
|
12
|
+
def !
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def respond_to?(*)
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def respond_to?(*)
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def instance_of?(klass)
|
25
|
+
raise(TypeError, 'class or module required') unless klass.is_a?(Class)
|
26
|
+
self.class == klass
|
27
|
+
end
|
28
|
+
|
29
|
+
def kind_of?(mod)
|
30
|
+
raise(TypeError, 'class or module required') unless mod.is_a?(Module)
|
31
|
+
self.class.ancestors.include?(mod)
|
32
|
+
end
|
33
|
+
|
34
|
+
alias_method :is_a?, :kind_of?
|
35
|
+
|
36
|
+
def <=>(other)
|
37
|
+
if other.is_a?(self.class)
|
38
|
+
0
|
39
|
+
else
|
40
|
+
-1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def nil?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def as_json(*)
|
49
|
+
'null'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|