HelpDeskAPI 1.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +72 -0
- data/helpdeskapi.gemspec +11 -0
- data/lib/helpdeskapi.rb +68 -0
- data/lib/helpdeskapi/authentication.rb +54 -0
- data/lib/helpdeskapi/comment.rb +56 -0
- data/lib/helpdeskapi/comments.rb +10 -0
- data/lib/helpdeskapi/endpoints.rb +19 -0
- data/lib/helpdeskapi/exceptions.rb +11 -0
- data/lib/helpdeskapi/organization.rb +37 -0
- data/lib/helpdeskapi/organizations.rb +12 -0
- data/lib/helpdeskapi/request.rb +40 -0
- data/lib/helpdeskapi/ticket.rb +92 -0
- data/lib/helpdeskapi/tickets.rb +42 -0
- data/lib/helpdeskapi/user.rb +78 -0
- data/lib/helpdeskapi/users.rb +17 -0
- data/lib/helpdeskapi/utilities.rb +23 -0
- data/test/test_ticket.rb +64 -0
- metadata +61 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f17405bcdc7beb2c54da528e9ee8d13f6698b20a
|
4
|
+
data.tar.gz: 3de324b2dc16290b3e2669d7985913df8fbd2c04
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 951db8336563881cb0b0828c2f3c844e13608bd52bcf91895f6d808a92a5833cd2f8f14e35c215e8fdd78ace48d2ff7e11849b05ff1724ba389d2f0dcf3bd880
|
7
|
+
data.tar.gz: 52617eae9e72af8da7808b24d5bfff30bcb68ec4b26c7556d746866b2bc10d2f1732d8cdba2c9c7750f15dc3c61dd5a14f08bb4ee81e21bcd82f3b36c7b387c0
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Chase L Engel
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
Ruby library for Spiceworks Help Desk.
|
2
|
+
|
3
|
+
Currently only basic actions have been implemented.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
```
|
7
|
+
$ gem build helpdeskapi.gemspec
|
8
|
+
$ gem install ./HelpDeskAPI-1.0.0.gem
|
9
|
+
```
|
10
|
+
|
11
|
+
Note: Some actions require administrator user
|
12
|
+
### Signing in
|
13
|
+
```
|
14
|
+
HelpDeskAPI::Client.new 'user@example.com', 'password'
|
15
|
+
```
|
16
|
+
### Tickets
|
17
|
+
```
|
18
|
+
# All tickets
|
19
|
+
HelpDeskAPI::Tickets.all
|
20
|
+
|
21
|
+
# Open tickets
|
22
|
+
HelpDeskAPI::Tickets.open
|
23
|
+
|
24
|
+
# Closed tickets
|
25
|
+
HelpDeskAPI::Tickets.closed
|
26
|
+
|
27
|
+
# My tickets
|
28
|
+
HelpDeskAPI::Tickets.my
|
29
|
+
|
30
|
+
# Unassigned tickets
|
31
|
+
HelpDeskAPI::Tickets.unassigned
|
32
|
+
|
33
|
+
# Waiting tickets
|
34
|
+
HelpDeskAPI::Tickets.waiting
|
35
|
+
|
36
|
+
# Past due tickets
|
37
|
+
HelpDeskAPI::Tickets.past_due
|
38
|
+
|
39
|
+
# Search for a ticket
|
40
|
+
HelpDeskAPI::Tickets.search 'Summary'
|
41
|
+
|
42
|
+
# Ticket creation
|
43
|
+
ticket = HelpDeskAPI::Ticket.new 'Summary', 'Description', user.id, HelpDeskAPI::Ticket::Priority::HIGH
|
44
|
+
ticket.submit
|
45
|
+
|
46
|
+
# Delete ticket
|
47
|
+
ticket.delete
|
48
|
+
```
|
49
|
+
### Comments
|
50
|
+
```
|
51
|
+
# Save comment
|
52
|
+
comment = ticket.comment 'This is a comment'
|
53
|
+
comment.save
|
54
|
+
# or
|
55
|
+
comment = HelpDeskAPI::Comment.new ticket.id, 'This is a comment'
|
56
|
+
comment.save
|
57
|
+
|
58
|
+
# Get all comment for a ticket
|
59
|
+
ticket.comments
|
60
|
+
# or
|
61
|
+
HelpDeskAPI::Comments.comments ticket.id
|
62
|
+
```
|
63
|
+
### Users
|
64
|
+
```
|
65
|
+
# Get users (Administrators and Techs)
|
66
|
+
HelpDeskAPI::Users.users
|
67
|
+
```
|
68
|
+
### Organizations
|
69
|
+
```
|
70
|
+
# All organizations
|
71
|
+
HelpDeskAPI::Organizations.organizations
|
72
|
+
```
|
data/helpdeskapi.gemspec
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'HelpDeskAPI'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2017-06-22'
|
5
|
+
s.summary = 'Ruby Library for the Spiceworks Help Desk API'
|
6
|
+
s.authors = ['Chase L Engel']
|
7
|
+
s.email = 'chaselengel@gmail.com'
|
8
|
+
s.files = `git ls-files -z`.split("\0")
|
9
|
+
s.homepage = 'https://github.com/ChaseLEngel/HelpDeskAPI'
|
10
|
+
s.license = 'MIT'
|
11
|
+
end
|
data/lib/helpdeskapi.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + '/helpdeskapi/authentication'
|
6
|
+
require File.dirname(__FILE__) + '/helpdeskapi/ticket'
|
7
|
+
require File.dirname(__FILE__) + '/helpdeskapi/request'
|
8
|
+
require File.dirname(__FILE__) + '/helpdeskapi/tickets'
|
9
|
+
require File.dirname(__FILE__) + '/helpdeskapi/users'
|
10
|
+
require File.dirname(__FILE__) + '/helpdeskapi/organizations'
|
11
|
+
require File.dirname(__FILE__) + '/helpdeskapi/endpoints'
|
12
|
+
require File.dirname(__FILE__) + '/helpdeskapi/exceptions'
|
13
|
+
|
14
|
+
module HelpDeskAPI
|
15
|
+
class Client
|
16
|
+
|
17
|
+
def initialize(username, password)
|
18
|
+
HelpDeskAPI::Authentication.username = username
|
19
|
+
HelpDeskAPI::Authentication.password = password
|
20
|
+
HelpDeskAPI::Authentication.authenticity_token = nil
|
21
|
+
HelpDeskAPI::Authentication.cookies = nil
|
22
|
+
sign_in
|
23
|
+
end
|
24
|
+
|
25
|
+
# Authenicate user and set cookies.
|
26
|
+
# This will be called automatically on endpoint request.
|
27
|
+
def sign_in
|
28
|
+
# Contact sign in page to set cookies.
|
29
|
+
begin
|
30
|
+
sign_in_res = RestClient.get(Endpoints::SIGN_IN)
|
31
|
+
rescue RestClient::ExceptionWithResponse => error
|
32
|
+
fail HelpDeskAPI::Exceptions.SignInError, "Error contacting #{Endpoints::SIGN_IN}: #{error}"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Parse authenticity_token from sign in form.
|
36
|
+
page = Nokogiri::HTML(sign_in_res)
|
37
|
+
HelpDeskAPI::Authentication.authenticity_token = page.css('form').css('input')[1]['value']
|
38
|
+
unless HelpDeskAPI::Authentication.authenticity_token
|
39
|
+
fail HelpDeskAPI::Exceptions.AuthenticityTokenError, 'Error parsing authenticity_token: Token not found.'
|
40
|
+
end
|
41
|
+
# Parse sign_in HTML for csrf-token
|
42
|
+
page.css('meta').each do |tag|
|
43
|
+
HelpDeskAPI::Authentication.csrf_token = tag['content'] if tag['name'] == 'csrf-token'
|
44
|
+
end
|
45
|
+
unless HelpDeskAPI::Authentication.csrf_token
|
46
|
+
fail HelpDeskAPI::Exceptions.CsrfTokenError, 'No csrf-token found'
|
47
|
+
end
|
48
|
+
|
49
|
+
# Set cookies for later requests
|
50
|
+
HelpDeskAPI::Authentication.cookies = sign_in_res.cookies
|
51
|
+
|
52
|
+
# Simulate sign in form submit button.
|
53
|
+
body = {
|
54
|
+
'authenticity_token': HelpDeskAPI::Authentication.authenticity_token,
|
55
|
+
'user[email_address]': HelpDeskAPI::Authentication.username,
|
56
|
+
'user[password]': HelpDeskAPI::Authentication.password
|
57
|
+
}
|
58
|
+
RestClient.post(Endpoints::SESSIONS, body, {:cookies => HelpDeskAPI::Authentication.cookies}) do |response, request, result, &block|
|
59
|
+
# Response should be a 302 redirect from /sessions
|
60
|
+
if Request::responseError?(response)
|
61
|
+
fail HelpDeskAPI::Exceptions.SessionsError, "Error contacting #{Endpoints::SESSIONS}: #{error}"
|
62
|
+
end
|
63
|
+
# Update cookies just incase
|
64
|
+
HelpDeskAPI::Authentication.cookies = response.cookies
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require File.dirname(__FILE__) + '/organizations'
|
3
|
+
|
4
|
+
module HelpDeskAPI
|
5
|
+
module Authentication
|
6
|
+
|
7
|
+
# Pass all function calls to Data singleton.
|
8
|
+
def self.method_missing(m, *args, &block)
|
9
|
+
Data.instance.send(m, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
class Data
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
attr_accessor :username, :password, :authenticity_token, :csrf_token, :cookies
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@username = nil
|
20
|
+
@password = nil
|
21
|
+
@authenticity_token = nil
|
22
|
+
@csrf_token = nil
|
23
|
+
@cookies = nil
|
24
|
+
@organization_id = nil
|
25
|
+
@creator_id = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def signed_in?
|
29
|
+
return !@cookies.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns creator_id for current user from users endpoint
|
33
|
+
def creator_id
|
34
|
+
return @creator_id if @creator_id
|
35
|
+
|
36
|
+
HelpDeskAPI::Users.users.each do |user|
|
37
|
+
if user.email == @username
|
38
|
+
@creator_id = user.id
|
39
|
+
return @creator_id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
fail NoCreatorIdError, "Failed to find creator_id for user: #{@username}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns organization_id or contacts API to get
|
47
|
+
# id of first organization.
|
48
|
+
def organization_id
|
49
|
+
return @organization_id if @organization_id
|
50
|
+
@organization_id = HelpDeskAPI::Organizations.organizations.first.id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module HelpDeskAPI
|
4
|
+
class Comment
|
5
|
+
|
6
|
+
KEYS = [
|
7
|
+
'id',
|
8
|
+
'activity_type',
|
9
|
+
'created_at',
|
10
|
+
'body',
|
11
|
+
'attachment_ids',
|
12
|
+
'ticket',
|
13
|
+
'creator',
|
14
|
+
]
|
15
|
+
|
16
|
+
def initialize(ticket_id = nil, body = nil)
|
17
|
+
@ticket_id = ticket_id
|
18
|
+
@body = body
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(comment_hash)
|
22
|
+
HelpDeskAPI::Utilities.validateHash(comment_hash, KEYS)
|
23
|
+
KEYS.each do |key|
|
24
|
+
instance_variable_set '@'+key, comment_hash[key]
|
25
|
+
self.class.class_eval { attr_accessor key }
|
26
|
+
end
|
27
|
+
return self
|
28
|
+
end
|
29
|
+
|
30
|
+
def save
|
31
|
+
payload = JSON.generate(
|
32
|
+
{
|
33
|
+
comment: {
|
34
|
+
activity_type: 'comment',
|
35
|
+
body: @body,
|
36
|
+
created_at: nil,
|
37
|
+
creator_id: nil,
|
38
|
+
creator_type: nil,
|
39
|
+
ticket_id: @ticket_id
|
40
|
+
},
|
41
|
+
ticket_comment: {
|
42
|
+
activity_type: 'comment',
|
43
|
+
body: @body,
|
44
|
+
created_at: nil,
|
45
|
+
creator_id: nil,
|
46
|
+
creator_type: nil,
|
47
|
+
initial_upload_ids: [],
|
48
|
+
ticket_id: @ticket_id
|
49
|
+
}
|
50
|
+
})
|
51
|
+
headers = {'authenticity_token': HelpDeskAPI::Authentication.authenticity_token, 'X-CSRF-Token': HelpDeskAPI::Authentication.csrf_token, 'Content-Type': 'application/json'}
|
52
|
+
response = HelpDeskAPI::Request.request('POST', Endpoints::TICKETS + "/#{@ticket_id}" + '/comments', payload, headers)
|
53
|
+
parse JSON.parse(response)['comment']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/request'
|
2
|
+
require File.dirname(__FILE__) + '/utilities'
|
3
|
+
|
4
|
+
module HelpDeskAPI
|
5
|
+
module Comments
|
6
|
+
def self.comments(ticket_id)
|
7
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS + "/#{ticket_id}/comments"), 'ticket_comments', Comment
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module HelpDeskAPI
|
2
|
+
module Endpoints
|
3
|
+
URL = 'https://on.spiceworks.com'
|
4
|
+
SIGN_IN = URL + '/sign_in'
|
5
|
+
SESSIONS = URL + '/sessions'
|
6
|
+
|
7
|
+
API_URL = URL + '/api'
|
8
|
+
TICKETS = '/tickets'
|
9
|
+
TICKETS_OPEN = TICKETS + '/open'
|
10
|
+
TICKETS_ALL = TICKETS + '/all'
|
11
|
+
TICKETS_CLOSED = TICKETS + '/closed'
|
12
|
+
TICKETS_MY_TICKETS = TICKETS + '/my'
|
13
|
+
TICKETS_UNASSIGNED = TICKETS + '/unassigned'
|
14
|
+
TICKETS_WAITING = TICKETS + '/waiting'
|
15
|
+
TICKETS_PAST_DUE = TICKETS + '/past_due'
|
16
|
+
USERS = '/users'
|
17
|
+
ORGANIZATIONS = '/organizations'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module HelpDeskAPI
|
2
|
+
module Exceptions
|
3
|
+
SignInError = Class.new(StandardError)
|
4
|
+
AuthenticityTokenError = Class.new(StandardError)
|
5
|
+
CsrfTokenError = Class.new(StandardError)
|
6
|
+
SessionsError = Class.new(StandardError)
|
7
|
+
NoCreatorIdError = Class.new(StandardError)
|
8
|
+
RequestError = Class.new(StandardError)
|
9
|
+
MissingKey = Class.new(StandardError)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/utilities'
|
2
|
+
|
3
|
+
module HelpDeskAPI
|
4
|
+
class Organization
|
5
|
+
|
6
|
+
KEYS = [
|
7
|
+
'id',
|
8
|
+
'name',
|
9
|
+
'host',
|
10
|
+
'links',
|
11
|
+
'domain_whitelist',
|
12
|
+
'email_footer',
|
13
|
+
'email_display_name',
|
14
|
+
'portal_enabled',
|
15
|
+
'ignore_subject',
|
16
|
+
'ignore_body',
|
17
|
+
'ignore_full_text',
|
18
|
+
'notification_settings',
|
19
|
+
'end_user_reopens_ticket',
|
20
|
+
'wants_automatic_assignment',
|
21
|
+
'category_ids',
|
22
|
+
'custom_attribute_ids',
|
23
|
+
'portal_setting_id',
|
24
|
+
'ticket_monitor_ids',
|
25
|
+
'active_directory_setting_id'
|
26
|
+
]
|
27
|
+
|
28
|
+
def parse(organization_hash)
|
29
|
+
HelpDeskAPI::Utilities.validateHash organization_hash, KEYS
|
30
|
+
KEYS.each do |key|
|
31
|
+
instance_variable_set '@'+key, organization_hash[key]
|
32
|
+
self.class.class_eval { attr_accessor key }
|
33
|
+
end
|
34
|
+
return self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/request'
|
2
|
+
require File.dirname(__FILE__) + '/endpoints'
|
3
|
+
require File.dirname(__FILE__) + '/utilities'
|
4
|
+
require File.dirname(__FILE__) + '/organization'
|
5
|
+
|
6
|
+
module HelpDeskAPI
|
7
|
+
module Organizations
|
8
|
+
def self.organizations
|
9
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::ORGANIZATIONS), 'organizations', Organization
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/authentication'
|
4
|
+
require File.dirname(__FILE__) + '/endpoints'
|
5
|
+
require File.dirname(__FILE__) + '/exceptions'
|
6
|
+
|
7
|
+
module HelpDeskAPI
|
8
|
+
module Request
|
9
|
+
@api = RestClient::Resource.new Endpoints::API_URL
|
10
|
+
|
11
|
+
# Contact API given endpoint and return JSON
|
12
|
+
def self.request(method, endpoint, payload = nil, headers = {})
|
13
|
+
headers = headers.merge({:cookies => HelpDeskAPI::Authentication.cookies})
|
14
|
+
endpoint_response = nil
|
15
|
+
|
16
|
+
case method
|
17
|
+
when 'POST'
|
18
|
+
@api[endpoint].post(payload, headers) { |response, _, _, _| endpoint_response = response }
|
19
|
+
when 'GET'
|
20
|
+
endpoint_response = @api[endpoint].get(headers)
|
21
|
+
when 'DELETE'
|
22
|
+
endpoint_response = @api[endpoint].delete(headers)
|
23
|
+
when 'PUT'
|
24
|
+
endpoint_response = @api[endpoint].put(payload, headers)
|
25
|
+
end
|
26
|
+
|
27
|
+
if responseError?(endpoint_response)
|
28
|
+
fail HelpDeskAPI::Exceptions.RequestError, "Error contacting #{endpoint_response.request.url} with HTTP code: #{endpoint_response.code}"
|
29
|
+
end
|
30
|
+
|
31
|
+
return endpoint_response
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns true if response contains HTTP error code.
|
35
|
+
def self.responseError?(response)
|
36
|
+
error_codes = [400, 401, 402, 403, 404, 500, 501, 502, 503]
|
37
|
+
error_codes.include? response.code
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/endpoints'
|
2
|
+
require File.dirname(__FILE__) + '/utilities'
|
3
|
+
require File.dirname(__FILE__) + '/request'
|
4
|
+
require File.dirname(__FILE__) + '/comment'
|
5
|
+
require File.dirname(__FILE__) + '/comments'
|
6
|
+
|
7
|
+
module HelpDeskAPI
|
8
|
+
class Ticket
|
9
|
+
|
10
|
+
module Priority
|
11
|
+
HIGH = '1'
|
12
|
+
MEDIUM = '2'
|
13
|
+
LOW = '3'
|
14
|
+
end
|
15
|
+
|
16
|
+
KEYS = [
|
17
|
+
'id',
|
18
|
+
'created_at',
|
19
|
+
'creator',
|
20
|
+
'description',
|
21
|
+
'due_at',
|
22
|
+
'organization_id',
|
23
|
+
'priority',
|
24
|
+
'status',
|
25
|
+
'summary',
|
26
|
+
'updated_at',
|
27
|
+
'custom_values',
|
28
|
+
'assignee',
|
29
|
+
'ticket_category',
|
30
|
+
]
|
31
|
+
|
32
|
+
def initialize(summary = nil, description = nil, assignee_id = nil, priority = nil)
|
33
|
+
@summary = summary
|
34
|
+
@description = description
|
35
|
+
@assignee_id = assignee_id
|
36
|
+
@priority = priority
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse(ticket_hash)
|
40
|
+
HelpDeskAPI::Utilities.validateHash(ticket_hash, KEYS)
|
41
|
+
KEYS.each do |key|
|
42
|
+
instance_variable_set '@'+key, ticket_hash[key]
|
43
|
+
self.class.class_eval { attr_accessor key }
|
44
|
+
end
|
45
|
+
return self
|
46
|
+
end
|
47
|
+
|
48
|
+
def submit
|
49
|
+
payload = JSON.generate({
|
50
|
+
ticket: {
|
51
|
+
summary: @summary,
|
52
|
+
description: @description,
|
53
|
+
priority: @priority,
|
54
|
+
due_at: nil,
|
55
|
+
updated_at: nil,
|
56
|
+
created_at: nil,
|
57
|
+
organization_id: HelpDeskAPI::Authentication.organization_id,
|
58
|
+
assignee_id: @assignee_id,
|
59
|
+
assignee_type: 'User',
|
60
|
+
creator_id: HelpDeskAPI::Authentication.creator_id,
|
61
|
+
creator_type: 'User',
|
62
|
+
custom_values: [],
|
63
|
+
ticket_category_id: nil,
|
64
|
+
ticket_category_type: nil,
|
65
|
+
watchers: []
|
66
|
+
}
|
67
|
+
})
|
68
|
+
headers = {'authenticity_token': HelpDeskAPI::Authentication.authenticity_token, 'X-CSRF-Token': HelpDeskAPI::Authentication.csrf_token, 'Content-Type': 'application/json'}
|
69
|
+
response = HelpDeskAPI::Request.request('POST', Endpoints::TICKETS, payload, headers)
|
70
|
+
parse JSON.parse(response)['tickets'].first
|
71
|
+
end
|
72
|
+
|
73
|
+
def close
|
74
|
+
end
|
75
|
+
|
76
|
+
def reopen
|
77
|
+
end
|
78
|
+
|
79
|
+
def delete
|
80
|
+
headers = {'authenticity_token': HelpDeskAPI::Authentication.authenticity_token, 'X-CSRF-Token': HelpDeskAPI::Authentication.csrf_token, 'Content-Type': 'application/json'}
|
81
|
+
HelpDeskAPI::Request.request('DELETE', Endpoints::TICKETS + "/#{@id}", nil, headers)
|
82
|
+
end
|
83
|
+
|
84
|
+
def comments
|
85
|
+
HelpDeskAPI::Comments.comments @id
|
86
|
+
end
|
87
|
+
|
88
|
+
def comment(body)
|
89
|
+
HelpDeskAPI::Comment.new @id, body
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/request'
|
2
|
+
require File.dirname(__FILE__) + '/endpoints'
|
3
|
+
require File.dirname(__FILE__) + '/ticket'
|
4
|
+
require File.dirname(__FILE__) + '/utilities'
|
5
|
+
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
module HelpDeskAPI
|
9
|
+
module Tickets
|
10
|
+
def self.search(query)
|
11
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_ALL+"?q=#{URI.escape query}"), 'tickets', Ticket
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.all
|
15
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_ALL), 'tickets', Ticket
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.open
|
19
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_OPEN), 'tickets', Ticket
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.closed
|
23
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_CLOSED), 'tickets', Ticket
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.my
|
27
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_MY_TICKETS), 'tickets', Ticket
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.unassigned
|
31
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_UNASSIGNED), 'ticket', Ticket
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.waiting
|
35
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_WAITING), 'ticket', Ticket
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.past_due
|
39
|
+
HelpDeskAPI::Utilities.parse_response HelpDeskAPI::Request.request('GET', HelpDeskAPI::Endpoints::TICKETS_PAST_DUE), 'ticket', Ticket
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/utilities'
|
2
|
+
require File.dirname(__FILE__) + '/request'
|
3
|
+
require File.dirname(__FILE__) + '/authentication'
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module HelpDeskAPI
|
8
|
+
class User
|
9
|
+
|
10
|
+
module Role
|
11
|
+
ADMIN = 'admin'
|
12
|
+
TECH = 'tech'
|
13
|
+
end
|
14
|
+
|
15
|
+
KEYS = [
|
16
|
+
'id',
|
17
|
+
'first_name',
|
18
|
+
'last_name',
|
19
|
+
'email',
|
20
|
+
'avatar_url',
|
21
|
+
'role',
|
22
|
+
'hourly_rate',
|
23
|
+
'spiceworks_user_id',
|
24
|
+
'wants_alerts',
|
25
|
+
'spiceworks_uid',
|
26
|
+
'system_user',
|
27
|
+
'verified',
|
28
|
+
'archived_user_id'
|
29
|
+
]
|
30
|
+
|
31
|
+
def initialize(first_name = nil, last_name = nil, email = nil, hourly_rate = nil)
|
32
|
+
@first_name = first_name
|
33
|
+
@last_name = last_name
|
34
|
+
@email = email
|
35
|
+
@hourly_rate = hourly_rate
|
36
|
+
end
|
37
|
+
|
38
|
+
def edit(hash)
|
39
|
+
editable = ['first_name', 'last_name', 'email', 'wants_alerts', 'hourly_rate']
|
40
|
+
hash.keep_if { |key, _| editable.include? key.to_s }
|
41
|
+
JSON.generate(
|
42
|
+
{
|
43
|
+
user: {
|
44
|
+
account_id: nil,
|
45
|
+
archived_user_id: @archived_user_id,
|
46
|
+
avatar_url: @avatar_url,
|
47
|
+
deleted: @deleted,
|
48
|
+
email: @email,
|
49
|
+
first_name: @first_name,
|
50
|
+
hourly_rate: @hourly_rate,
|
51
|
+
last_name: @last_name,
|
52
|
+
owned_account_id: nil,
|
53
|
+
role: @role,
|
54
|
+
spiceworks_uid: @spiceworks_uid,
|
55
|
+
spiceworks_user_id: @spiceworks_user_id,
|
56
|
+
system_user: @system_user,
|
57
|
+
verified: @verified,
|
58
|
+
wants_alerts: @wants_alerts
|
59
|
+
}
|
60
|
+
})
|
61
|
+
return # Missing account_id
|
62
|
+
headers = {'authenticity_token': HelpDeskAPI::Authentication.authenticity_token, 'X-CSRF-Token': HelpDeskAPI::Authentication.csrf_token, 'Content-Type': 'application/json'}
|
63
|
+
HelpDeskAPI::Request.request('PUT', Endpoints::USERS + "/#{@id}", payload, headers)
|
64
|
+
end
|
65
|
+
|
66
|
+
def save
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse(user_hash)
|
70
|
+
HelpDeskAPI::Utilities.validateHash(user_hash, KEYS)
|
71
|
+
KEYS.each do |key|
|
72
|
+
instance_variable_set '@'+key, user_hash[key]
|
73
|
+
self.class.class_eval { attr_accessor key }
|
74
|
+
end
|
75
|
+
return self
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/request'
|
2
|
+
require File.dirname(__FILE__) + '/endpoints'
|
3
|
+
require File.dirname(__FILE__) + '/user'
|
4
|
+
require File.dirname(__FILE__) + '/utilities'
|
5
|
+
|
6
|
+
module HelpDeskAPI
|
7
|
+
module Users
|
8
|
+
def self.users
|
9
|
+
HelpDeskAPI::Utilities.parse_response Request::request('GET', HelpDeskAPI::Endpoints::USERS), 'users', User
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def self.parse(hash)
|
14
|
+
hash['users'].map { |user_hash| User.new.parse(user_hash) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/exceptions'
|
4
|
+
|
5
|
+
module HelpDeskAPI
|
6
|
+
module Utilities
|
7
|
+
# Makes sure all keys exist in hash
|
8
|
+
def self.validateHash(hash, keys)
|
9
|
+
keys.each do |key|
|
10
|
+
unless hash.has_key? key
|
11
|
+
fail HelpDeskAPI::Exceptions.MissingKey, "Missing key #{key} in hash:\n#{hash}\n"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Converts response to JSON then creates given object and calls parse
|
17
|
+
# to handle parsing the response JSON
|
18
|
+
def self.parse_response(response, key, obj)
|
19
|
+
hash = JSON.parse response
|
20
|
+
hash[key].map { |object_hash| obj.new.parse(object_hash) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/test_ticket.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
require './lib/helpdeskapi'
|
4
|
+
|
5
|
+
class TestTickets < Minitest::Test
|
6
|
+
|
7
|
+
def setup
|
8
|
+
username = ENV['HELP_DESK_API_USERNAME']
|
9
|
+
password = ENV['HELP_DESK_API_PASSWORD']
|
10
|
+
@user_id = ENV['HELP_DESK_API_USER_ID'].to_s
|
11
|
+
|
12
|
+
if username.nil? || password.nil? || @user_id.nil?
|
13
|
+
puts "HELP_DESK_API_USERNAME or HELP_DESK_API_PASSWORD or HELP_DESK_API_USER_ID undefinded. Exiting."
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
HelpDeskAPI::Client.new username, password
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_ticket_submit
|
21
|
+
time = Time.now.to_i.to_s
|
22
|
+
|
23
|
+
ticket = HelpDeskAPI::Ticket.new time, time, @user_id, HelpDeskAPI::Ticket::Priority::LOW
|
24
|
+
ticket.submit
|
25
|
+
|
26
|
+
tickets = HelpDeskAPI::Tickets.all
|
27
|
+
|
28
|
+
tickets.keep_if { |t| t.summary == time }
|
29
|
+
refute_empty tickets
|
30
|
+
|
31
|
+
assert_equal tickets.first.summary, time
|
32
|
+
assert_equal tickets.first.description, time
|
33
|
+
assert_equal tickets.first.assignee["id"].to_s, @user_id.to_s
|
34
|
+
assert_equal tickets.first.priority, HelpDeskAPI::Ticket::Priority::LOW
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_ticket_comment
|
39
|
+
time = Time.now.to_i.to_s
|
40
|
+
|
41
|
+
tickets = HelpDeskAPI::Tickets.all
|
42
|
+
ticket = tickets.first
|
43
|
+
|
44
|
+
comment = ticket.comment time
|
45
|
+
comment.save
|
46
|
+
|
47
|
+
comments = ticket.comments
|
48
|
+
refute_empty comments
|
49
|
+
|
50
|
+
comments.keep_if { |c| c.body == time }
|
51
|
+
refute_empty comments
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_ticket_delete
|
55
|
+
tickets = HelpDeskAPI::Tickets.all
|
56
|
+
ticket = tickets.first
|
57
|
+
|
58
|
+
ticket.delete
|
59
|
+
|
60
|
+
tickets = HelpDeskAPI::Tickets.all
|
61
|
+
tickets.keep_if { |t| t.id == ticket.id }
|
62
|
+
assert_empty tickets
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: HelpDeskAPI
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chase L Engel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: chaselengel@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- LICENSE.txt
|
20
|
+
- README.md
|
21
|
+
- helpdeskapi.gemspec
|
22
|
+
- lib/helpdeskapi.rb
|
23
|
+
- lib/helpdeskapi/authentication.rb
|
24
|
+
- lib/helpdeskapi/comment.rb
|
25
|
+
- lib/helpdeskapi/comments.rb
|
26
|
+
- lib/helpdeskapi/endpoints.rb
|
27
|
+
- lib/helpdeskapi/exceptions.rb
|
28
|
+
- lib/helpdeskapi/organization.rb
|
29
|
+
- lib/helpdeskapi/organizations.rb
|
30
|
+
- lib/helpdeskapi/request.rb
|
31
|
+
- lib/helpdeskapi/ticket.rb
|
32
|
+
- lib/helpdeskapi/tickets.rb
|
33
|
+
- lib/helpdeskapi/user.rb
|
34
|
+
- lib/helpdeskapi/users.rb
|
35
|
+
- lib/helpdeskapi/utilities.rb
|
36
|
+
- test/test_ticket.rb
|
37
|
+
homepage: https://github.com/ChaseLEngel/HelpDeskAPI
|
38
|
+
licenses:
|
39
|
+
- MIT
|
40
|
+
metadata: {}
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 2.5.1
|
58
|
+
signing_key:
|
59
|
+
specification_version: 4
|
60
|
+
summary: Ruby Library for the Spiceworks Help Desk API
|
61
|
+
test_files: []
|