zammad_api 0.9.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1430cf67f29761e9852ef05ae2e47dec4b8f6848
4
+ data.tar.gz: 71da04439cbcbcb0fba11d01d3af82336250a78e
5
+ SHA512:
6
+ metadata.gz: 9e141f9947064e2d7995fa458969af5ed35228c985fe56b42538887b1e226267ee371a21de4afaa34a30438717624d8f1a7e8f47aa733c6ddc3eba9f1c349ea2
7
+ data.tar.gz: 48fc482034cc42bdde3636de3c1208ee698e9882b229b6102fd5aa9e6a0aec67d83a4fd11ba16527743a902b519b44a33b15800661fcb29eabbea1eccf5e5e54
@@ -0,0 +1,53 @@
1
+ require 'zammad_api/log'
2
+ require 'zammad_api/transport'
3
+ require 'zammad_api/dispatcher'
4
+ require 'zammad_api/resources'
5
+
6
+ module ZammadAPI
7
+
8
+ class Client
9
+
10
+ def initialize(config)
11
+ @config = config
12
+ @logger = ZammadAPI::Log.new(@config)
13
+ @transport = ZammadAPI::Transport.new(@config, @logger)
14
+ check_config
15
+ end
16
+
17
+ def method_missing(method, *_args)
18
+ method = modulize( method.to_s )
19
+ class_name = "ZammadAPI::Resources::#{method}"
20
+ begin
21
+ class_object = Kernel.const_get(class_name)
22
+ rescue
23
+ raise "Resource for #{method} does not exist"
24
+ end
25
+ ZammadAPI::Dispatcher.new(@transport, class_object)
26
+ end
27
+
28
+ private
29
+
30
+ def check_config
31
+ raise 'missing url in config' if !@config[:url]
32
+ raise 'config url needs to start with http:// or https://' if @config[:url] !~ %r{^(http|https)://}
33
+
34
+ # check for token auth
35
+ return if @config[:http_token] && !@config[:http_token].empty?
36
+
37
+ if !@config[:user] || @config[:user].empty?
38
+ raise 'missing user in config'
39
+ end
40
+
41
+ return if @config[:password] && !@config[:password].empty?
42
+
43
+ raise 'missing password in config'
44
+ end
45
+
46
+ def modulize(string)
47
+ string.gsub(/__(.?)/) { "::#{$1.upcase}" }
48
+ .gsub(%r{/(.?)}) { "::#{$1.upcase}" }
49
+ .gsub(/(?:_+|-+)([a-z])/) { $1.upcase }
50
+ .gsub(/(\A|\s)([a-z])/) { $1 + $2.upcase }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,13 @@
1
+ module ZammadAPI
2
+ class Dispatcher
3
+
4
+ def initialize(transport, resource)
5
+ @transport = transport
6
+ @resource = resource
7
+ end
8
+
9
+ def method_missing(method, *args)
10
+ @resource.send(method, @transport, args[0])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ require 'zammad_api/list_base'
2
+
3
+ module ZammadAPI
4
+ class ListAll < ListBase
5
+
6
+ private
7
+
8
+ def perform_request(parameter)
9
+ request('all', @url, parameter)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,85 @@
1
+ module ZammadAPI
2
+ class ListBase
3
+
4
+ def initialize(resource, transport, parameter = {})
5
+ @resource = resource
6
+ @url = @resource.get_url
7
+ @transport = transport
8
+ @parameter = {
9
+ page: 1,
10
+ per_page: 10,
11
+ expand: 'true',
12
+ }.merge(parameter)
13
+ end
14
+
15
+ def [](position)
16
+
17
+ local_parameter = @parameter.merge(
18
+ page: position + 1,
19
+ per_page: 1
20
+ )
21
+ perform_request(local_parameter)[0]
22
+ end
23
+
24
+ def page(page, per_page, &block)
25
+
26
+ @parameter[:page] = page
27
+ @parameter[:per_page] = per_page
28
+ fetch_and_yield_each(&block)
29
+ end
30
+
31
+ def page_next(&block)
32
+ @parameter[:page] += 1
33
+ fetch_and_yield_each(&block)
34
+ end
35
+
36
+ def page_prev(&block)
37
+ @parameter[:page] -= 1
38
+ fetch_and_yield_each(&block)
39
+ end
40
+
41
+ def each(&block)
42
+ fetch_and_yield_each(&block)
43
+ end
44
+
45
+ private
46
+
47
+ def fetch_and_yield_each
48
+ result = perform_request(@parameter)
49
+ result.each { |item|
50
+ yield item
51
+ }
52
+ end
53
+
54
+ def request(request, url, parameter)
55
+
56
+ # convert parameters into a GET query
57
+ url += '?' + parameter.map { |key, value|
58
+
59
+ if !value.is_a? String
60
+ value = value.to_s
61
+ end
62
+
63
+ "#{key}=#{CGI.escape value}"
64
+ }.join('&')
65
+
66
+ response = @transport.get(url: url)
67
+ data = JSON.parse(response.body)
68
+ if response.status != 200
69
+ raise "Can't get .#{request} of object (#{@resource.class.name}): #{data['error']}"
70
+ end
71
+
72
+ list = []
73
+ data.each { |local_data|
74
+ item = @resource.new(@transport, local_data)
75
+ item.new_instance = false
76
+ list.push item
77
+ }
78
+ list
79
+ end
80
+
81
+ def perform_request(_parameter)
82
+ raise "no perform_request implementation for #{self.class.name} found"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,12 @@
1
+ require 'zammad_api/list_base'
2
+
3
+ module ZammadAPI
4
+ class ListSearch < ListBase
5
+
6
+ private
7
+
8
+ def perform_request(parameter)
9
+ request('search', "#{@url}/search", parameter)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ module ZammadAPI
2
+ class Log
3
+
4
+ def initialize(config)
5
+ return if !config[:logger]
6
+ require 'logger'
7
+ @logger = Logger.new($stderr)
8
+ #@logger.level = Logger::WARN
9
+ @logger.level = Logger::DEBUG
10
+ end
11
+
12
+ def method_missing(method, *args)
13
+ return if !@logger
14
+ @logger.send(method, args)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,130 @@
1
+ require 'cgi'
2
+ require 'json'
3
+ require 'zammad_api/transport'
4
+
5
+ module ZammadAPI
6
+ module Resources
7
+ class Base
8
+ attr_accessor :new_instance, :url, :attributes
9
+ attr_reader :changes
10
+
11
+ def initialize(transport, attributes = {})
12
+ @new_instance = true
13
+ @transport = transport
14
+ @changes = {}
15
+ @url = self.class.get_url
16
+
17
+ if attributes.nil?
18
+ attributes = {}
19
+ end
20
+ @attributes = attributes
21
+ symbolize_keys_deep!(@attributes)
22
+ end
23
+
24
+ def method_missing(method, *args)
25
+ if method.to_s[-1, 1] == '='
26
+ method = method.to_s[0, method.length - 1].to_sym
27
+ @changes[method] = [@attributes[method], args[0]]
28
+ @attributes[method] = args[0]
29
+ end
30
+ @attributes[method]
31
+ end
32
+
33
+ def new_record?
34
+ @new_instance
35
+ end
36
+
37
+ def changed?
38
+ return false if @changes.empty?
39
+ true
40
+ end
41
+
42
+ def destroy
43
+ response = @transport.delete(url: "#{@url}/#{@attributes[:id]}")
44
+ if response.body.to_s != '' && response.body.to_s != ' '
45
+ data = JSON.parse(response.body)
46
+ end
47
+ if response.status != 200
48
+ raise "Can't destroy object (#{self.class.name}): #{data['error']}"
49
+ end
50
+ true
51
+ end
52
+
53
+ def save
54
+ if @new_instance
55
+ response = @transport.post(url: "#{@url}?expand=true", params: @attributes)
56
+ attributes = JSON.parse(response.body)
57
+ if response.status != 201
58
+ raise "Can't create new object (#{self.class.name}): #{attributes['error']}"
59
+ end
60
+ else
61
+ attributes_to_post = {}
62
+ @changes.each { |name, values|
63
+ attributes_to_post[name] = values[1]
64
+ }
65
+ response = @transport.put(url: "#{@url}/#{@attributes[:id]}?expand=true", params: attributes_to_post)
66
+ attributes = JSON.parse(response.body)
67
+ if response.status != 200
68
+ raise "Can't update new object (#{self.class.name}): #{attributes['error']}"
69
+ end
70
+ end
71
+ symbolize_keys_deep!(attributes)
72
+ attributes.delete(:article)
73
+ @attributes = attributes
74
+ @new_instance = false
75
+ @changes = {}
76
+ true
77
+ end
78
+
79
+ def self.get_url
80
+ @url
81
+ end
82
+
83
+ def self.url(value)
84
+ @url = value
85
+ end
86
+
87
+ def self.all(transport, _)
88
+ ZammadAPI::ListAll.new(self, transport, per_page: 100)
89
+ end
90
+
91
+ def self.search(transport, parameter)
92
+ ZammadAPI::ListSearch.new(self, transport, parameter)
93
+ end
94
+
95
+ def self.find(transport, id)
96
+ response = transport.get(url: "#{@url}/#{id}?expand=true")
97
+ data = JSON.parse(response.body)
98
+ if response.status != 200
99
+ raise "Can't find object (#{self.class.name}): #{data['error']}"
100
+ end
101
+ item = new(transport, data)
102
+ item.new_instance = false
103
+ item
104
+ end
105
+
106
+ def self.create(transport, data)
107
+ item = new(transport, data)
108
+ item.save
109
+ item
110
+ end
111
+
112
+ def self.destroy(transport, id)
113
+ item = find(transport, id)
114
+ item.destroy
115
+ true
116
+ end
117
+
118
+ private
119
+
120
+ def symbolize_keys_deep!(hash)
121
+ hash.keys.each do |key|
122
+ key_symbol = key.respond_to?(:to_sym) ? key.to_sym : key
123
+ hash[key_symbol] = hash.delete key # Preserve order even when key == key_symbol
124
+
125
+ symbolize_keys_deep! hash[key_symbol] if hash[key_symbol].is_a? Hash
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,3 @@
1
+ class ZammadAPI::Resources::Group < ZammadAPI::Resources::Base
2
+ url '/api/v1/groups'
3
+ end
@@ -0,0 +1,3 @@
1
+ class ZammadAPI::Resources::Organization < ZammadAPI::Resources::Base
2
+ url '/api/v1/organizations'
3
+ end
@@ -0,0 +1,26 @@
1
+ class ZammadAPI::Resources::Ticket < ZammadAPI::Resources::Base
2
+ url '/api/v1/tickets'
3
+
4
+ def articles
5
+ response = @transport.get(url: "/api/v1/ticket_articles/by_ticket/#{id}?expand=true")
6
+ data = JSON.parse(response.body)
7
+ if response.status != 200
8
+ raise "Can't get articles (#{self.class.name}): #{data['error']}"
9
+ end
10
+ articles = []
11
+ data.each { |raw|
12
+ item = ZammadAPI::Resources::TicketArticle.new(@transport, raw)
13
+ item.new_instance = false
14
+ articles.push item
15
+ }
16
+ articles
17
+ end
18
+
19
+ def article(data)
20
+ data['ticket_id'] = @attributes[:id]
21
+ item = ZammadAPI::Resources::TicketArticle.new(@transport, data)
22
+ item.save
23
+ item
24
+ end
25
+
26
+ end
@@ -0,0 +1,3 @@
1
+ class ZammadAPI::Resources::TicketArticle < ZammadAPI::Resources::Base
2
+ url '/api/v1/ticket_articles'
3
+ end
@@ -0,0 +1,3 @@
1
+ class ZammadAPI::Resources::TicketPriority < ZammadAPI::Resources::Base
2
+ url '/api/v1/ticket_priorities'
3
+ end
@@ -0,0 +1,3 @@
1
+ class ZammadAPI::Resources::TicketState < ZammadAPI::Resources::Base
2
+ url '/api/v1/ticket_states'
3
+ end
@@ -0,0 +1,3 @@
1
+ class ZammadAPI::Resources::User < ZammadAPI::Resources::Base
2
+ url '/api/v1/users'
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'zammad_api/list_base'
2
+ require 'zammad_api/list_all'
3
+ require 'zammad_api/list_search'
4
+ require 'zammad_api/resources/base'
5
+ require 'zammad_api/resources/user'
6
+ require 'zammad_api/resources/group'
7
+ require 'zammad_api/resources/organization'
8
+ require 'zammad_api/resources/ticket'
9
+ require 'zammad_api/resources/ticket_article'
10
+ require 'zammad_api/resources/ticket_state'
11
+ require 'zammad_api/resources/ticket_priority'
12
+
13
+ module ZammadAPI
14
+ class Resource
15
+ end
16
+ end
@@ -0,0 +1,63 @@
1
+ require 'faraday'
2
+ require 'openssl'
3
+
4
+ module ZammadAPI
5
+ class Transport
6
+
7
+ attr_accessor :url, :user, :password
8
+
9
+ def initialize(config, logger)
10
+ @logger = logger
11
+ @logger.debug "Transport to #{config[:url]} with #{config[:user]}:#{config[:password]}"
12
+ @conn = Faraday.new(url: config[:url]) do |faraday|
13
+ #faraday.request :url_encoded # form-encode POST params
14
+ #faraday.response :logger # log requests to STDOUT
15
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
16
+ end
17
+ @conn.headers[:user_agent] = 'Zammad API Ruby'
18
+ if config[:http_token] && !config[:http_token].empty?
19
+ @conn.token_auth(config[:http_token])
20
+ else
21
+ @conn.basic_auth(config[:user], config[:password])
22
+ end
23
+ end
24
+
25
+ def get(param)
26
+ @logger.debug "GET: #{@url}#{param[:url]}"
27
+ response = @conn.get param[:url]
28
+ response
29
+ end
30
+
31
+ def post(param)
32
+ @logger.debug "POST: #{@url}#{param[:url]}"
33
+ @logger.debug "Params: #{param[:params].inspect}"
34
+ response = @conn.post do |req|
35
+ req.url param[:url]
36
+ req.headers['Content-Type'] = 'application/json'
37
+ req.body = param[:params].to_json
38
+ end
39
+ @logger.debug "Response: #{response.body}"
40
+ response
41
+ end
42
+
43
+ def put(param)
44
+ @logger.debug "PUT: #{@url}#{param[:url]}"
45
+ @logger.debug "Params: #{param[:params].inspect}"
46
+ response = @conn.put do |req|
47
+ req.url param[:url]
48
+ req.headers['Content-Type'] = 'application/json'
49
+ req.body = param[:params].to_json
50
+ end
51
+ @logger.debug "Response: #{response.body}"
52
+ response
53
+ end
54
+
55
+ def delete(param)
56
+ @logger.debug "DELETE: #{@url}#{param[:url]}"
57
+ response = @conn.delete param[:url]
58
+ @logger.debug "Response: #{response.body}"
59
+ response
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module ZammadAPI
2
+ VERSION = '0.9.1'.freeze
3
+ end
data/lib/zammad_api.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'zammad_api/version'
2
+ require 'zammad_api/client'
3
+
4
+ module ZammadAPI
5
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zammad_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - Martin Edenhofer
8
+ - Thorsten Eckel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-10-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.9'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.9'
28
+ - !ruby/object:Gem::Dependency
29
+ name: logger
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.2'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.12'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.12'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '10.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '3.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '3.0'
84
+ description: Ruby wrapper for the Zammad API v1.0.
85
+ email:
86
+ - support@zammad.org
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - lib/zammad_api.rb
92
+ - lib/zammad_api/client.rb
93
+ - lib/zammad_api/dispatcher.rb
94
+ - lib/zammad_api/list_all.rb
95
+ - lib/zammad_api/list_base.rb
96
+ - lib/zammad_api/list_search.rb
97
+ - lib/zammad_api/log.rb
98
+ - lib/zammad_api/resources.rb
99
+ - lib/zammad_api/resources/base.rb
100
+ - lib/zammad_api/resources/group.rb
101
+ - lib/zammad_api/resources/organization.rb
102
+ - lib/zammad_api/resources/ticket.rb
103
+ - lib/zammad_api/resources/ticket_article.rb
104
+ - lib/zammad_api/resources/ticket_priority.rb
105
+ - lib/zammad_api/resources/ticket_state.rb
106
+ - lib/zammad_api/resources/user.rb
107
+ - lib/zammad_api/transport.rb
108
+ - lib/zammad_api/version.rb
109
+ homepage: https://github.com/zammad/zammad_api_client_ruby
110
+ licenses: []
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.4.8
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Zammad API v1.0 client.
132
+ test_files: []