asana 2.0.0 → 2.0.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/.github/workflows/build.yml +1 -1
- data/.rubocop.yml +38 -3
- data/.ruby-version +1 -1
- data/Appraisals +8 -3
- data/Gemfile +7 -3
- data/Gemfile.lock +54 -64
- data/Guardfile +12 -10
- data/README.md +24 -12
- data/Rakefile +14 -17
- data/VERSION +1 -1
- data/asana.gemspec +20 -18
- data/examples/cli_app.rb +2 -2
- data/examples/events.rb +3 -3
- data/examples/personal_access_token.rb +2 -2
- data/lib/asana/authentication/oauth2/access_token_authentication.rb +4 -1
- data/lib/asana/authentication/oauth2/bearer_token_authentication.rb +3 -2
- data/lib/asana/authentication/oauth2/client.rb +2 -0
- data/lib/asana/authentication/oauth2.rb +6 -4
- data/lib/asana/authentication/token_authentication.rb +3 -1
- data/lib/asana/authentication.rb +2 -0
- data/lib/asana/client/configuration.rb +6 -5
- data/lib/asana/client.rb +13 -11
- data/lib/asana/errors.rb +16 -11
- data/lib/asana/http_client/environment_info.rb +9 -8
- data/lib/asana/http_client/error_handling.rb +23 -24
- data/lib/asana/http_client/response.rb +2 -0
- data/lib/asana/http_client.rb +66 -65
- data/lib/asana/resource_includes/attachment_uploading.rb +6 -6
- data/lib/asana/resource_includes/collection.rb +4 -4
- data/lib/asana/resource_includes/event.rb +2 -0
- data/lib/asana/resource_includes/event_subscription.rb +2 -0
- data/lib/asana/resource_includes/events.rb +4 -1
- data/lib/asana/resource_includes/registry.rb +2 -0
- data/lib/asana/resource_includes/resource.rb +8 -5
- data/lib/asana/resource_includes/response_helper.rb +2 -0
- data/lib/asana/resources/audit_log_api.rb +42 -0
- data/lib/asana/resources/gen/attachments_base.rb +1 -1
- data/lib/asana/resources/gen/audit_log_api_base.rb +1 -1
- data/lib/asana/resources/gen/memberships_base.rb +71 -0
- data/lib/asana/resources/gen/tasks_base.rb +1 -1
- data/lib/asana/resources/goal.rb +54 -0
- data/lib/asana/resources/goal_relationship.rb +32 -0
- data/lib/asana/resources/membership.rb +20 -0
- data/lib/asana/resources/project_brief.rb +30 -0
- data/lib/asana/resources/project_template.rb +36 -0
- data/lib/asana/resources/status_update.rb +54 -0
- data/lib/asana/resources/time_period.rb +30 -0
- data/lib/asana/resources/typeahead.rb +1 -1
- data/lib/asana/resources.rb +4 -4
- data/lib/asana/ruby2_0_0_compatibility.rb +2 -0
- data/lib/asana/version.rb +1 -1
- data/lib/asana.rb +2 -0
- data/samples/memberships_sample.yaml +41 -0
- metadata +57 -46
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Asana
|
2
4
|
module Authentication
|
3
5
|
module OAuth2
|
@@ -24,8 +26,7 @@ module Asana
|
|
24
26
|
#
|
25
27
|
# Returns nothing.
|
26
28
|
def configure(connection)
|
27
|
-
connection.authorization
|
28
|
-
connection.request :oauth2, token_type: 'bearer'
|
29
|
+
connection.request :authorization, 'Bearer', @token
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'oauth2/bearer_token_authentication'
|
2
4
|
require_relative 'oauth2/access_token_authentication'
|
3
5
|
require_relative 'oauth2/client'
|
@@ -31,10 +33,10 @@ module Asana
|
|
31
33
|
client = Client.new(client_id: client_id,
|
32
34
|
client_secret: client_secret,
|
33
35
|
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob')
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
auth_code =
|
36
|
+
$stdout.puts '1. Go to the following URL to authorize the ' \
|
37
|
+
"application: #{client.authorize_url}"
|
38
|
+
$stdout.puts '2. Paste the authorization code here: '
|
39
|
+
auth_code = $stdin.gets.chomp
|
38
40
|
client.token_from_auth_code(auth_code)
|
39
41
|
end
|
40
42
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Asana
|
2
4
|
module Authentication
|
3
5
|
# Public: Represents an API token authentication mechanism.
|
@@ -13,7 +15,7 @@ module Asana
|
|
13
15
|
#
|
14
16
|
# Returns nothing.
|
15
17
|
def configure(connection)
|
16
|
-
connection.
|
18
|
+
connection.request :authorization, :basic, @token, ''
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
data/lib/asana/authentication.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Asana
|
2
4
|
class Client
|
3
5
|
# Internal: Represents a configuration DSL for an Asana::Client.
|
@@ -17,7 +19,7 @@ module Asana
|
|
17
19
|
# Public: Initializes an empty configuration object.
|
18
20
|
def initialize
|
19
21
|
@configuration = {
|
20
|
-
|
22
|
+
log_asana_change_warnings: true
|
21
23
|
}
|
22
24
|
end
|
23
25
|
|
@@ -100,7 +102,6 @@ module Asana
|
|
100
102
|
#
|
101
103
|
# Raises ArgumentError if the OAuth2 configuration arguments are invalid.
|
102
104
|
#
|
103
|
-
# rubocop:disable Metrics/MethodLength
|
104
105
|
def oauth2(value)
|
105
106
|
case value
|
106
107
|
when ::OAuth2::AccessToken
|
@@ -111,8 +112,8 @@ module Asana
|
|
111
112
|
from_bearer_token(value[:bearer_token])
|
112
113
|
else
|
113
114
|
error 'Invalid OAuth2 configuration: pass in either an ' \
|
114
|
-
|
115
|
-
|
115
|
+
'::OAuth2::AccessToken object of your own or a hash ' \
|
116
|
+
'containing :refresh_token or :bearer_token.'
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
@@ -158,7 +159,7 @@ module Asana
|
|
158
159
|
end
|
159
160
|
|
160
161
|
def requiring(hash, *keys)
|
161
|
-
missing_keys = keys.
|
162
|
+
missing_keys = keys.reject { |k| hash.key?(k) }
|
162
163
|
missing_keys.any? && error("Missing keys: #{missing_keys.join(', ')}")
|
163
164
|
keys.map { |k| hash[k] }
|
164
165
|
end
|
data/lib/asana/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'authentication'
|
2
4
|
require_relative 'client/configuration'
|
3
5
|
require_relative 'resources'
|
@@ -59,12 +61,12 @@ module Asana
|
|
59
61
|
@resource = resource
|
60
62
|
end
|
61
63
|
|
62
|
-
def method_missing(
|
63
|
-
@resource.public_send(
|
64
|
+
def method_missing(method_name, *args, **kwargs, &block)
|
65
|
+
@resource.public_send(method_name, *([@client] + args), **kwargs, &block)
|
64
66
|
end
|
65
67
|
|
66
|
-
def respond_to_missing?(
|
67
|
-
@resource.respond_to?(
|
68
|
+
def respond_to_missing?(method_name, *)
|
69
|
+
@resource.respond_to?(method_name)
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
@@ -72,15 +74,15 @@ module Asana
|
|
72
74
|
#
|
73
75
|
# Yields a {Asana::Client::Configuration} object as a configuration
|
74
76
|
# DSL. See {Asana::Client} for usage examples.
|
75
|
-
def initialize
|
76
|
-
config = Configuration.new.tap
|
77
|
+
def initialize(&block)
|
78
|
+
config = Configuration.new.tap(&block).to_h
|
77
79
|
@http_client =
|
78
|
-
HttpClient.new(authentication:
|
79
|
-
adapter:
|
80
|
-
user_agent:
|
81
|
-
debug_mode:
|
80
|
+
HttpClient.new(authentication: config.fetch(:authentication),
|
81
|
+
adapter: config[:faraday_adapter],
|
82
|
+
user_agent: config[:user_agent],
|
83
|
+
debug_mode: config[:debug_mode],
|
82
84
|
log_asana_change_warnings: config[:log_asana_change_warnings],
|
83
|
-
default_headers:
|
85
|
+
default_headers: config[:default_headers],
|
84
86
|
&config[:faraday_configuration])
|
85
87
|
end
|
86
88
|
|
data/lib/asana/errors.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Asana
|
2
4
|
# Public: Defines the different errors that the Asana API may throw, which the
|
3
5
|
# client code may want to catch.
|
@@ -19,8 +21,8 @@ module Asana
|
|
19
21
|
# user could not be authenticated.
|
20
22
|
NotAuthorized = Class.new(APIError) do
|
21
23
|
def to_s
|
22
|
-
'Valid credentials were not provided with the request, so the API could '\
|
23
|
-
|
24
|
+
'Valid credentials were not provided with the request, so the API could ' \
|
25
|
+
'not associate a user with the request.'
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -28,8 +30,8 @@ module Asana
|
|
28
30
|
# that requires a premium account (Payment Required).
|
29
31
|
PremiumOnly = Class.new(APIError) do
|
30
32
|
def to_s
|
31
|
-
'The endpoint that is being requested is only available to premium '\
|
32
|
-
|
33
|
+
'The endpoint that is being requested is only available to premium ' \
|
34
|
+
'users.'
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
@@ -37,18 +39,18 @@ module Asana
|
|
37
39
|
# access the requested resource or to perform the requested action on it.
|
38
40
|
Forbidden = Class.new(APIError) do
|
39
41
|
def to_s
|
40
|
-
'The authorization and request syntax was valid but the server is refusing '\
|
41
|
-
|
42
|
-
|
42
|
+
'The authorization and request syntax was valid but the server is refusing ' \
|
43
|
+
'to complete the request. This can happen if you try to read or write ' \
|
44
|
+
'to objects or properties that the user does not have access to.'
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
46
48
|
# Public: A 404 error. Raised when the requested resource doesn't exist.
|
47
49
|
NotFound = Class.new(APIError) do
|
48
50
|
def to_s
|
49
|
-
'Either the request method and path supplied do not specify a known '\
|
50
|
-
|
51
|
-
|
51
|
+
'Either the request method and path supplied do not specify a known ' \
|
52
|
+
'action in the API, or the object specified by the request does not ' \
|
53
|
+
'exist.'
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
@@ -59,11 +61,12 @@ module Asana
|
|
59
61
|
attr_accessor :phrase
|
60
62
|
|
61
63
|
def initialize(phrase)
|
64
|
+
super()
|
62
65
|
@phrase = phrase
|
63
66
|
end
|
64
67
|
|
65
68
|
def to_s
|
66
|
-
"There has been an error on Asana's end. Use this unique phrase to "\
|
69
|
+
"There has been an error on Asana's end. Use this unique phrase to " \
|
67
70
|
'identify the problem when contacting support: ' + %("#{@phrase}")
|
68
71
|
end
|
69
72
|
end
|
@@ -74,6 +77,7 @@ module Asana
|
|
74
77
|
attr_accessor :errors
|
75
78
|
|
76
79
|
def initialize(errors)
|
80
|
+
super()
|
77
81
|
@errors = errors
|
78
82
|
end
|
79
83
|
|
@@ -89,6 +93,7 @@ module Asana
|
|
89
93
|
attr_accessor :retry_after_seconds
|
90
94
|
|
91
95
|
def initialize(retry_after_seconds)
|
96
|
+
super()
|
92
97
|
@retry_after_seconds = retry_after_seconds
|
93
98
|
end
|
94
99
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative '../version'
|
2
4
|
require 'openssl'
|
3
5
|
|
@@ -6,7 +8,7 @@ module Asana
|
|
6
8
|
# Internal: Adds environment information to a Faraday request.
|
7
9
|
class EnvironmentInfo
|
8
10
|
# Internal: The default user agent to use in all requests to the API.
|
9
|
-
USER_AGENT = "ruby-asana v#{Asana::VERSION}"
|
11
|
+
USER_AGENT = "ruby-asana v#{Asana::VERSION}"
|
10
12
|
|
11
13
|
def initialize(user_agent = nil)
|
12
14
|
@user_agent = user_agent || USER_AGENT
|
@@ -19,7 +21,7 @@ module Asana
|
|
19
21
|
# environment.
|
20
22
|
def configure(builder)
|
21
23
|
builder.headers[:user_agent] = @user_agent
|
22
|
-
builder.headers[:
|
24
|
+
builder.headers[:'X-Asana-Client-Lib'] = header
|
23
25
|
end
|
24
26
|
|
25
27
|
private
|
@@ -33,21 +35,20 @@ module Asana
|
|
33
35
|
.map { |k, v| "#{k}=#{v}" }.join('&')
|
34
36
|
end
|
35
37
|
|
36
|
-
# rubocop:disable Metrics/MethodLength
|
37
38
|
def os
|
38
|
-
|
39
|
+
case RUBY_PLATFORM
|
40
|
+
when /win32/, /mingw/
|
39
41
|
'windows'
|
40
|
-
|
42
|
+
when /linux/
|
41
43
|
'linux'
|
42
|
-
|
44
|
+
when /darwin/
|
43
45
|
'darwin'
|
44
|
-
|
46
|
+
when /freebsd/
|
45
47
|
'freebsd'
|
46
48
|
else
|
47
49
|
'unknown'
|
48
50
|
end
|
49
51
|
end
|
50
|
-
# rubocop:enable Metrics/MethodLength
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../errors'
|
4
4
|
|
@@ -27,37 +27,34 @@ module Asana
|
|
27
27
|
# Raises [Asana::Errors::ServerError] when there's a server problem.
|
28
28
|
# Raises [Asana::Errors::APIError] when the API returns an unknown error.
|
29
29
|
#
|
30
|
-
# rubocop:disable
|
31
|
-
def handle(num_retries=0, &request)
|
30
|
+
# rubocop:disable Metrics/AbcSize
|
31
|
+
def handle(num_retries = 0, &request)
|
32
32
|
request.call
|
33
33
|
rescue Faraday::ClientError => e
|
34
34
|
raise e unless e.response
|
35
|
+
|
35
36
|
case e.response[:status]
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
when 400 then raise invalid_request(e.response)
|
38
|
+
when 401 then raise not_authorized(e.response)
|
39
|
+
when 402 then raise payment_required(e.response)
|
40
|
+
when 403 then raise forbidden(e.response)
|
41
|
+
when 404 then raise not_found(e.response)
|
42
|
+
when 412 then recover_response(e.response)
|
43
|
+
when 429 then raise rate_limit_enforced(e.response)
|
44
|
+
when 500 then raise server_error(e.response)
|
45
|
+
else raise api_error(e.response)
|
45
46
|
end
|
46
47
|
# Retry for timeouts or 500s from Asana
|
47
48
|
rescue Faraday::ServerError => e
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
raise server_error(e.response)
|
52
|
-
end
|
49
|
+
raise server_error(e.response) unless num_retries < MAX_RETRIES
|
50
|
+
|
51
|
+
handle(num_retries + 1, &request)
|
53
52
|
rescue Net::ReadTimeout => e
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
raise e
|
58
|
-
end
|
53
|
+
raise e unless num_retries < MAX_RETRIES
|
54
|
+
|
55
|
+
handle(num_retries + 1, &request)
|
59
56
|
end
|
60
|
-
# rubocop:enable
|
57
|
+
# rubocop:enable Metrics/AbcSize
|
61
58
|
|
62
59
|
# Internal: Returns an InvalidRequest exception including a list of
|
63
60
|
# errors.
|
@@ -112,13 +109,15 @@ module Asana
|
|
112
109
|
|
113
110
|
# Internal: Parser a response body from JSON.
|
114
111
|
def body(response)
|
115
|
-
|
112
|
+
JSON.parse(response[:body])
|
116
113
|
end
|
117
114
|
|
115
|
+
# rubocop:disable Style/OpenStructUse
|
118
116
|
def recover_response(response)
|
119
117
|
r = response.dup.tap { |res| res[:body] = body(response) }
|
120
118
|
Response.new(OpenStruct.new(env: OpenStruct.new(r)))
|
121
119
|
end
|
120
|
+
# rubocop:enable Style/OpenStructUse
|
122
121
|
end
|
123
122
|
end
|
124
123
|
end
|
data/lib/asana/http_client.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
|
-
require '
|
3
|
-
require 'faraday_middleware/multi_json'
|
4
|
+
require 'faraday/follow_redirects'
|
4
5
|
|
5
6
|
require_relative 'http_client/error_handling'
|
6
7
|
require_relative 'http_client/environment_info'
|
@@ -11,7 +12,7 @@ module Asana
|
|
11
12
|
# parsing and common options.
|
12
13
|
class HttpClient
|
13
14
|
# Internal: The API base URI.
|
14
|
-
BASE_URI = 'https://app.asana.com/api/1.0'
|
15
|
+
BASE_URI = 'https://app.asana.com/api/1.0'
|
15
16
|
|
16
17
|
# Public: Initializes an HttpClient to make requests to the Asana API.
|
17
18
|
#
|
@@ -130,7 +131,8 @@ module Asana
|
|
130
131
|
yield builder if request_config
|
131
132
|
configure_format(builder)
|
132
133
|
add_middleware(builder)
|
133
|
-
|
134
|
+
configure_redirects(builder)
|
135
|
+
@config&.call(builder)
|
134
136
|
use_adapter(builder, @adapter)
|
135
137
|
end
|
136
138
|
end
|
@@ -147,13 +149,16 @@ module Asana
|
|
147
149
|
end
|
148
150
|
|
149
151
|
def configure_format(builder)
|
150
|
-
builder.request :
|
151
|
-
builder.response :
|
152
|
+
builder.request :json
|
153
|
+
builder.response :json
|
152
154
|
end
|
153
155
|
|
154
156
|
def add_middleware(builder)
|
155
157
|
builder.use Faraday::Response::RaiseError
|
156
|
-
|
158
|
+
end
|
159
|
+
|
160
|
+
def configure_redirects(builder)
|
161
|
+
builder.response :follow_redirects
|
157
162
|
end
|
158
163
|
|
159
164
|
def use_adapter(builder, adapter)
|
@@ -170,79 +175,75 @@ module Asana
|
|
170
175
|
end
|
171
176
|
|
172
177
|
def log_request(method, url, body)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
+
warn format('[%<klass>s] %<method>s %<url>s (%<bodt>s)',
|
179
|
+
klass: self.class,
|
180
|
+
method: method.to_s.upcase,
|
181
|
+
url: url,
|
182
|
+
body: body.inspect)
|
178
183
|
end
|
179
184
|
|
185
|
+
# rubocop:disable Metrics/AbcSize
|
186
|
+
# rubocop:disable Metrics/MethodLength
|
180
187
|
def log_asana_change_headers(request_headers, response_headers)
|
181
188
|
change_header_key = nil
|
182
189
|
|
183
190
|
response_headers.each_key do |key|
|
184
|
-
if key.downcase == 'asana-change'
|
185
|
-
change_header_key = key
|
186
|
-
end
|
191
|
+
change_header_key = key if key.downcase == 'asana-change'
|
187
192
|
end
|
188
193
|
|
189
|
-
if change_header_key
|
190
|
-
accounted_for_flags = Array.new
|
194
|
+
return if change_header_key.nil?
|
191
195
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
elsif req_header.downcase == 'asana-disable'
|
202
|
-
request_headers[req_header].split(',').each do |flag|
|
203
|
-
accounted_for_flags.push(flag)
|
204
|
-
end
|
196
|
+
accounted_for_flags = []
|
197
|
+
|
198
|
+
request_headers = {} if request_headers.nil?
|
199
|
+
# Grab the request's asana-enable flags
|
200
|
+
request_headers.each_key do |req_header|
|
201
|
+
case req_header.downcase
|
202
|
+
when 'asana-enable', 'asana-disable'
|
203
|
+
request_headers[req_header].split(',').each do |flag|
|
204
|
+
accounted_for_flags.push(flag)
|
205
205
|
end
|
206
206
|
end
|
207
|
+
end
|
208
|
+
|
209
|
+
changes = response_headers[change_header_key].split(',')
|
207
210
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
affected = field[1]
|
228
|
-
end
|
229
|
-
|
230
|
-
# Only show the error if the flag was not in the request's asana-enable header
|
231
|
-
if !(accounted_for_flags.include? name) && (affected == 'true')
|
232
|
-
message1 = 'This request is affected by the "%s"' +
|
233
|
-
' deprecation. Please visit this url for more info: %s'
|
234
|
-
message2 = 'Adding "%s" to your "Asana-Enable" or ' +
|
235
|
-
'"Asana-Disable" header will opt in/out to this deprecation ' +
|
236
|
-
'and suppress this warning.'
|
237
|
-
|
238
|
-
STDERR.puts format(message1, name, info)
|
239
|
-
STDERR.puts format(message2, name)
|
240
|
-
end
|
211
|
+
changes.each do |unsplit_change|
|
212
|
+
change = unsplit_change.split(';')
|
213
|
+
|
214
|
+
name = nil
|
215
|
+
info = nil
|
216
|
+
affected = nil
|
217
|
+
|
218
|
+
change.each do |unsplit_field|
|
219
|
+
field = unsplit_field.split('=')
|
220
|
+
|
221
|
+
field[0].strip!
|
222
|
+
field[1].strip!
|
223
|
+
case field[0]
|
224
|
+
when 'name'
|
225
|
+
name = field[1]
|
226
|
+
when 'info'
|
227
|
+
info = field[1]
|
228
|
+
when 'affected'
|
229
|
+
affected = field[1]
|
241
230
|
end
|
231
|
+
|
232
|
+
# Only show the error if the flag was not in the request's asana-enable header
|
233
|
+
next unless !(accounted_for_flags.include? name) && (affected == 'true')
|
234
|
+
|
235
|
+
message1 = 'This request is affected by the "%s" ' \
|
236
|
+
'deprecation. Please visit this url for more info: %s'
|
237
|
+
message2 = 'Adding "%s" to your "Asana-Enable" or ' \
|
238
|
+
'"Asana-Disable" header will opt in/out to this deprecation ' \
|
239
|
+
'and suppress this warning.'
|
240
|
+
|
241
|
+
warn format(message1, name, info)
|
242
|
+
warn format(message2, name)
|
242
243
|
end
|
243
244
|
end
|
244
245
|
end
|
246
|
+
# rubocop:enable Metrics/AbcSize
|
247
|
+
# rubocop:enable Metrics/MethodLength
|
245
248
|
end
|
246
249
|
end
|
247
|
-
|
248
|
-
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday/multipart'
|
4
|
+
|
1
5
|
module Asana
|
2
6
|
module Resources
|
3
7
|
# Internal: Mixin to add the ability to upload an attachment to a specific
|
@@ -11,8 +15,6 @@ module Asana
|
|
11
15
|
# options - [Hash] the request I/O options
|
12
16
|
# data - [Hash] extra attributes to post
|
13
17
|
#
|
14
|
-
# rubocop:disable Metrics/AbcSize
|
15
|
-
# rubocop:disable Metrics/MethodLength
|
16
18
|
def attach(filename: required('filename'),
|
17
19
|
mime: required('mime'),
|
18
20
|
io: nil, options: {}, **data)
|
@@ -21,9 +23,9 @@ module Asana
|
|
21
23
|
path = File.expand_path(filename)
|
22
24
|
raise ArgumentError, "file #{filename} doesn't exist" unless File.exist?(path)
|
23
25
|
|
24
|
-
Faraday::FilePart.new(path, mime)
|
26
|
+
Faraday::Multipart::FilePart.new(path, mime)
|
25
27
|
else
|
26
|
-
Faraday::FilePart.new(io, mime, filename)
|
28
|
+
Faraday::Multipart::FilePart.new(io, mime, filename)
|
27
29
|
end
|
28
30
|
|
29
31
|
response = client.post("/#{self.class.plural_name}/#{gid}/attachments",
|
@@ -33,8 +35,6 @@ module Asana
|
|
33
35
|
|
34
36
|
Attachment.new(parse(response).first, client: client)
|
35
37
|
end
|
36
|
-
# rubocop:enable Metrics/MethodLength
|
37
|
-
# rubocop:enable Metrics/AbcSize
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'response_helper'
|
2
4
|
|
3
5
|
module Asana
|
@@ -40,7 +42,7 @@ module Asana
|
|
40
42
|
def last
|
41
43
|
@elements.last
|
42
44
|
end
|
43
|
-
|
45
|
+
|
44
46
|
# Public: Returns the size of the collection.
|
45
47
|
def size
|
46
48
|
to_a.size
|
@@ -49,9 +51,7 @@ module Asana
|
|
49
51
|
|
50
52
|
# Public: Returns a String representation of the collection.
|
51
53
|
def to_s
|
52
|
-
"#<Asana::Collection<#{@type}> "
|
53
|
-
"[#{@elements.map(&:inspect).join(', ')}" +
|
54
|
-
(@next_page_data ? ', ...' : '') + ']>'
|
54
|
+
"#<Asana::Collection<#{@type}> [#{@elements.map(&:inspect).join(', ')}#{@next_page_data ? ', ...' : ''}]>"
|
55
55
|
end
|
56
56
|
alias inspect to_s
|
57
57
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'event'
|
2
4
|
|
3
5
|
module Asana
|
@@ -89,13 +91,14 @@ module Asana
|
|
89
91
|
|
90
92
|
# Internal: Returns the formatted params for the poll request.
|
91
93
|
def params
|
92
|
-
{ resource: @resource, sync: @sync }.
|
94
|
+
{ resource: @resource, sync: @sync }.compact
|
93
95
|
end
|
94
96
|
|
95
97
|
# Internal: Executes a block if at least @wait seconds have passed since
|
96
98
|
# @last_poll.
|
97
99
|
def rate_limiting
|
98
100
|
return if @last_poll && Time.now - @last_poll <= @wait
|
101
|
+
|
99
102
|
yield.tap { @last_poll = Time.now }
|
100
103
|
end
|
101
104
|
end
|