smartsheet 2.77.0 → 2.77.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -12
  3. data/.rubocop.yml +4 -4
  4. data/.travis.yml +26 -15
  5. data/.yardopts +3 -3
  6. data/ADVANCED.md +78 -78
  7. data/CHANGELOG.md +115 -112
  8. data/Gemfile +6 -6
  9. data/LICENSE +202 -202
  10. data/README.md +246 -246
  11. data/Rakefile +29 -29
  12. data/bin/console +14 -14
  13. data/bin/setup +8 -8
  14. data/lib/smartsheet.rb +2 -2
  15. data/lib/smartsheet/api/body_builder.rb +25 -25
  16. data/lib/smartsheet/api/endpoint_spec.rb +54 -54
  17. data/lib/smartsheet/api/faraday_adapter/faraday_net_client.rb +45 -45
  18. data/lib/smartsheet/api/faraday_adapter/faraday_response.rb +70 -70
  19. data/lib/smartsheet/api/faraday_adapter/middleware/faraday_error_translator.rb +20 -20
  20. data/lib/smartsheet/api/faraday_adapter/middleware/response_parser.rb +25 -25
  21. data/lib/smartsheet/api/file_spec.rb +55 -55
  22. data/lib/smartsheet/api/header_builder.rb +96 -96
  23. data/lib/smartsheet/api/request.rb +42 -42
  24. data/lib/smartsheet/api/request_client.rb +43 -43
  25. data/lib/smartsheet/api/request_logger.rb +182 -182
  26. data/lib/smartsheet/api/request_spec.rb +57 -57
  27. data/lib/smartsheet/api/response_net_client_decorator.rb +54 -54
  28. data/lib/smartsheet/api/retry_logic.rb +40 -40
  29. data/lib/smartsheet/api/retry_net_client_decorator.rb +37 -37
  30. data/lib/smartsheet/api/url_builder.rb +25 -25
  31. data/lib/smartsheet/client.rb +193 -193
  32. data/lib/smartsheet/constants.rb +18 -18
  33. data/lib/smartsheet/endpoints/contacts/contacts.rb +30 -30
  34. data/lib/smartsheet/endpoints/events/events.rb +20 -20
  35. data/lib/smartsheet/endpoints/favorites/favorites.rb +159 -159
  36. data/lib/smartsheet/endpoints/folders/folders.rb +125 -125
  37. data/lib/smartsheet/endpoints/groups/groups.rb +83 -83
  38. data/lib/smartsheet/endpoints/home/home.rb +20 -20
  39. data/lib/smartsheet/endpoints/reports/reports.rb +100 -100
  40. data/lib/smartsheet/endpoints/reports/reports_share.rb +69 -69
  41. data/lib/smartsheet/endpoints/search/search.rb +30 -30
  42. data/lib/smartsheet/endpoints/server_info/server_info.rb +21 -21
  43. data/lib/smartsheet/endpoints/share/share.rb +58 -58
  44. data/lib/smartsheet/endpoints/sheets/automation_rules.rb +55 -55
  45. data/lib/smartsheet/endpoints/sheets/cells.rb +82 -82
  46. data/lib/smartsheet/endpoints/sheets/columns.rb +66 -66
  47. data/lib/smartsheet/endpoints/sheets/comments.rb +64 -64
  48. data/lib/smartsheet/endpoints/sheets/comments_attachments.rb +78 -78
  49. data/lib/smartsheet/endpoints/sheets/cross_sheet_references.rb +45 -45
  50. data/lib/smartsheet/endpoints/sheets/discussions.rb +84 -84
  51. data/lib/smartsheet/endpoints/sheets/discussions_attachments.rb +22 -22
  52. data/lib/smartsheet/endpoints/sheets/rows.rb +106 -106
  53. data/lib/smartsheet/endpoints/sheets/rows_attachments.rb +92 -92
  54. data/lib/smartsheet/endpoints/sheets/sheets.rb +510 -510
  55. data/lib/smartsheet/endpoints/sheets/sheets_attachments.rb +174 -174
  56. data/lib/smartsheet/endpoints/sheets/sheets_share.rb +69 -69
  57. data/lib/smartsheet/endpoints/sights/sights.rb +101 -101
  58. data/lib/smartsheet/endpoints/sights/sights_share.rb +69 -69
  59. data/lib/smartsheet/endpoints/templates/templates.rb +29 -29
  60. data/lib/smartsheet/endpoints/token/token.rb +65 -65
  61. data/lib/smartsheet/endpoints/update_requests/sent_update_requests.rb +44 -44
  62. data/lib/smartsheet/endpoints/update_requests/update_requests.rb +74 -74
  63. data/lib/smartsheet/endpoints/users/alternate_emails.rb +79 -79
  64. data/lib/smartsheet/endpoints/users/users.rb +77 -77
  65. data/lib/smartsheet/endpoints/webhooks/webhooks.rb +71 -71
  66. data/lib/smartsheet/endpoints/workspaces/workspaces.rb +87 -87
  67. data/lib/smartsheet/endpoints/workspaces/workspaces_share.rb +70 -70
  68. data/lib/smartsheet/error.rb +69 -69
  69. data/lib/smartsheet/general_request.rb +74 -74
  70. data/lib/smartsheet/version.rb +5 -5
  71. data/smartsheet.gemspec +54 -54
  72. metadata +3 -4
@@ -1,44 +1,44 @@
1
- require 'smartsheet/version'
2
- require 'smartsheet/error'
3
-
4
- module Smartsheet
5
- module API
6
- # Composes {EndpointSpec endpoint specifications} and {RequestSpec request specifications} to
7
- # form a single {Request} that it submits to the provided client
8
- class RequestClient
9
- def initialize(
10
- token,
11
- client,
12
- base_url,
13
- app_user_agent: nil,
14
- assume_user: nil,
15
- logger: MuteRequestLogger.new
16
- )
17
- @token = token
18
- @client = client
19
- @app_user_agent = app_user_agent
20
- @assume_user = assume_user
21
- @logger = logger
22
- @base_url = base_url
23
- end
24
-
25
- def make_request(endpoint_spec, request_spec)
26
- request = Request.new(
27
- token,
28
- endpoint_spec,
29
- request_spec,
30
- base_url,
31
- app_user_agent: app_user_agent,
32
- assume_user: assume_user
33
- )
34
-
35
- logger.log_request(request)
36
- client.make_request(request)
37
- end
38
-
39
- private
40
-
41
- attr_reader :token, :client, :app_user_agent, :assume_user, :logger, :base_url
42
- end
43
- end
1
+ require 'smartsheet/version'
2
+ require 'smartsheet/error'
3
+
4
+ module Smartsheet
5
+ module API
6
+ # Composes {EndpointSpec endpoint specifications} and {RequestSpec request specifications} to
7
+ # form a single {Request} that it submits to the provided client
8
+ class RequestClient
9
+ def initialize(
10
+ token,
11
+ client,
12
+ base_url,
13
+ app_user_agent: nil,
14
+ assume_user: nil,
15
+ logger: MuteRequestLogger.new
16
+ )
17
+ @token = token
18
+ @client = client
19
+ @app_user_agent = app_user_agent
20
+ @assume_user = assume_user
21
+ @logger = logger
22
+ @base_url = base_url
23
+ end
24
+
25
+ def make_request(endpoint_spec, request_spec)
26
+ request = Request.new(
27
+ token,
28
+ endpoint_spec,
29
+ request_spec,
30
+ base_url,
31
+ app_user_agent: app_user_agent,
32
+ assume_user: assume_user
33
+ )
34
+
35
+ logger.log_request(request)
36
+ client.make_request(request)
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :token, :client, :app_user_agent, :assume_user, :logger, :base_url
42
+ end
43
+ end
44
44
  end
@@ -1,183 +1,183 @@
1
- require 'logger'
2
-
3
- module Smartsheet
4
- module API
5
- # Censors strings and hash values for select blacklisted keys
6
- class Censor
7
- EXPOSED_CHARS = 4
8
- KEY_TO_STRING = ->(k){ k.to_s }
9
- KEY_TO_DOWNCASE_STRING = ->(k){ k.to_s.downcase }
10
-
11
- def initialize(*blacklist)
12
- @blacklist = Set.new(blacklist)
13
- end
14
-
15
- def censor_hash(h, case_insensitive: false)
16
- if case_insensitive
17
- _censor_hash(h, KEY_TO_DOWNCASE_STRING, downcased_blacklist)
18
- else
19
- _censor_hash(h, KEY_TO_STRING, blacklist)
20
- end
21
- end
22
-
23
- def censor(str)
24
- total_length = str.length
25
- censored_length = [total_length - EXPOSED_CHARS, 0].max
26
- ('*' * censored_length) + str[censored_length...total_length]
27
- end
28
-
29
- private
30
-
31
- def _censor_hash(h, key_transform, cased_blacklist)
32
- h.collect do |(k, v)|
33
- new_v =
34
- cased_blacklist.include?(key_transform.call(k)) ?
35
- censor(v) :
36
- v
37
-
38
- [k, new_v]
39
- end.to_h
40
- end
41
-
42
- def downcased_blacklist
43
- blacklist.collect { |x| x.downcase }
44
- end
45
-
46
- attr_reader :blacklist
47
- end
48
-
49
- # Logs request and response information, while censoring OAuth-relevant keys
50
- class RequestLogger
51
- QUERY_PARAM_CENSOR = Censor.new 'code', 'client_id', 'hash', 'refresh_token'
52
- HEADER_CENSOR = Censor.new 'authorization'
53
- PAYLOAD_CENSOR = Censor.new 'access_token', 'refresh_token'
54
-
55
- TRUNCATED_BODY_LENGTH = 1024
56
-
57
- def initialize(logger, log_full_body:)
58
- @logger = logger
59
- @log_full_body = log_full_body
60
- end
61
-
62
- def log_request(request)
63
- log_request_basics(Logger::INFO, request)
64
- log_headers('Request', request)
65
- log_body('Request', request.body)
66
- end
67
-
68
- def log_retry_attempt(request, response, attempt_num)
69
- logger.warn { "Request attempt #{attempt_num} failed" }
70
- log_request_basics(Logger::WARN, request)
71
- log_api_error(Logger::WARN, response)
72
- end
73
-
74
- def log_retry_failure(num_tries)
75
- try_word = num_tries == 1 ? 'try' : 'tries'
76
- logger.error { "Request failed after #{num_tries} #{try_word}" }
77
- end
78
-
79
- def log_successful_response(response)
80
- log_status(Logger::INFO, response)
81
- log_headers('Response', response)
82
- log_body('Response', response.result)
83
- end
84
-
85
- def log_api_error_response(request, error)
86
- log_request_basics(Logger::ERROR, request)
87
- log_api_error(Logger::ERROR, error)
88
- end
89
-
90
- def log_http_error_response(request, error)
91
- log_request_basics(Logger::ERROR, request)
92
- log_http_error(Logger::ERROR, error)
93
- end
94
-
95
- private
96
-
97
- attr_reader :logger, :log_full_body
98
-
99
- def log_request_basics(level, request)
100
- logger.log(level) { "Request: #{request.method.upcase} #{build_logging_url(request)}" }
101
- end
102
-
103
- def build_logging_url(request)
104
- query_params = QUERY_PARAM_CENSOR.censor_hash(request.params)
105
- query_param_str =
106
- if query_params.empty?
107
- ''
108
- else
109
- '?' + query_params.collect { |(k, v)| "#{k}=#{v}" }.join('&') # TODO: URI Encoding
110
- end
111
- request.url + query_param_str
112
- end
113
-
114
- def log_api_error(level, response)
115
- log_status(level, response)
116
- logger.log(level) do
117
- "#{response.error_code}: #{response.message} - Ref ID: #{response.ref_id}"
118
- end
119
- log_headers('Response', response)
120
- end
121
-
122
- def log_http_error(level, response)
123
- log_status(level, response)
124
- log_headers('Response', response)
125
- end
126
-
127
- def log_status(level, response)
128
- logger.log(level) { "Response: #{response.status_code} #{response.reason_phrase}" }
129
- end
130
-
131
- def log_headers(context, req_or_resp)
132
- censored_hash = HEADER_CENSOR.censor_hash(req_or_resp.headers, case_insensitive: true)
133
- logger.debug { "#{context} Headers: #{censored_hash}" }
134
- end
135
-
136
- def log_body(context, body)
137
- return unless body
138
-
139
- body_str =
140
- if body.is_a? String
141
- body
142
- elsif body.is_a? Hash
143
- PAYLOAD_CENSOR.censor_hash(body).to_s
144
- else
145
- '<Binary body>'
146
- end
147
-
148
- body_str = truncate_body(body_str) unless log_full_body
149
-
150
- logger.debug "#{context} Body: #{body_str}"
151
- end
152
-
153
- def truncate_body(body_str)
154
- if body_str.length > TRUNCATED_BODY_LENGTH
155
- body_str[0...TRUNCATED_BODY_LENGTH] + '...'
156
- else
157
- body_str
158
- end
159
- end
160
- end
161
-
162
- # Stubs all request logging methods by doing nothing (see {RequestLogger})
163
- class MuteRequestLogger
164
- def log_request(request)
165
- end
166
-
167
- def log_retry_attempt(request, response, attempt_num)
168
- end
169
-
170
- def log_retry_failure(num_retries)
171
- end
172
-
173
- def log_successful_response(response)
174
- end
175
-
176
- def log_api_error_response(request, error)
177
- end
178
-
179
- def log_http_error_response(request, error)
180
- end
181
- end
182
- end
1
+ require 'logger'
2
+
3
+ module Smartsheet
4
+ module API
5
+ # Censors strings and hash values for select blacklisted keys
6
+ class Censor
7
+ EXPOSED_CHARS = 4
8
+ KEY_TO_STRING = ->(k){ k.to_s }
9
+ KEY_TO_DOWNCASE_STRING = ->(k){ k.to_s.downcase }
10
+
11
+ def initialize(*blacklist)
12
+ @blacklist = Set.new(blacklist)
13
+ end
14
+
15
+ def censor_hash(h, case_insensitive: false)
16
+ if case_insensitive
17
+ _censor_hash(h, KEY_TO_DOWNCASE_STRING, downcased_blacklist)
18
+ else
19
+ _censor_hash(h, KEY_TO_STRING, blacklist)
20
+ end
21
+ end
22
+
23
+ def censor(str)
24
+ total_length = str.length
25
+ censored_length = [total_length - EXPOSED_CHARS, 0].max
26
+ ('*' * censored_length) + str[censored_length...total_length]
27
+ end
28
+
29
+ private
30
+
31
+ def _censor_hash(h, key_transform, cased_blacklist)
32
+ h.collect do |(k, v)|
33
+ new_v =
34
+ cased_blacklist.include?(key_transform.call(k)) ?
35
+ censor(v) :
36
+ v
37
+
38
+ [k, new_v]
39
+ end.to_h
40
+ end
41
+
42
+ def downcased_blacklist
43
+ blacklist.collect { |x| x.downcase }
44
+ end
45
+
46
+ attr_reader :blacklist
47
+ end
48
+
49
+ # Logs request and response information, while censoring OAuth-relevant keys
50
+ class RequestLogger
51
+ QUERY_PARAM_CENSOR = Censor.new 'code', 'client_id', 'hash', 'refresh_token'
52
+ HEADER_CENSOR = Censor.new 'authorization'
53
+ PAYLOAD_CENSOR = Censor.new 'access_token', 'refresh_token'
54
+
55
+ TRUNCATED_BODY_LENGTH = 1024
56
+
57
+ def initialize(logger, log_full_body:)
58
+ @logger = logger
59
+ @log_full_body = log_full_body
60
+ end
61
+
62
+ def log_request(request)
63
+ log_request_basics(Logger::INFO, request)
64
+ log_headers('Request', request)
65
+ log_body('Request', request.body)
66
+ end
67
+
68
+ def log_retry_attempt(request, response, attempt_num)
69
+ logger.warn { "Request attempt #{attempt_num} failed" }
70
+ log_request_basics(Logger::WARN, request)
71
+ log_api_error(Logger::WARN, response)
72
+ end
73
+
74
+ def log_retry_failure(num_tries)
75
+ try_word = num_tries == 1 ? 'try' : 'tries'
76
+ logger.error { "Request failed after #{num_tries} #{try_word}" }
77
+ end
78
+
79
+ def log_successful_response(response)
80
+ log_status(Logger::INFO, response)
81
+ log_headers('Response', response)
82
+ log_body('Response', response.result)
83
+ end
84
+
85
+ def log_api_error_response(request, error)
86
+ log_request_basics(Logger::ERROR, request)
87
+ log_api_error(Logger::ERROR, error)
88
+ end
89
+
90
+ def log_http_error_response(request, error)
91
+ log_request_basics(Logger::ERROR, request)
92
+ log_http_error(Logger::ERROR, error)
93
+ end
94
+
95
+ private
96
+
97
+ attr_reader :logger, :log_full_body
98
+
99
+ def log_request_basics(level, request)
100
+ logger.log(level) { "Request: #{request.method.upcase} #{build_logging_url(request)}" }
101
+ end
102
+
103
+ def build_logging_url(request)
104
+ query_params = QUERY_PARAM_CENSOR.censor_hash(request.params)
105
+ query_param_str =
106
+ if query_params.empty?
107
+ ''
108
+ else
109
+ '?' + query_params.collect { |(k, v)| "#{k}=#{v}" }.join('&') # TODO: URI Encoding
110
+ end
111
+ request.url + query_param_str
112
+ end
113
+
114
+ def log_api_error(level, response)
115
+ log_status(level, response)
116
+ logger.log(level) do
117
+ "#{response.error_code}: #{response.message} - Ref ID: #{response.ref_id}"
118
+ end
119
+ log_headers('Response', response)
120
+ end
121
+
122
+ def log_http_error(level, response)
123
+ log_status(level, response)
124
+ log_headers('Response', response)
125
+ end
126
+
127
+ def log_status(level, response)
128
+ logger.log(level) { "Response: #{response.status_code} #{response.reason_phrase}" }
129
+ end
130
+
131
+ def log_headers(context, req_or_resp)
132
+ censored_hash = HEADER_CENSOR.censor_hash(req_or_resp.headers, case_insensitive: true)
133
+ logger.debug { "#{context} Headers: #{censored_hash}" }
134
+ end
135
+
136
+ def log_body(context, body)
137
+ return unless body
138
+
139
+ body_str =
140
+ if body.is_a? String
141
+ body
142
+ elsif body.is_a? Hash
143
+ PAYLOAD_CENSOR.censor_hash(body).to_s
144
+ else
145
+ '<Binary body>'
146
+ end
147
+
148
+ body_str = truncate_body(body_str) unless log_full_body
149
+
150
+ logger.debug "#{context} Body: #{body_str}"
151
+ end
152
+
153
+ def truncate_body(body_str)
154
+ if body_str.length > TRUNCATED_BODY_LENGTH
155
+ body_str[0...TRUNCATED_BODY_LENGTH] + '...'
156
+ else
157
+ body_str
158
+ end
159
+ end
160
+ end
161
+
162
+ # Stubs all request logging methods by doing nothing (see {RequestLogger})
163
+ class MuteRequestLogger
164
+ def log_request(request)
165
+ end
166
+
167
+ def log_retry_attempt(request, response, attempt_num)
168
+ end
169
+
170
+ def log_retry_failure(num_retries)
171
+ end
172
+
173
+ def log_successful_response(response)
174
+ end
175
+
176
+ def log_api_error_response(request, error)
177
+ end
178
+
179
+ def log_http_error_response(request, error)
180
+ end
181
+ end
182
+ end
183
183
  end