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.
Files changed (39) hide show
  1. data/lib/kayako_client.rb +36 -0
  2. data/lib/kayako_client/base.rb +98 -0
  3. data/lib/kayako_client/department.rb +31 -0
  4. data/lib/kayako_client/http/http.rb +217 -0
  5. data/lib/kayako_client/http/http_backend.rb +31 -0
  6. data/lib/kayako_client/http/http_client.rb +87 -0
  7. data/lib/kayako_client/http/http_response.rb +61 -0
  8. data/lib/kayako_client/http/net_http.rb +109 -0
  9. data/lib/kayako_client/mixins/api.rb +299 -0
  10. data/lib/kayako_client/mixins/attachment.rb +69 -0
  11. data/lib/kayako_client/mixins/authentication.rb +34 -0
  12. data/lib/kayako_client/mixins/client.rb +308 -0
  13. data/lib/kayako_client/mixins/logger.rb +29 -0
  14. data/lib/kayako_client/mixins/object.rb +456 -0
  15. data/lib/kayako_client/mixins/post_client.rb +42 -0
  16. data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
  17. data/lib/kayako_client/mixins/ticket_api.rb +55 -0
  18. data/lib/kayako_client/mixins/ticket_client.rb +135 -0
  19. data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
  20. data/lib/kayako_client/staff.rb +25 -0
  21. data/lib/kayako_client/staff_group.rb +9 -0
  22. data/lib/kayako_client/ticket.rb +241 -0
  23. data/lib/kayako_client/ticket_attachment.rb +42 -0
  24. data/lib/kayako_client/ticket_count.rb +135 -0
  25. data/lib/kayako_client/ticket_custom_field.rb +110 -0
  26. data/lib/kayako_client/ticket_note.rb +105 -0
  27. data/lib/kayako_client/ticket_post.rb +61 -0
  28. data/lib/kayako_client/ticket_priority.rb +24 -0
  29. data/lib/kayako_client/ticket_status.rb +31 -0
  30. data/lib/kayako_client/ticket_time_track.rb +27 -0
  31. data/lib/kayako_client/ticket_type.rb +26 -0
  32. data/lib/kayako_client/user.rb +61 -0
  33. data/lib/kayako_client/user_group.rb +12 -0
  34. data/lib/kayako_client/user_organization.rb +23 -0
  35. data/lib/kayako_client/xml/lib_xml.rb +86 -0
  36. data/lib/kayako_client/xml/rexml_document.rb +77 -0
  37. data/lib/kayako_client/xml/xml.rb +63 -0
  38. data/lib/kayako_client/xml/xml_backend.rb +42 -0
  39. 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