KayakoClient 0.0.1b
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.
- data/lib/kayako_client.rb +36 -0
- data/lib/kayako_client/base.rb +98 -0
- data/lib/kayako_client/department.rb +31 -0
- data/lib/kayako_client/http/http.rb +217 -0
- data/lib/kayako_client/http/http_backend.rb +31 -0
- data/lib/kayako_client/http/http_client.rb +87 -0
- data/lib/kayako_client/http/http_response.rb +61 -0
- data/lib/kayako_client/http/net_http.rb +109 -0
- data/lib/kayako_client/mixins/api.rb +299 -0
- data/lib/kayako_client/mixins/attachment.rb +69 -0
- data/lib/kayako_client/mixins/authentication.rb +34 -0
- data/lib/kayako_client/mixins/client.rb +308 -0
- data/lib/kayako_client/mixins/logger.rb +29 -0
- data/lib/kayako_client/mixins/object.rb +456 -0
- data/lib/kayako_client/mixins/post_client.rb +42 -0
- data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
- data/lib/kayako_client/mixins/ticket_api.rb +55 -0
- data/lib/kayako_client/mixins/ticket_client.rb +135 -0
- data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
- data/lib/kayako_client/staff.rb +25 -0
- data/lib/kayako_client/staff_group.rb +9 -0
- data/lib/kayako_client/ticket.rb +241 -0
- data/lib/kayako_client/ticket_attachment.rb +42 -0
- data/lib/kayako_client/ticket_count.rb +135 -0
- data/lib/kayako_client/ticket_custom_field.rb +110 -0
- data/lib/kayako_client/ticket_note.rb +105 -0
- data/lib/kayako_client/ticket_post.rb +61 -0
- data/lib/kayako_client/ticket_priority.rb +24 -0
- data/lib/kayako_client/ticket_status.rb +31 -0
- data/lib/kayako_client/ticket_time_track.rb +27 -0
- data/lib/kayako_client/ticket_type.rb +26 -0
- data/lib/kayako_client/user.rb +61 -0
- data/lib/kayako_client/user_group.rb +12 -0
- data/lib/kayako_client/user_organization.rb +23 -0
- data/lib/kayako_client/xml/lib_xml.rb +86 -0
- data/lib/kayako_client/xml/rexml_document.rb +77 -0
- data/lib/kayako_client/xml/xml.rb +63 -0
- data/lib/kayako_client/xml/xml_backend.rb +42 -0
- metadata +105 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module KayakoClient
|
2
|
+
|
3
|
+
class HTTPResponse
|
4
|
+
attr_accessor :status, :body
|
5
|
+
|
6
|
+
def initialize(status, body = '')
|
7
|
+
@status = status
|
8
|
+
@body = body
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
class HTTPOK < HTTPResponse
|
14
|
+
|
15
|
+
def initialize(body = '')
|
16
|
+
super(200, body)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class HTTPBadRequest < HTTPResponse
|
22
|
+
|
23
|
+
def initialize(body = '')
|
24
|
+
super(400, body)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class HTTPUnauthorized < HTTPResponse
|
30
|
+
|
31
|
+
def initialize(body = '')
|
32
|
+
super(401, body)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class HTTPForbidden < HTTPResponse
|
38
|
+
|
39
|
+
def initialize(body = '')
|
40
|
+
super(403, body)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
class HTTPNotFound < HTTPResponse
|
46
|
+
|
47
|
+
def initialize(body = '')
|
48
|
+
super(404, body)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class HTTPNotAllowed < HTTPResponse
|
54
|
+
|
55
|
+
def initialize(body = '')
|
56
|
+
super(405, body)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module KayakoClient
|
4
|
+
class NetHTTP
|
5
|
+
include KayakoClient::Logger
|
6
|
+
include KayakoClient::HTTPBackend
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@client = Net::HTTP::Proxy(options[:host], options[:port], options[:user], options[:pass])
|
10
|
+
@logger = options[:logger] if options[:logger]
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(base, params = {})
|
14
|
+
uri = URI.parse(base)
|
15
|
+
log = params.delete(:logger) || logger
|
16
|
+
@client.use_ssl = true if uri.is_a?(URI::HTTPS)
|
17
|
+
resp = @client.start(uri.host, uri.port) do |request|
|
18
|
+
query = url(uri.path, params)
|
19
|
+
log.debug ":get => #{query}" if log
|
20
|
+
request.get(query)
|
21
|
+
end
|
22
|
+
response(resp)
|
23
|
+
end
|
24
|
+
|
25
|
+
def put(base, params = {})
|
26
|
+
uri = URI.parse(base)
|
27
|
+
e = params.delete(:e)
|
28
|
+
log = params.delete(:logger) || logger
|
29
|
+
@client.use_ssl = true if uri.is_a?(URI::HTTPS)
|
30
|
+
resp = @client.start(uri.host, uri.port) do |request|
|
31
|
+
query = url(uri.path, { :e => e })
|
32
|
+
data = form_data(params)
|
33
|
+
if log
|
34
|
+
log.debug ":put => #{query}"
|
35
|
+
log.debug "PUT Data: #{data}"
|
36
|
+
end
|
37
|
+
request.put(query, data, 'Content-Type' => 'application/x-www-form-urlencoded')
|
38
|
+
end
|
39
|
+
response(resp)
|
40
|
+
end
|
41
|
+
|
42
|
+
def post(base, params = {})
|
43
|
+
uri = URI.parse(base)
|
44
|
+
e = params.delete(:e)
|
45
|
+
log = params.delete(:logger) || logger
|
46
|
+
@client.use_ssl = true if uri.is_a?(URI::HTTPS)
|
47
|
+
resp = @client.start(uri.host, uri.port) do |request|
|
48
|
+
query = url(uri.path, { :e => e })
|
49
|
+
data = form_data(params)
|
50
|
+
if log
|
51
|
+
log.debug ":post => #{query}"
|
52
|
+
log.debug "POST Data: #{data}"
|
53
|
+
end
|
54
|
+
request.post(query, data, 'Content-Type' => 'application/x-www-form-urlencoded')
|
55
|
+
end
|
56
|
+
response(resp)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete(base, params = {})
|
60
|
+
uri = URI.parse(base)
|
61
|
+
log = params.delete(:logger) || logger
|
62
|
+
@client.use_ssl = true if uri.is_a?(URI::HTTPS)
|
63
|
+
resp = @client.start(uri.host, uri.port) do |request|
|
64
|
+
query = url(uri.path, params)
|
65
|
+
log.debug ":delete => #{query}" if log
|
66
|
+
request.delete(query)
|
67
|
+
end
|
68
|
+
response(resp)
|
69
|
+
end
|
70
|
+
|
71
|
+
def response(resp)
|
72
|
+
case resp
|
73
|
+
when Net::HTTPOK
|
74
|
+
KayakoClient::HTTPOK.new(resp.body)
|
75
|
+
when Net::HTTPBadRequest
|
76
|
+
KayakoClient::HTTPBadRequest.new(resp.body)
|
77
|
+
when Net::HTTPUnauthorized
|
78
|
+
KayakoClient::HTTPUnauthorized.new(resp.body)
|
79
|
+
when Net::HTTPForbidden
|
80
|
+
KayakoClient::HTTPForbidden.new(resp.body)
|
81
|
+
when Net::HTTPNotFound
|
82
|
+
KayakoClient::HTTPNotFound.new(resp.body)
|
83
|
+
when Net::HTTPMethodNotAllowed
|
84
|
+
KayakoClient::HTTPNotAllowed.new(resp.body)
|
85
|
+
else
|
86
|
+
KayakoClient::HTTPResponse.new(resp.code, resp.body)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def urlencode(string)
|
93
|
+
URI.escape(string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
94
|
+
end
|
95
|
+
|
96
|
+
def url(base, params = {})
|
97
|
+
base + '?' + params.collect { |name, value| urlencode(name.to_s) + '=' + urlencode(value.to_s) }.join('&')
|
98
|
+
end
|
99
|
+
|
100
|
+
def form_data(params = {})
|
101
|
+
params.collect { |name, value|
|
102
|
+
value.is_a?(Array) ?
|
103
|
+
value.collect { |item| urlencode(name.to_s) + '[]=' + urlencode(item.to_s) } :
|
104
|
+
urlencode(name.to_s) + '=' + urlencode(value.to_s)
|
105
|
+
}.join('&')
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
module KayakoClient
|
2
|
+
module API
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def api_url=(url)
|
9
|
+
@api_url = url
|
10
|
+
end
|
11
|
+
|
12
|
+
def api_url
|
13
|
+
@api_url ||= self.class.api_url
|
14
|
+
end
|
15
|
+
|
16
|
+
def api_key=(key)
|
17
|
+
@api_key = key
|
18
|
+
end
|
19
|
+
|
20
|
+
def api_key
|
21
|
+
@api_key ||= self.class.api_key
|
22
|
+
end
|
23
|
+
|
24
|
+
def secret_key=(secret)
|
25
|
+
@secret_key = secret
|
26
|
+
end
|
27
|
+
|
28
|
+
def secret_key
|
29
|
+
@secret_key ||= self.class.secret_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def put
|
33
|
+
raise NotImplementedError, "method not supported" unless self.class.support?(:put)
|
34
|
+
raise RuntimeError, "client not configured" unless configured?
|
35
|
+
if changed?
|
36
|
+
params = changes.inject({}) do |hash, property|
|
37
|
+
hash[property] = instance_variable_get("@#{property}")
|
38
|
+
hash
|
39
|
+
end
|
40
|
+
require_properties(:put, params)
|
41
|
+
validate(:put, params)
|
42
|
+
check_conditions(params)
|
43
|
+
response = put_request(params)
|
44
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
45
|
+
if logger
|
46
|
+
logger.debug "Response:"
|
47
|
+
logger.debug response.body
|
48
|
+
end
|
49
|
+
payload = xml_backend.new(response.body, { :logger => logger })
|
50
|
+
clean
|
51
|
+
import(payload.to_hash)
|
52
|
+
loaded!
|
53
|
+
logger.info ":put successful for object##{id}" if logger
|
54
|
+
true
|
55
|
+
else
|
56
|
+
unless response.is_a?(Hash)
|
57
|
+
logger.error "Response: #{response.status} #{response.body}" if logger
|
58
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
59
|
+
end
|
60
|
+
false
|
61
|
+
end
|
62
|
+
else
|
63
|
+
logger.warn "nothing to :put" if logger
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
alias_method :update, :put
|
69
|
+
|
70
|
+
def post
|
71
|
+
raise NotImplementedError, "method not supported" unless self.class.support?(:post)
|
72
|
+
raise RuntimeError, "client not configured" unless configured?
|
73
|
+
if id
|
74
|
+
logger.warn "Object has :id - calling :put instead" if logger
|
75
|
+
return put
|
76
|
+
end
|
77
|
+
raise RuntimeError, "object cannot be saved" unless new?
|
78
|
+
params = changes.inject({}) do |hash, property|
|
79
|
+
hash[property] = instance_variable_get("@#{property}")
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
require_properties(:post, params)
|
83
|
+
validate(:post, params)
|
84
|
+
check_conditions(params)
|
85
|
+
response = post_request(params)
|
86
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
87
|
+
if logger
|
88
|
+
logger.debug "Response:"
|
89
|
+
logger.debug response.body
|
90
|
+
end
|
91
|
+
payload = xml_backend.new(response.body, { :logger => logger })
|
92
|
+
clean
|
93
|
+
import(payload.to_hash)
|
94
|
+
loaded!
|
95
|
+
logger.info ":post successful" if logger
|
96
|
+
true
|
97
|
+
else
|
98
|
+
unless response.is_a?(Hash)
|
99
|
+
logger.error "Response: #{response.status} #{response.body}" if logger
|
100
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
101
|
+
end
|
102
|
+
false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
alias_method :save, :post
|
107
|
+
|
108
|
+
def delete
|
109
|
+
raise NotImplementedError, "method not supported" unless self.class.support?(:delete)
|
110
|
+
raise RuntimeError, "client not configured" unless configured?
|
111
|
+
unless new?
|
112
|
+
response = delete_request
|
113
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
114
|
+
logger.info ":delete successful for object##{id}" if logger
|
115
|
+
else
|
116
|
+
logger.error "Response: #{response.status} #{response.body}" if logger
|
117
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
118
|
+
end
|
119
|
+
else
|
120
|
+
logger.warn "cannot delete new object" if logger
|
121
|
+
raise StandardError, "cannot delete new object"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
alias_method :destroy, :delete
|
126
|
+
|
127
|
+
module ClassMethods
|
128
|
+
|
129
|
+
def api_url=(url)
|
130
|
+
@@api_url = url
|
131
|
+
end
|
132
|
+
|
133
|
+
def api_url
|
134
|
+
@@api_url ||= ''
|
135
|
+
end
|
136
|
+
|
137
|
+
def api_key=(key)
|
138
|
+
@@api_key = key
|
139
|
+
end
|
140
|
+
|
141
|
+
def api_key
|
142
|
+
@@api_key ||= ''
|
143
|
+
end
|
144
|
+
|
145
|
+
def secret_key=(secret)
|
146
|
+
@@secret_key = secret
|
147
|
+
end
|
148
|
+
|
149
|
+
def secret_key
|
150
|
+
@@secret_key ||= ''
|
151
|
+
end
|
152
|
+
|
153
|
+
def all(options = {})
|
154
|
+
raise NotImplementedError, "method not supported" unless support?(:all)
|
155
|
+
unless configured? || (options[:api_url] && options[:api_key] && options[:secret_key])
|
156
|
+
raise RuntimeError, "client not configured"
|
157
|
+
end
|
158
|
+
response = get_request(options)
|
159
|
+
log = options[:logger] || logger
|
160
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
161
|
+
objects = []
|
162
|
+
if log
|
163
|
+
log.debug "Response:"
|
164
|
+
log.debug response.body
|
165
|
+
end
|
166
|
+
payload = xml_backend.new(response.body, { :logger => log })
|
167
|
+
payload.each do |element|
|
168
|
+
object = new(payload.to_hash(element).merge(inherited_options(options)))
|
169
|
+
object.loaded!
|
170
|
+
objects << object
|
171
|
+
end
|
172
|
+
log.info ":get(:all) successful (#{objects.size} objects)" if log
|
173
|
+
objects
|
174
|
+
else
|
175
|
+
log.error "Response: #{response.status} #{response.body}" if log
|
176
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def get(*args)
|
181
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
182
|
+
id = args[0]
|
183
|
+
id = :all unless id || options[:id]
|
184
|
+
raise NotImplementedError, "method not supported" unless support?(:get)
|
185
|
+
unless configured? || (options[:api_url] && options[:api_key] && options[:secret_key])
|
186
|
+
raise RuntimeError, "client not configured"
|
187
|
+
end
|
188
|
+
log = options[:logger] || logger
|
189
|
+
if id == :all
|
190
|
+
return all(options)
|
191
|
+
elsif id && id.to_i > 0
|
192
|
+
id = id.to_i
|
193
|
+
elsif options[:id]
|
194
|
+
id = options[:id]
|
195
|
+
else
|
196
|
+
if id
|
197
|
+
log.error "invalid :id - #{id}" if log
|
198
|
+
raise ArgumentError, "invalid ID"
|
199
|
+
else
|
200
|
+
log.error "missing :id" if log
|
201
|
+
raise ArgumentError, "missing ID"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
response = get_request(options.merge(:id => id))
|
205
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
206
|
+
if log
|
207
|
+
log.debug "Response:"
|
208
|
+
log.debug response.body
|
209
|
+
end
|
210
|
+
payload = xml_backend.new(response.body, { :logger => log })
|
211
|
+
params = payload.to_hash
|
212
|
+
unless params.nil?
|
213
|
+
object = new(params.merge(inherited_options(options)))
|
214
|
+
object.loaded!
|
215
|
+
log.info ":get(#{id}) successful" if log
|
216
|
+
object
|
217
|
+
else
|
218
|
+
log.info ":get(#{id}) successful (not found)" if log
|
219
|
+
nil
|
220
|
+
end
|
221
|
+
else
|
222
|
+
log.error "Response: #{response.status} #{response.body}" if log
|
223
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
alias_method :find, :get
|
228
|
+
|
229
|
+
def post(options = {})
|
230
|
+
raise NotImplementedError, "method not supported" unless support?(:post)
|
231
|
+
object = new(options)
|
232
|
+
if object.post
|
233
|
+
object
|
234
|
+
else
|
235
|
+
object.has_errors? ? object.errors : nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
alias_method :create, :post
|
240
|
+
|
241
|
+
def delete(id, options = {})
|
242
|
+
raise NotImplementedError, "method not supported" unless support?(:delete)
|
243
|
+
unless configured? || (options[:api_url] && options[:api_key] && options[:secret_key])
|
244
|
+
raise RuntimeError, "client not configured"
|
245
|
+
end
|
246
|
+
response = delete_request(options.merge(:id => id))
|
247
|
+
log = options[:logger] || logger
|
248
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
249
|
+
log.info ":delete successful for object##{id}" if log
|
250
|
+
true
|
251
|
+
else
|
252
|
+
log.error "Response: #{response.status} #{response.body}" if log
|
253
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
254
|
+
false
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
alias_method :destroy, :delete
|
259
|
+
|
260
|
+
private
|
261
|
+
|
262
|
+
def configured?
|
263
|
+
!api_url.empty? && !api_key.empty? && !secret_key.empty?
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
private
|
269
|
+
|
270
|
+
def configured?
|
271
|
+
!api_url.empty? && !api_key.empty? && !secret_key.empty?
|
272
|
+
end
|
273
|
+
|
274
|
+
def reload!(options = {})
|
275
|
+
raise NotImplementedError, "method not supported" unless self.class.support?(:get)
|
276
|
+
raise RuntimeError, "client not configured" unless configured?
|
277
|
+
raise RuntimeError, "cannot reload modified object" if changed?
|
278
|
+
raise RuntimeError, "object not saved yet" unless id && !new?
|
279
|
+
response = self.class.get_request(options.merge(:id => id))
|
280
|
+
if response.is_a?(KayakoClient::HTTPOK)
|
281
|
+
if logger
|
282
|
+
logger.debug "Response:"
|
283
|
+
logger.debug response.body
|
284
|
+
end
|
285
|
+
payload = xml_backend.new(response.body, { :logger => logger })
|
286
|
+
clean
|
287
|
+
import(payload.to_hash)
|
288
|
+
loaded!
|
289
|
+
logger.info ":get(#{id}) successful" if logger
|
290
|
+
true
|
291
|
+
else
|
292
|
+
logger.error "Response: #{response.status} #{response.body}" if logger
|
293
|
+
raise StandardError, "server returned #{response.status}: #{response.body}"
|
294
|
+
false
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
end
|