jira-ruby 1.7.1 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 280f02562d113b77a58fa5716f9cf9fe39fe6641893d3aecdd250caf4acf7d33
4
- data.tar.gz: f29efc88140a3381b816bcbcec7a977120610470c72b4758bf359353f69eb316
3
+ metadata.gz: 541b1fe24d3e52142ac5d00e028cc7a378e396b7ae4b3fb279959d4d65ceb855
4
+ data.tar.gz: 2800df3cd3d0cf68e55ad789872fd6bc261a1134b44a66c796a48c5d018072a3
5
5
  SHA512:
6
- metadata.gz: '087796061f2ef0472f91c36f64de9550ecb3f7ba6028e8ba91de43b3868e898d7ec4e82733bf31cf336f4a4fd4db9f2f89db320b9ff1db0759c303b6fcbf33ca'
7
- data.tar.gz: b7fff299ec8eac30ff10f00bf36c6c659a6f29b2ab90a6b62e8ce810167ad9188d497a57f29dd389c536a393a2f8aa9897283c24f37b93ed554e8a21140b1e3e
6
+ metadata.gz: 218b645e82b788254576bb925fa2061a5f023484be5100e67622a0072edd03b6dabda04206ea394a06e630cb918f98bb74d39fc2e99245d64c71cc42b160043d
7
+ data.tar.gz: 88d34f8904a0f1954981ca75b2dae6475c2159d373f384b7cba32a2bd7988070cf9b9ba286975882b652d56c5fbab7b36373d8edd5633e6056a903ac54d50838
data/.gitignore CHANGED
@@ -9,3 +9,5 @@ pkg/*
9
9
  .DS_STORE
10
10
  doc
11
11
  .ruby-version
12
+
13
+ .rakeTasks
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3
4
3
  - 2.4
5
- - ruby-head
4
+ - 2.5
5
+ - 2.6
6
+ - 2.7
6
7
  before_script:
7
8
  - rake jira:generate_public_cert
8
9
  script: bundle exec rake spec
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",
@@ -38,6 +38,7 @@ require 'jira/resource/createmeta'
38
38
  require 'jira/resource/webhook'
39
39
  require 'jira/resource/agile'
40
40
  require 'jira/resource/board'
41
+ require 'jira/resource/board_configuration'
41
42
 
42
43
  require 'jira/request_client'
43
44
  require 'jira/oauth_client'
@@ -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)
@@ -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))
@@ -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
- add_cookies(request) if options[:use_cookies]
33
- request.basic_auth(@options[:username], @options[:password]) if @options[:username] && @options[:password]
34
- response = basic_auth_http_conn.request(request)
35
- @authenticated = response.is_a? Net::HTTPOK
36
- store_cookies(response) if options[:use_cookies]
37
- response
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
- uri = URI.parse(@options[:site])
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
 
@@ -8,7 +8,7 @@ module JIRA
8
8
 
9
9
  def initialize(response)
10
10
  @response = response
11
- @message = response.try(:message) || response.try(:body)
11
+ @message = response.try(:message).presence || response.try(:body)
12
12
  end
13
13
  end
14
14
  end
@@ -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
- # When a proxy is enabled, Net::HTTP expects that the request path omits the domain name
7
- path = request_path(http_method, url)
6
+ @http_method = http_method
8
7
 
9
- request = Net::HTTP.const_get(http_method.to_s.capitalize).new(path, headers)
10
- request.body = body unless body.nil?
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
- response = basic_auth_http_conn.request(request)
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
- def request_path(http_method, url)
55
+ attr_reader :http_method
56
+
57
+ def request_path(url)
57
58
  JwtUriBuilder.new(
58
59
  url,
59
60
  http_method.to_s,
@@ -72,29 +72,39 @@ module JIRA
72
72
  @access_token
73
73
  end
74
74
 
75
- def make_request(http_method, path, body = '', headers = {})
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(path)
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
- path = uri.to_s
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, path, headers
90
+ response = access_token.send http_method, url, headers
91
91
  when :post, :put
92
- response = access_token.send http_method, path, body, headers
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
@@ -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
- headers = { 'X-Atlassian-Token' => 'nocheck' }
24
- data = { 'file' => UploadIO.new(attrs['file'], 'application/binary', attrs['file']) }
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
- response = client.request_client.basic_auth_http_conn.request(request)
26
+ headers = { 'X-Atlassian-Token' => 'nocheck' }
27
+ data = { 'file' => UploadIO.new(file, mime_type, file) }
31
28
 
32
- set_attrs(attrs, false)
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
- set_attrs(attachment)
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
@@ -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)