zendesk2 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +7 -0
- data/Gemfile +2 -0
- data/README.md +133 -6
- data/Rakefile +5 -0
- data/lib/zendesk2/client.rb +10 -14
- data/lib/zendesk2/models/organization.rb +9 -9
- data/lib/zendesk2/models/ticket.rb +14 -14
- data/lib/zendesk2/models/user.rb +52 -15
- data/lib/zendesk2/paged_collection.rb +4 -3
- data/lib/zendesk2/requests/get_organization_tickets.rb +2 -2
- data/lib/zendesk2/requests/get_organization_users.rb +1 -1
- data/lib/zendesk2/requests/update_user.rb +2 -0
- data/lib/zendesk2/version.rb +1 -1
- data/lib/zendesk2.rb +4 -2
- data/spec/shared/resource.rb +4 -4
- data/spec/users_spec.rb +2 -2
- metadata +3 -3
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Zendesk2
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://secure.travis-ci.org/lanej/zendesk2.png)](http://travis-ci.org/lanej/zendesk2)
|
4
|
+
|
5
|
+
Ruby client for the [Zendesk V2 API](http://developer.zendesk.com/documentation/rest_api/introduction.html) using [cistern](https://github.com/lanej/cistern) and [faraday](https://github.com/technoweenie/faraday)
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -8,17 +10,142 @@ Add this line to your application's Gemfile:
|
|
8
10
|
|
9
11
|
gem 'zendesk2'
|
10
12
|
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
13
|
Or install it yourself as:
|
16
14
|
|
17
15
|
$ gem install zendesk2
|
18
16
|
|
19
17
|
## Usage
|
20
18
|
|
21
|
-
|
19
|
+
### Defaults
|
20
|
+
|
21
|
+
Default credentials will be read in from `~/.zendesk2` file in YAML format.
|
22
|
+
|
23
|
+
---
|
24
|
+
:subdomain: zendeskdev
|
25
|
+
:username: zendeskedge@example.com
|
26
|
+
:password: wickedsecurepassword
|
27
|
+
|
28
|
+
### Creating the client
|
29
|
+
|
30
|
+
Either the absolute url or the subdomain is required. Username and password is always required.
|
31
|
+
|
32
|
+
Zendesk2::Client.new(subdomain: "engineyard", username: "orchestra", password: "gwoo")
|
33
|
+
=> #<Zendesk2::Client::Real:0x007f99da1f9430 @url="https://engineyard.zendesk.com/api/v2", @username="orchestra", @password="gwoo", …>
|
34
|
+
|
35
|
+
or
|
36
|
+
|
37
|
+
=> #<Zendesk2::Client::Real:0x007fd1bae486b0 @url="http://support.cloud.engineyard.com", @username="mate", @password="bambilla", …>
|
38
|
+
|
39
|
+
### Resources
|
40
|
+
|
41
|
+
#### Collections
|
42
|
+
|
43
|
+
Currently support resources
|
44
|
+
|
45
|
+
* User
|
46
|
+
* Ticket
|
47
|
+
* Organization
|
48
|
+
|
49
|
+
All collection are accessed like so:
|
50
|
+
|
51
|
+
client.users.all
|
52
|
+
=> <Zendesk2::Client::Users
|
53
|
+
count=1779,
|
54
|
+
next_page_link="https://dev.zendesk.com/api/v2/users.json?page=2",
|
55
|
+
previous_page_link=nil
|
56
|
+
[
|
57
|
+
<Zendesk2::Client::User
|
58
|
+
id=125394183,
|
59
|
+
url="https://dev.zendesk.com/api/v2/users/125394183.json",
|
60
|
+
...
|
61
|
+
>
|
62
|
+
]
|
63
|
+
|
64
|
+
Collections also respond to `create` and `new`
|
65
|
+
|
66
|
+
client.users.create(email: "ohhai@example.org", name: "lulz")
|
67
|
+
=> <Zendesk2::Client::User
|
68
|
+
id=234020811,
|
69
|
+
...
|
70
|
+
url="https://engineyarddev.zendesk.com/api/v2/users/234020811.json",
|
71
|
+
...
|
72
|
+
email="ohhai@example.org",
|
73
|
+
>
|
74
|
+
|
75
|
+
|
76
|
+
client.users.new(email: "ohhai@example.org")
|
77
|
+
=> <Zendesk2::Client::User
|
78
|
+
id=nil,
|
79
|
+
...
|
80
|
+
url=nil,
|
81
|
+
...
|
82
|
+
email="ohhai@example.org",
|
83
|
+
...
|
84
|
+
>
|
85
|
+
|
86
|
+
#### Paging
|
87
|
+
|
88
|
+
Paged collections respond to `next_page` and `previous_page` when appropriate. `page_size` and `page` can be passed directly to the collection to control size and index.
|
89
|
+
|
90
|
+
page = client.users.all("per_page" => 1, "page" => 4)
|
91
|
+
=> <Zendesk2::Client::Users
|
92
|
+
count=1780,
|
93
|
+
next_page_link="https://dev.zendesk.com/api/v2/users.json?page=5&per_page=1",
|
94
|
+
previous_page_link="https://dev.zendesk.com/api/v2/users.json?page=3&per_page=1"
|
95
|
+
[
|
96
|
+
<Zendesk2::Client::User
|
97
|
+
id=217761652,
|
98
|
+
url="https://dev.zendesk.com/api/v2/users/217761652.json",
|
99
|
+
external_id=nil,
|
100
|
+
name="Guy Dude",
|
101
|
+
...
|
102
|
+
>
|
103
|
+
]
|
104
|
+
|
105
|
+
page.next_page
|
106
|
+
=> <Zendesk2::Client::Users
|
107
|
+
count=1780,
|
108
|
+
next_page_link="https://dev.zendesk.com/api/v2/users.json?page=6&per_page=1",
|
109
|
+
previous_page_link="https://dev.zendesk.com/api/v2/users.json?page=4&per_page=1"
|
110
|
+
[
|
111
|
+
<Zendesk2::Client::User
|
112
|
+
id=217761742,
|
113
|
+
url="https://dev.zendesk.com/api/v2/users/217761742.json",
|
114
|
+
...
|
115
|
+
name="epitaphical osteofibrous",
|
116
|
+
...
|
117
|
+
>
|
118
|
+
]
|
119
|
+
|
120
|
+
page.previous_page
|
121
|
+
=> <Zendesk2::Client::Users
|
122
|
+
count=1780,
|
123
|
+
next_page_link="https://dev.zendesk.com/api/v2/users.json?page=5&per_page=1",
|
124
|
+
previous_page_link="https://dev.zendesk.com/api/v2/users.json?page=3&per_page=1"
|
125
|
+
[
|
126
|
+
<Zendesk2::Client::User
|
127
|
+
id=217761652,
|
128
|
+
url="https://dev.zendesk.com/api/v2/users/217761652.json",
|
129
|
+
...
|
130
|
+
name="Guy Dude",
|
131
|
+
...
|
132
|
+
>
|
133
|
+
]
|
134
|
+
|
135
|
+
#### Models
|
136
|
+
|
137
|
+
All models respond to `destroy` and `save` if applicable. `save` performs a 'create' operation if there is no identity provided or an 'update' if there is an identity.
|
138
|
+
|
139
|
+
Zendesk2::Client::Ticket.new.save # performs a create
|
140
|
+
Zendesk2::Client::Ticket.new(id: 1).save # performs an update
|
141
|
+
|
142
|
+
Attributes can be enumerated by the `attributes` method.
|
143
|
+
|
144
|
+
## Releasing
|
145
|
+
|
146
|
+
|
147
|
+
$ gem install gem-release
|
148
|
+
$ gem bump -trv (major|minor|patch)
|
22
149
|
|
23
150
|
## Contributing
|
24
151
|
|
data/Rakefile
CHANGED
data/lib/zendesk2/client.rb
CHANGED
@@ -29,7 +29,7 @@ class Zendesk2::Client < Cistern::Service
|
|
29
29
|
request :update_ticket
|
30
30
|
request :update_user
|
31
31
|
|
32
|
-
recognizes :url, :subdomain, :host, :port, :path, :scheme, :logger, :adapter
|
32
|
+
recognizes :url, :subdomain, :host, :port, :path, :scheme, :logger, :adapter, :username, :password, :token
|
33
33
|
|
34
34
|
class Real
|
35
35
|
|
@@ -42,28 +42,28 @@ class Zendesk2::Client < Cistern::Service
|
|
42
42
|
|
43
43
|
host ||= "#{subdomain}.zendesk.com"
|
44
44
|
|
45
|
-
|
45
|
+
path = options[:path] || "api/v2"
|
46
46
|
scheme = options[:scheme] || "https"
|
47
47
|
|
48
48
|
port = options[:port] || (scheme == "https" ? 443 : 80)
|
49
49
|
|
50
|
-
"#{scheme}://#{host}:#{port}/#{
|
50
|
+
"#{scheme}://#{host}:#{port}/#{path}"
|
51
51
|
end
|
52
52
|
|
53
|
-
@url = url
|
54
|
-
@path ||= URI.parse(url).path
|
53
|
+
@url = URI.parse(url).to_s
|
55
54
|
|
56
55
|
logger = options[:logger]
|
57
56
|
adapter = options[:adapter] || :net_http
|
58
57
|
connection_options = options[:connection_options] || {ssl: {verify: false}}
|
59
|
-
|
60
|
-
|
58
|
+
username = options[:username] || Zendesk2.defaults[:username]
|
59
|
+
password = options[:password] || Zendesk2.defaults[:password]
|
60
|
+
@token = options[:token]
|
61
61
|
|
62
|
-
raise "Missing required options: [:username, :password]" unless
|
62
|
+
raise "Missing required options: [:username, :password]" unless username && password
|
63
63
|
|
64
64
|
@connection = Faraday.new({url: @url}.merge(connection_options)) do |builder|
|
65
65
|
# response
|
66
|
-
builder.use Faraday::Request::BasicAuthentication,
|
66
|
+
builder.use Faraday::Request::BasicAuthentication, username, password
|
67
67
|
builder.use Faraday::Response::RaiseError
|
68
68
|
builder.use Faraday::Response::Logger, logger if logger
|
69
69
|
builder.response :json
|
@@ -163,13 +163,9 @@ class Zendesk2::Client < Cistern::Service
|
|
163
163
|
|
164
164
|
next_page = if page_index < total_pages
|
165
165
|
url_for("#{path}?page=#{page_index + 1}&per_page=#{page_size}")
|
166
|
-
else
|
167
|
-
nil
|
168
166
|
end
|
169
167
|
previous_page = if page_index > 1
|
170
168
|
url_for("#{path}?page=#{page_index - 1}&per_page=#{page_size}")
|
171
|
-
else
|
172
|
-
nil
|
173
169
|
end
|
174
170
|
|
175
171
|
resource_page = resources.slice(offset, page_size)
|
@@ -201,7 +197,7 @@ class Zendesk2::Client < Cistern::Service
|
|
201
197
|
:url => url,
|
202
198
|
:body => body,
|
203
199
|
:request_headers => {
|
204
|
-
"Content-Type" => "application/json"
|
200
|
+
"Content-Type" => "application/json; charset=utf-8"
|
205
201
|
},
|
206
202
|
)
|
207
203
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
class Zendesk2::Client::Organization < Cistern::Model
|
2
2
|
include Zendesk2::Errors
|
3
|
-
identity :id
|
4
|
-
attribute :shared_comments
|
5
|
-
attribute :notes
|
3
|
+
identity :id, type: :integer
|
4
|
+
attribute :shared_comments, type: :boolean
|
5
|
+
attribute :notes, type: :array
|
6
6
|
attribute :tags
|
7
|
-
attribute :domain_names
|
8
|
-
attribute :group_id
|
9
|
-
attribute :external_id
|
7
|
+
attribute :domain_names, type: :array
|
8
|
+
attribute :group_id, type: :integer
|
9
|
+
attribute :external_id, type: :integer
|
10
10
|
attribute :name
|
11
|
-
attribute :created_at,
|
11
|
+
attribute :created_at, type: :time
|
12
12
|
attribute :details
|
13
|
-
attribute :shared_tickets
|
14
|
-
attribute :updated_at,
|
13
|
+
attribute :shared_tickets, type: :boolean
|
14
|
+
attribute :updated_at, type: :time
|
15
15
|
|
16
16
|
def destroy
|
17
17
|
requires :identity
|
@@ -1,28 +1,28 @@
|
|
1
1
|
class Zendesk2::Client::Ticket < Cistern::Model
|
2
2
|
include Zendesk2::Errors
|
3
|
-
identity :id
|
3
|
+
identity :id, type: :id
|
4
4
|
attribute :external_id
|
5
5
|
attribute :via
|
6
|
-
attribute :created_at,
|
7
|
-
attribute :updated_at,
|
6
|
+
attribute :created_at, type: :time
|
7
|
+
attribute :updated_at, type: :time
|
8
8
|
attribute :type
|
9
9
|
attribute :subject
|
10
10
|
attribute :description
|
11
11
|
attribute :priority
|
12
12
|
attribute :status
|
13
13
|
attribute :recipient
|
14
|
-
attribute :requester_id
|
15
|
-
attribute :submitter_id
|
16
|
-
attribute :assignee_id
|
17
|
-
attribute :organization_id
|
18
|
-
attribute :group_id
|
14
|
+
attribute :requester_id, type: :integer
|
15
|
+
attribute :submitter_id, type: :integer
|
16
|
+
attribute :assignee_id, type: :integer
|
17
|
+
attribute :organization_id, type: :integer
|
18
|
+
attribute :group_id, type: :integer
|
19
19
|
attribute :collaborator_ids, type: :array
|
20
|
-
attribute :forum_topic_id
|
21
|
-
attribute :problem_id
|
22
|
-
attribute :has_incidents
|
23
|
-
attribute :due_at,
|
24
|
-
attribute :tags,
|
25
|
-
attribute :fields
|
20
|
+
attribute :forum_topic_id, type: :integer
|
21
|
+
attribute :problem_id, type: :integer
|
22
|
+
attribute :has_incidents, type: :boolean
|
23
|
+
attribute :due_at, type: :time
|
24
|
+
attribute :tags, type: :array
|
25
|
+
attribute :fields, type: :array
|
26
26
|
|
27
27
|
def save
|
28
28
|
if new_record?
|
data/lib/zendesk2/models/user.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
class Zendesk2::Client::User < Cistern::Model
|
2
|
-
identity :id
|
2
|
+
identity :id, type: :id
|
3
3
|
attribute :url
|
4
4
|
attribute :external_id
|
5
5
|
attribute :name
|
6
6
|
attribute :alias
|
7
|
-
attribute :created_at,
|
8
|
-
attribute :updated_at,
|
9
|
-
attribute :active,
|
10
|
-
attribute :verified,
|
11
|
-
attribute :shared
|
12
|
-
attribute :locale_id
|
7
|
+
attribute :created_at, type: :time
|
8
|
+
attribute :updated_at, type: :time
|
9
|
+
attribute :active, type: :boolean
|
10
|
+
attribute :verified, type: :boolean
|
11
|
+
attribute :shared, type: :boolean
|
12
|
+
attribute :locale_id, type: :integer
|
13
13
|
attribute :locale
|
14
14
|
attribute :time_zone
|
15
|
-
attribute :last_login_at,
|
15
|
+
attribute :last_login_at, type: :time
|
16
16
|
attribute :email
|
17
17
|
attribute :phone
|
18
18
|
attribute :signature
|
19
19
|
attribute :details
|
20
20
|
attribute :notes
|
21
|
-
attribute :organization_id
|
21
|
+
attribute :organization_id, type: :integer
|
22
22
|
attribute :role
|
23
|
-
attribute :custom_role_id
|
24
|
-
attribute :moderator
|
23
|
+
attribute :custom_role_id, type: :integer
|
24
|
+
attribute :moderator, type: :boolean
|
25
25
|
attribute :ticket_restriction
|
26
|
-
attribute :only_private_comments
|
27
|
-
attribute :tags
|
28
|
-
attribute :suspended
|
26
|
+
attribute :only_private_comments, type: :boolean
|
27
|
+
attribute :tags, type: :array
|
28
|
+
attribute :suspended, type: :boolean
|
29
29
|
attribute :photo
|
30
30
|
attribute :authenticity_token
|
31
31
|
|
@@ -53,9 +53,46 @@ class Zendesk2::Client::User < Cistern::Model
|
|
53
53
|
!self.active
|
54
54
|
end
|
55
55
|
|
56
|
+
def organization=(organization)
|
57
|
+
self.organization_id= organization.id
|
58
|
+
end
|
59
|
+
|
60
|
+
def organization
|
61
|
+
self.connection.organizations.get(self.organization_id)
|
62
|
+
end
|
63
|
+
|
64
|
+
def login_url(timestamp, options={})
|
65
|
+
requires :name, :email
|
66
|
+
|
67
|
+
return_to = options[:return_to]
|
68
|
+
token = self.token || options[:token]
|
69
|
+
|
70
|
+
uri = Addressable::URI.parse(self.connection.url)
|
71
|
+
uri.path = "/access/remote"
|
72
|
+
|
73
|
+
raise "timestamp cannot be nil" unless timestamp
|
74
|
+
|
75
|
+
hash_str = "#{self.name}#{self.email}#{token}#{timestamp}"
|
76
|
+
query_values = {
|
77
|
+
'name' => name,
|
78
|
+
'email' => email,
|
79
|
+
'timestamp' => timestamp,
|
80
|
+
'hash' => Digest::MD5.hexdigest(hash_str)
|
81
|
+
}
|
82
|
+
unless Zendesk2.blank?(return_to)
|
83
|
+
query_values['return_to'] = return_to
|
84
|
+
end
|
85
|
+
uri.query_values = query_values
|
86
|
+
|
87
|
+
uri.to_s
|
88
|
+
end
|
89
|
+
|
56
90
|
private
|
57
91
|
|
58
92
|
def params
|
59
|
-
Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), "name", "email", "organization_id", "external_id", "alias", "
|
93
|
+
writable_attributes = Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), "name", "email", "organization_id", "external_id", "alias", "verified", "locate_id", "time_zone", "phone", "signature", "details", "notes", "role", "custom_role_id", "moderator", "ticket_restriction", "only_private_comments")
|
94
|
+
writable_attributes.delete("organization_id") if writable_attributes["organization_id"] == 0
|
95
|
+
writable_attributes.delete("custom_role_id") if writable_attributes["custom_role_id"] == 0
|
96
|
+
writable_attributes
|
60
97
|
end
|
61
98
|
end
|
@@ -14,12 +14,13 @@ module Zendesk2::PagedCollection
|
|
14
14
|
def all(params={})
|
15
15
|
body = connection.send(collection_method, params).body
|
16
16
|
|
17
|
-
load(body[collection_root])
|
18
|
-
merge_attributes(Cistern::Hash.slice(body, "count", "next_page", "previous_page"))
|
17
|
+
collection = self.clone.load(body[collection_root])
|
18
|
+
collection.merge_attributes(Cistern::Hash.slice(body, "count", "next_page", "previous_page"))
|
19
|
+
collection
|
19
20
|
end
|
20
21
|
|
21
22
|
def get(id)
|
22
|
-
if data = connection.send(model_method, {"id" => id}).body[self.model_root]
|
23
|
+
if data = self.connection.send(model_method, {"id" => id}).body[self.model_root]
|
23
24
|
new(data)
|
24
25
|
end
|
25
26
|
end
|
@@ -16,8 +16,8 @@ class Zendesk2::Client
|
|
16
16
|
def get_organization_tickets(params={})
|
17
17
|
id = params["id"]
|
18
18
|
|
19
|
-
requesters = self.data[:users].values.select{|u| u["organization_id"]
|
20
|
-
page(params, :tickets, "/organizations/#{id}/tickets.json", "tickets", filter: lambda{|c| c.select{|u| requesters.include?(u["organization_id"]
|
19
|
+
requesters = self.data[:users].values.select{|u| u["organization_id"] == id}.map{|s| s["organization_id"]}
|
20
|
+
page(params, :tickets, "/organizations/#{id}/tickets.json", "tickets", filter: lambda{|c| c.select{|u| requesters.include?(u["organization_id"])}})
|
21
21
|
end
|
22
22
|
end # Mock
|
23
23
|
end
|
@@ -15,7 +15,7 @@ class Zendesk2::Client
|
|
15
15
|
class Mock
|
16
16
|
def get_organization_users(params={})
|
17
17
|
id = params["id"]
|
18
|
-
page(params, :users, "/organizations/#{id}/users.json", "users", filter: lambda{|c| c.select{|u| u["organization_id"]
|
18
|
+
page(params, :users, "/organizations/#{id}/users.json", "users", filter: lambda{|c| c.select{|u| u["organization_id"] == id}})
|
19
19
|
end
|
20
20
|
end # Mock
|
21
21
|
end
|
data/lib/zendesk2/version.rb
CHANGED
data/lib/zendesk2.rb
CHANGED
data/spec/shared/resource.rb
CHANGED
@@ -17,14 +17,14 @@ shared_examples "a resource" do |_collection, _params, _update_params|
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it "by retrieving the next page" do
|
20
|
-
first_page = collection.all("per_page" =>
|
21
|
-
second_page = collection.all("per_page" => 1).next_page
|
20
|
+
first_page = collection.all("per_page" => 1)
|
21
|
+
second_page = collection.all("per_page" => 1).next_page
|
22
22
|
second_page.should_not == first_page
|
23
23
|
end
|
24
24
|
|
25
25
|
it "by retrieving the previous page" do
|
26
|
-
first_page = collection.all("per_page" => "1")
|
27
|
-
previous_to_second_page = collection.all("per_page" => 1).next_page.previous_page
|
26
|
+
first_page = collection.all("per_page" => "1")
|
27
|
+
previous_to_second_page = collection.all("per_page" => 1).next_page.previous_page
|
28
28
|
previous_to_second_page.should == first_page
|
29
29
|
end
|
30
30
|
end
|
data/spec/users_spec.rb
CHANGED
@@ -4,8 +4,8 @@ describe "users" do
|
|
4
4
|
let(:client) { create_client }
|
5
5
|
it_should_behave_like "a resource",
|
6
6
|
:users,
|
7
|
-
lambda { {email: "zendesk2+#{Zendesk2.uuid}@example.org", name:
|
8
|
-
lambda { {name:
|
7
|
+
lambda { {email: "zendesk2+#{Zendesk2.uuid}@example.org", name: Zendesk2.uuid, verified: true} },
|
8
|
+
lambda { {name: Zendesk2.uuid} }
|
9
9
|
|
10
10
|
it "should get current user" do
|
11
11
|
current_user = client.users.current
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cistern
|
@@ -100,6 +100,7 @@ extra_rdoc_files: []
|
|
100
100
|
files:
|
101
101
|
- .gitignore
|
102
102
|
- .rspec
|
103
|
+
- .travis.yml
|
103
104
|
- Gemfile
|
104
105
|
- Guardfile
|
105
106
|
- LICENSE
|
@@ -172,4 +173,3 @@ test_files:
|
|
172
173
|
- spec/support/client_helper.rb
|
173
174
|
- spec/tickets_spec.rb
|
174
175
|
- spec/users_spec.rb
|
175
|
-
has_rdoc:
|