zendesk2 0.0.4 → 0.0.5

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/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ bundler_args: "--without development"
5
+ before_install:
6
+ - gem install bundler --pre
7
+ script: "bundle exec rake --trace"
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in zendesk2.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'rake'
7
+
6
8
  group :test do
7
9
  gem 'guard-rspec'
8
10
  gem 'rspec'
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Zendesk2
2
2
 
3
- TODO: Write a gem description
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
- TODO: Write usage instructions here
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
@@ -1,2 +1,7 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -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
- @path = options[:path] || "api/v2"
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}/#{@path}"
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
- @username = options[:username] || Zendesk2.defaults[:username]
60
- @password = options[:password] || Zendesk2.defaults[:password]
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 @username && @password
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, @username, @password
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, type: :time
11
+ attribute :created_at, type: :time
12
12
  attribute :details
13
- attribute :shared_tickets
14
- attribute :updated_at, type: :time
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, type: :time
7
- attribute :updated_at, type: :time
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, type: :time
24
- attribute :tags, type: :array
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?
@@ -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, type: :time
8
- attribute :updated_at, type: :time
9
- attribute :active, type: :boolean
10
- attribute :verified, type: :boolean
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, type: :time
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", "active", "verified", "locate_id", "time_zone", "phone", "signature", "details", "notes", "role", "custom_role_id", "moderator", "ticket_restriction", "only_private_comments")
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"].to_s == id.to_s}.map{|s| s["organization_id"].to_s}
20
- page(params, :tickets, "/organizations/#{id}/tickets.json", "tickets", filter: lambda{|c| c.select{|u| requesters.include?(u["organization_id"].to_s)}})
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"].to_s == id.to_s}})
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
@@ -10,6 +10,8 @@ class Zendesk2::Client
10
10
  "user" => params
11
11
  },
12
12
  )
13
+ rescue => e
14
+ p e.response
13
15
  end
14
16
  end
15
17
  class Mock
@@ -1,3 +1,3 @@
1
1
  module Zendesk2
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/zendesk2.rb CHANGED
@@ -37,6 +37,8 @@ module Zendesk2
37
37
  def self.stringify_keys(hash)
38
38
  hash.inject({}){|r,(k,v)| r.merge(k.to_s => v)}
39
39
  end
40
- end
41
40
 
42
- Zendesk = Zendesk2
41
+ def self.blank?(string)
42
+ !!string || string == ""
43
+ end
44
+ end
@@ -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" => "1").to_a
21
- second_page = collection.all("per_page" => 1).next_page.to_a
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").to_a
27
- previous_to_second_page = collection.all("per_page" => 1).next_page.previous_page.to_a
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: "Roger Wilco", verified: true} },
8
- lambda { {name: "Rogerito Wilcinzo"} }
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
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-06-19 00:00:00.000000000 Z
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: