jira-ruby 1.7.1 → 2.1.2
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 +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +3 -2
- data/README.md +3 -3
- data/lib/jira-ruby.rb +1 -0
- data/lib/jira/base.rb +1 -1
- data/lib/jira/client.rb +57 -5
- data/lib/jira/http_client.rb +26 -11
- data/lib/jira/http_error.rb +1 -1
- data/lib/jira/jwt_client.rb +10 -9
- data/lib/jira/oauth_client.rb +15 -5
- data/lib/jira/request_client.rb +15 -3
- data/lib/jira/resource/attachment.rb +19 -14
- data/lib/jira/resource/board.rb +7 -0
- data/lib/jira/resource/board_configuration.rb +9 -0
- data/lib/jira/resource/sprint.rb +12 -8
- data/lib/jira/resource/watcher.rb +7 -0
- data/lib/jira/version.rb +1 -1
- data/spec/integration/watcher_spec.rb +15 -6
- data/spec/jira/base_spec.rb +12 -0
- data/spec/jira/client_spec.rb +9 -0
- data/spec/jira/http_client_spec.rb +130 -6
- data/spec/jira/oauth_client_spec.rb +27 -10
- data/spec/jira/request_client_spec.rb +37 -10
- data/spec/jira/resource/attachment_spec.rb +79 -22
- data/spec/jira/resource/board_spec.rb +49 -0
- data/spec/jira/resource/sprint_spec.rb +23 -11
- metadata +28 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 541b1fe24d3e52142ac5d00e028cc7a378e396b7ae4b3fb279959d4d65ceb855
|
4
|
+
data.tar.gz: 2800df3cd3d0cf68e55ad789872fd6bc261a1134b44a66c796a48c5d018072a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 218b645e82b788254576bb925fa2061a5f023484be5100e67622a0072edd03b6dabda04206ea394a06e630cb918f98bb74d39fc2e99245d64c71cc42b160043d
|
7
|
+
data.tar.gz: 88d34f8904a0f1954981ca75b2dae6475c2159d373f384b7cba32a2bd7988070cf9b9ba286975882b652d56c5fbab7b36373d8edd5633e6056a903ac54d50838
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -163,7 +163,7 @@ api_token = "myApiToken"
|
|
163
163
|
options = {
|
164
164
|
:username => username,
|
165
165
|
:password => api_token,
|
166
|
-
:site => 'http://localhost:8080/', # or 'https://<your_subdomain>.atlassian.net'
|
166
|
+
:site => 'http://localhost:8080/', # or 'https://<your_subdomain>.atlassian.net/'
|
167
167
|
:context_path => '/myjira', # often blank
|
168
168
|
:auth_type => :basic,
|
169
169
|
:read_timeout => 120
|
@@ -307,7 +307,7 @@ class App < Sinatra::Base
|
|
307
307
|
# site uri, and the request token, access token, and authorize paths
|
308
308
|
before do
|
309
309
|
options = {
|
310
|
-
:site => 'http://localhost:2990',
|
310
|
+
:site => 'http://localhost:2990/',
|
311
311
|
:context_path => '/jira',
|
312
312
|
:signature_method => 'RSA-SHA1',
|
313
313
|
:request_token_path => "/plugins/servlet/oauth/request-token",
|
@@ -405,7 +405,7 @@ require 'pp'
|
|
405
405
|
require 'jira-ruby'
|
406
406
|
|
407
407
|
options = {
|
408
|
-
:site => 'http://localhost:2990',
|
408
|
+
:site => 'http://localhost:2990/',
|
409
409
|
:context_path => '/jira',
|
410
410
|
:signature_method => 'RSA-SHA1',
|
411
411
|
:private_key_file => "rsakey.pem",
|
data/lib/jira-ruby.rb
CHANGED
data/lib/jira/base.rb
CHANGED
@@ -424,7 +424,7 @@ module JIRA
|
|
424
424
|
end
|
425
425
|
if @attrs['self']
|
426
426
|
the_url = @attrs['self']
|
427
|
-
the_url = the_url.sub(@client.options[:site], '') if @client.options[:site]
|
427
|
+
the_url = the_url.sub(@client.options[:site].chomp('/'), '') if @client.options[:site]
|
428
428
|
the_url
|
429
429
|
elsif key_value
|
430
430
|
self.class.singular_path(client, key_value.to_s, prefix)
|
data/lib/jira/client.rb
CHANGED
@@ -14,19 +14,29 @@ module JIRA
|
|
14
14
|
# :request_token_path => "/plugins/servlet/oauth/request-token",
|
15
15
|
# :authorize_path => "/plugins/servlet/oauth/authorize",
|
16
16
|
# :access_token_path => "/plugins/servlet/oauth/access-token",
|
17
|
+
# :private_key => nil,
|
17
18
|
# :private_key_file => "rsakey.pem",
|
18
19
|
# :rest_base_path => "/rest/api/2",
|
19
20
|
# :consumer_key => nil,
|
20
21
|
# :consumer_secret => nil,
|
21
22
|
# :ssl_verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
23
|
+
# :ssl_version => nil,
|
22
24
|
# :use_ssl => true,
|
23
25
|
# :username => nil,
|
24
26
|
# :password => nil,
|
25
27
|
# :auth_type => :oauth,
|
26
28
|
# :proxy_address => nil,
|
27
29
|
# :proxy_port => nil,
|
30
|
+
# :proxy_username => nil,
|
31
|
+
# :proxy_password => nil,
|
28
32
|
# :additional_cookies => nil,
|
29
|
-
# :default_headers => {}
|
33
|
+
# :default_headers => {},
|
34
|
+
# :use_client_cert => false,
|
35
|
+
# :read_timeout => nil,
|
36
|
+
# :http_debug => false,
|
37
|
+
# :shared_secret => nil,
|
38
|
+
# :cert_path => nil,
|
39
|
+
# :key_path => nil
|
30
40
|
#
|
31
41
|
# See the JIRA::Base class methods for all of the available methods on these accessor
|
32
42
|
# objects.
|
@@ -45,6 +55,40 @@ module JIRA
|
|
45
55
|
|
46
56
|
def_delegators :@request_client, :init_access_token, :set_access_token, :set_request_token, :request_token, :access_token, :authenticated?
|
47
57
|
|
58
|
+
DEFINED_OPTIONS = [
|
59
|
+
:site,
|
60
|
+
:context_path,
|
61
|
+
:signature_method,
|
62
|
+
:request_token_path,
|
63
|
+
:authorize_path,
|
64
|
+
:access_token_path,
|
65
|
+
:private_key,
|
66
|
+
:private_key_file,
|
67
|
+
:rest_base_path,
|
68
|
+
:consumer_key,
|
69
|
+
:consumer_secret,
|
70
|
+
:ssl_verify_mode,
|
71
|
+
:ssl_version,
|
72
|
+
:use_ssl,
|
73
|
+
:username,
|
74
|
+
:password,
|
75
|
+
:auth_type,
|
76
|
+
:proxy_address,
|
77
|
+
:proxy_port,
|
78
|
+
:proxy_username,
|
79
|
+
:proxy_password,
|
80
|
+
:additional_cookies,
|
81
|
+
:default_headers,
|
82
|
+
:use_client_cert,
|
83
|
+
:read_timeout,
|
84
|
+
:http_debug,
|
85
|
+
:issuer,
|
86
|
+
:base_url,
|
87
|
+
:shared_secret,
|
88
|
+
:cert_path,
|
89
|
+
:key_path
|
90
|
+
].freeze
|
91
|
+
|
48
92
|
DEFAULT_OPTIONS = {
|
49
93
|
site: 'http://localhost:2990',
|
50
94
|
context_path: '/jira',
|
@@ -62,6 +106,9 @@ module JIRA
|
|
62
106
|
@options = options
|
63
107
|
@options[:rest_base_path] = @options[:context_path] + @options[:rest_base_path]
|
64
108
|
|
109
|
+
unknown_options = options.keys.reject { |o| DEFINED_OPTIONS.include?(o) }
|
110
|
+
raise ArgumentError, "Unknown option(s) given: #{unknown_options}" unless unknown_options.empty?
|
111
|
+
|
65
112
|
if options[:use_client_cert]
|
66
113
|
raise ArgumentError, 'Options: :cert_path must be set when :use_client_cert is true' unless @options[:cert_path]
|
67
114
|
raise ArgumentError, 'Options: :key_path must be set when :use_client_cert is true' unless @options[:key_path]
|
@@ -159,6 +206,10 @@ module JIRA
|
|
159
206
|
JIRA::Resource::BoardFactory.new(self)
|
160
207
|
end
|
161
208
|
|
209
|
+
def BoardConfiguration
|
210
|
+
JIRA::Resource::BoardConfigurationFactory.new(self)
|
211
|
+
end
|
212
|
+
|
162
213
|
def RapidView
|
163
214
|
JIRA::Resource::RapidViewFactory.new(self)
|
164
215
|
end
|
@@ -203,10 +254,6 @@ module JIRA
|
|
203
254
|
JIRA::Resource::RemotelinkFactory.new(self)
|
204
255
|
end
|
205
256
|
|
206
|
-
def Sprint
|
207
|
-
JIRA::Resource::SprintFactory.new(self)
|
208
|
-
end
|
209
|
-
|
210
257
|
def Agile
|
211
258
|
JIRA::Resource::AgileFactory.new(self)
|
212
259
|
end
|
@@ -230,6 +277,11 @@ module JIRA
|
|
230
277
|
request(:post, path, body, merge_default_headers(headers))
|
231
278
|
end
|
232
279
|
|
280
|
+
def post_multipart(path, file, headers = {})
|
281
|
+
puts "post multipart: #{path} - [#{file}]" if @http_debug
|
282
|
+
@request_client.request_multipart(path, file, headers)
|
283
|
+
end
|
284
|
+
|
233
285
|
def put(path, body = '', headers = {})
|
234
286
|
headers = { 'Content-Type' => 'application/json' }.merge(headers)
|
235
287
|
request(:put, path, body, merge_default_headers(headers))
|
data/lib/jira/http_client.rb
CHANGED
@@ -6,8 +6,8 @@ require 'uri'
|
|
6
6
|
module JIRA
|
7
7
|
class HttpClient < RequestClient
|
8
8
|
DEFAULT_OPTIONS = {
|
9
|
-
username:
|
10
|
-
password:
|
9
|
+
username: nil,
|
10
|
+
password: nil
|
11
11
|
}.freeze
|
12
12
|
|
13
13
|
attr_reader :options
|
@@ -18,7 +18,7 @@ module JIRA
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def make_cookie_auth_request
|
21
|
-
body = { username: @options[:username], password: @options[:password] }.to_json
|
21
|
+
body = { username: @options[:username].to_s, password: @options[:password].to_s }.to_json
|
22
22
|
@options.delete(:username)
|
23
23
|
@options.delete(:password)
|
24
24
|
make_request(:post, @options[:context_path] + '/rest/auth/1/session', body, 'Content-Type' => 'application/json')
|
@@ -29,12 +29,15 @@ module JIRA
|
|
29
29
|
path = request_path(url)
|
30
30
|
request = Net::HTTP.const_get(http_method.to_s.capitalize).new(path, headers)
|
31
31
|
request.body = body unless body.nil?
|
32
|
-
|
33
|
-
request
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
|
33
|
+
execute_request(request)
|
34
|
+
end
|
35
|
+
|
36
|
+
def make_multipart_request(url, body, headers = {})
|
37
|
+
path = request_path(url)
|
38
|
+
request = Net::HTTP::Post::Multipart.new(path, body, headers)
|
39
|
+
|
40
|
+
execute_request(request)
|
38
41
|
end
|
39
42
|
|
40
43
|
def basic_auth_http_conn
|
@@ -43,7 +46,7 @@ module JIRA
|
|
43
46
|
|
44
47
|
def http_conn(uri)
|
45
48
|
if @options[:proxy_address]
|
46
|
-
http_class = Net::HTTP::Proxy(@options[:proxy_address], @options[:proxy_port] || 80)
|
49
|
+
http_class = Net::HTTP::Proxy(@options[:proxy_address], @options[:proxy_port] || 80, @options[:proxy_username], @options[:proxy_password])
|
47
50
|
else
|
48
51
|
http_class = Net::HTTP
|
49
52
|
end
|
@@ -54,12 +57,13 @@ module JIRA
|
|
54
57
|
http_conn.key = @options[:key]
|
55
58
|
end
|
56
59
|
http_conn.verify_mode = @options[:ssl_verify_mode]
|
60
|
+
http_conn.ssl_version = @options[:ssl_version] if @options[:ssl_version]
|
57
61
|
http_conn.read_timeout = @options[:read_timeout]
|
58
62
|
http_conn
|
59
63
|
end
|
60
64
|
|
61
65
|
def uri
|
62
|
-
|
66
|
+
URI.parse(@options[:site])
|
63
67
|
end
|
64
68
|
|
65
69
|
def authenticated?
|
@@ -68,6 +72,17 @@ module JIRA
|
|
68
72
|
|
69
73
|
private
|
70
74
|
|
75
|
+
def execute_request(request)
|
76
|
+
add_cookies(request) if options[:use_cookies]
|
77
|
+
request.basic_auth(@options[:username], @options[:password]) if @options[:username] && @options[:password]
|
78
|
+
|
79
|
+
response = basic_auth_http_conn.request(request)
|
80
|
+
@authenticated = response.is_a? Net::HTTPOK
|
81
|
+
store_cookies(response) if options[:use_cookies]
|
82
|
+
|
83
|
+
response
|
84
|
+
end
|
85
|
+
|
71
86
|
def request_path(url)
|
72
87
|
parsed_uri = URI(url)
|
73
88
|
|
data/lib/jira/http_error.rb
CHANGED
data/lib/jira/jwt_client.rb
CHANGED
@@ -3,16 +3,15 @@ require 'atlassian/jwt'
|
|
3
3
|
module JIRA
|
4
4
|
class JwtClient < HttpClient
|
5
5
|
def make_request(http_method, url, body = '', headers = {})
|
6
|
-
|
7
|
-
path = request_path(http_method, url)
|
6
|
+
@http_method = http_method
|
8
7
|
|
9
|
-
|
10
|
-
|
8
|
+
super(http_method, url, body, headers)
|
9
|
+
end
|
10
|
+
|
11
|
+
def make_multipart_request(url, data, headers = {})
|
12
|
+
@http_method = :post
|
11
13
|
|
12
|
-
|
13
|
-
@authenticated = response.is_a? Net::HTTPOK
|
14
|
-
store_cookies(response) if options[:use_cookies]
|
15
|
-
response
|
14
|
+
super(url, data, headers)
|
16
15
|
end
|
17
16
|
|
18
17
|
class JwtUriBuilder
|
@@ -53,7 +52,9 @@ module JIRA
|
|
53
52
|
|
54
53
|
private
|
55
54
|
|
56
|
-
|
55
|
+
attr_reader :http_method
|
56
|
+
|
57
|
+
def request_path(url)
|
57
58
|
JwtUriBuilder.new(
|
58
59
|
url,
|
59
60
|
http_method.to_s,
|
data/lib/jira/oauth_client.rb
CHANGED
@@ -72,29 +72,39 @@ module JIRA
|
|
72
72
|
@access_token
|
73
73
|
end
|
74
74
|
|
75
|
-
def make_request(http_method,
|
75
|
+
def make_request(http_method, url, body = '', headers = {})
|
76
76
|
# When using oauth_2legged we need to add an empty oauth_token parameter to every request.
|
77
77
|
if @options[:auth_type] == :oauth_2legged
|
78
78
|
oauth_params_str = 'oauth_token='
|
79
|
-
uri = URI.parse(
|
79
|
+
uri = URI.parse(url)
|
80
80
|
uri.query = if uri.query.to_s == ''
|
81
81
|
oauth_params_str
|
82
82
|
else
|
83
83
|
uri.query + '&' + oauth_params_str
|
84
84
|
end
|
85
|
-
|
85
|
+
url = uri.to_s
|
86
86
|
end
|
87
87
|
|
88
88
|
case http_method
|
89
89
|
when :delete, :get, :head
|
90
|
-
response = access_token.send http_method,
|
90
|
+
response = access_token.send http_method, url, headers
|
91
91
|
when :post, :put
|
92
|
-
response = access_token.send http_method,
|
92
|
+
response = access_token.send http_method, url, body, headers
|
93
93
|
end
|
94
94
|
@authenticated = true
|
95
95
|
response
|
96
96
|
end
|
97
97
|
|
98
|
+
def make_multipart_request(url, data, headers = {})
|
99
|
+
request = Net::HTTP::Post::Multipart.new url, data, headers
|
100
|
+
|
101
|
+
access_token.sign! request
|
102
|
+
|
103
|
+
response = consumer.http.request(request)
|
104
|
+
@authenticated = true
|
105
|
+
response
|
106
|
+
end
|
107
|
+
|
98
108
|
def authenticated?
|
99
109
|
@authenticated
|
100
110
|
end
|
data/lib/jira/request_client.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'oauth'
|
2
2
|
require 'json'
|
3
3
|
require 'net/https'
|
4
|
-
# require 'pry'
|
5
4
|
|
6
5
|
module JIRA
|
7
6
|
class RequestClient
|
@@ -11,9 +10,22 @@ module JIRA
|
|
11
10
|
|
12
11
|
def request(*args)
|
13
12
|
response = make_request(*args)
|
14
|
-
# binding.pry unless response.kind_of?(Net::HTTPSuccess)
|
15
13
|
raise HTTPError, response unless response.is_a?(Net::HTTPSuccess)
|
16
14
|
response
|
17
15
|
end
|
16
|
+
|
17
|
+
def request_multipart(*args)
|
18
|
+
response = make_multipart_request(*args)
|
19
|
+
raise HTTPError, response unless response.is_a?(Net::HTTPSuccess)
|
20
|
+
response
|
21
|
+
end
|
22
|
+
|
23
|
+
def make_request(*args)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_multipart_request(*args)
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
18
30
|
end
|
19
|
-
end
|
31
|
+
end
|
@@ -19,27 +19,32 @@ module JIRA
|
|
19
19
|
parse_json(response.body)
|
20
20
|
end
|
21
21
|
|
22
|
-
def save!(attrs)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
request = Net::HTTP::Post::Multipart.new url, data, headers
|
27
|
-
request.basic_auth(client.request_client.options[:username],
|
28
|
-
client.request_client.options[:password])
|
22
|
+
def save!(attrs, path = url)
|
23
|
+
file = attrs['file'] || attrs[:file] # Keep supporting 'file' parameter as a string for backward compatibility
|
24
|
+
mime_type = attrs[:mimeType] || 'application/binary'
|
29
25
|
|
30
|
-
|
26
|
+
headers = { 'X-Atlassian-Token' => 'nocheck' }
|
27
|
+
data = { 'file' => UploadIO.new(file, mime_type, file) }
|
31
28
|
|
32
|
-
|
33
|
-
unless response.body.nil? || response.body.length < 2
|
34
|
-
json = self.class.parse_json(response.body)
|
35
|
-
attachment = json[0]
|
29
|
+
response = client.post_multipart(path, data , headers)
|
36
30
|
|
37
|
-
|
38
|
-
end
|
31
|
+
set_attributes(attrs, response)
|
39
32
|
|
40
33
|
@expanded = false
|
41
34
|
true
|
42
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def set_attributes(attributes, response)
|
40
|
+
set_attrs(attributes, false)
|
41
|
+
return if response.body.nil? || response.body.length < 2
|
42
|
+
|
43
|
+
json = self.class.parse_json(response.body)
|
44
|
+
attachment = json[0]
|
45
|
+
|
46
|
+
set_attrs(attachment)
|
47
|
+
end
|
43
48
|
end
|
44
49
|
end
|
45
50
|
end
|
data/lib/jira/resource/board.rb
CHANGED
@@ -46,6 +46,13 @@ module JIRA
|
|
46
46
|
results.map { |issue| client.Issue.build(issue) }
|
47
47
|
end
|
48
48
|
|
49
|
+
def configuration(params = {})
|
50
|
+
path = path_base(client) + "/board/#{id}/configuration"
|
51
|
+
response = client.get(url_with_query_params(path, params))
|
52
|
+
json = self.class.parse_json(response.body)
|
53
|
+
client.BoardConfiguration.build(json)
|
54
|
+
end
|
55
|
+
|
49
56
|
# options
|
50
57
|
# - state ~ future, active, closed, you can define multiple states separated by commas, e.g. state=active,closed
|
51
58
|
# - maxResults ~ default: 50 (JIRA API), 1000 (this library)
|