xero-ruby 2.8.0 → 2.10.0

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.
@@ -31,7 +31,8 @@ module XeroRuby
31
31
  # @param project_create_or_update [ProjectCreateOrUpdate] Create a new project with ProjectCreateOrUpdate object
32
32
  # @param [Hash] opts the optional parameters
33
33
  # @return [Array<(Project, Integer, Hash)>] Project data, response status code and response headers
34
- def create_project_with_http_info(xero_tenant_id, project_create_or_update, opts = {})
34
+ def create_project_with_http_info(xero_tenant_id, project_create_or_update, options = {})
35
+ opts = options.dup
35
36
  if @api_client.config.debugging
36
37
  @api_client.config.logger.debug 'Calling API: ProjectApi.create_project ...'
37
38
  end
@@ -111,7 +112,8 @@ module XeroRuby
111
112
  # @param time_entry_create_or_update [TimeEntryCreateOrUpdate] The time entry object you are creating
112
113
  # @param [Hash] opts the optional parameters
113
114
  # @return [Array<(TimeEntry, Integer, Hash)>] TimeEntry data, response status code and response headers
114
- def create_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_create_or_update, opts = {})
115
+ def create_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_create_or_update, options = {})
116
+ opts = options.dup
115
117
  if @api_client.config.debugging
116
118
  @api_client.config.logger.debug 'Calling API: ProjectApi.create_time_entry ...'
117
119
  end
@@ -195,7 +197,8 @@ module XeroRuby
195
197
  # @param time_entry_id [String] You can specify an individual task by appending the id to the endpoint
196
198
  # @param [Hash] opts the optional parameters
197
199
  # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
198
- def delete_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_id, opts = {})
200
+ def delete_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_id, options = {})
201
+ opts = options.dup
199
202
  if @api_client.config.debugging
200
203
  @api_client.config.logger.debug 'Calling API: ProjectApi.delete_time_entry ...'
201
204
  end
@@ -273,7 +276,8 @@ module XeroRuby
273
276
  # @param project_id [String] You can specify an individual project by appending the projectId to the endpoint
274
277
  # @param [Hash] opts the optional parameters
275
278
  # @return [Array<(Project, Integer, Hash)>] Project data, response status code and response headers
276
- def get_project_with_http_info(xero_tenant_id, project_id, opts = {})
279
+ def get_project_with_http_info(xero_tenant_id, project_id, options = {})
280
+ opts = options.dup
277
281
  if @api_client.config.debugging
278
282
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_project ...'
279
283
  end
@@ -351,7 +355,8 @@ module XeroRuby
351
355
  # @option opts [Integer] :page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0.
352
356
  # @option opts [Integer] :page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500.
353
357
  # @return [Array<(ProjectUsers, Integer, Hash)>] ProjectUsers data, response status code and response headers
354
- def get_project_users_with_http_info(xero_tenant_id, opts = {})
358
+ def get_project_users_with_http_info(xero_tenant_id, options = {})
359
+ opts = options.dup
355
360
  if @api_client.config.debugging
356
361
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_project_users ...'
357
362
  end
@@ -441,7 +446,8 @@ module XeroRuby
441
446
  # @option opts [Integer] :page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0.
442
447
  # @option opts [Integer] :page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500.
443
448
  # @return [Array<(Projects, Integer, Hash)>] Projects data, response status code and response headers
444
- def get_projects_with_http_info(xero_tenant_id, opts = {})
449
+ def get_projects_with_http_info(xero_tenant_id, options = {})
450
+ opts = options.dup
445
451
  if @api_client.config.debugging
446
452
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_projects ...'
447
453
  end
@@ -528,7 +534,8 @@ module XeroRuby
528
534
  # @param task_id [String] You can specify an individual task by appending the taskId to the endpoint, i.e. GET https://.../tasks/{taskID}
529
535
  # @param [Hash] opts the optional parameters
530
536
  # @return [Array<(Task, Integer, Hash)>] Task data, response status code and response headers
531
- def get_task_with_http_info(xero_tenant_id, project_id, task_id, opts = {})
537
+ def get_task_with_http_info(xero_tenant_id, project_id, task_id, options = {})
538
+ opts = options.dup
532
539
  if @api_client.config.debugging
533
540
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_task ...'
534
541
  end
@@ -616,7 +623,8 @@ module XeroRuby
616
623
  # @option opts [String] :task_ids taskIdsSearch for all tasks that match a comma separated list of taskIds, i.e. GET https://.../tasks?taskIds&#x3D;{taskID},{taskID}
617
624
  # @option opts [ChargeType] :charge_type
618
625
  # @return [Array<(Tasks, Integer, Hash)>] Tasks data, response status code and response headers
619
- def get_tasks_with_http_info(xero_tenant_id, project_id, opts = {})
626
+ def get_tasks_with_http_info(xero_tenant_id, project_id, options = {})
627
+ opts = options.dup
620
628
  if @api_client.config.debugging
621
629
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_tasks ...'
622
630
  end
@@ -716,7 +724,8 @@ module XeroRuby
716
724
  # @option opts [DateTime] :date_after_utc ISO 8601 UTC date. Finds all time entries on or after this date filtered on the &#x60;dateUtc&#x60; field.
717
725
  # @option opts [DateTime] :date_before_utc ISO 8601 UTC date. Finds all time entries on or before this date filtered on the &#x60;dateUtc&#x60; field.
718
726
  # @return [Array<(TimeEntries, Integer, Hash)>] TimeEntries data, response status code and response headers
719
- def get_time_entries_with_http_info(xero_tenant_id, project_id, opts = {})
727
+ def get_time_entries_with_http_info(xero_tenant_id, project_id, options = {})
728
+ opts = options.dup
720
729
  if @api_client.config.debugging
721
730
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_time_entries ...'
722
731
  end
@@ -804,7 +813,8 @@ module XeroRuby
804
813
  # @param time_entry_id [String] You can specify an individual time entry by appending the id to the endpoint
805
814
  # @param [Hash] opts the optional parameters
806
815
  # @return [Array<(TimeEntry, Integer, Hash)>] TimeEntry data, response status code and response headers
807
- def get_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_id, opts = {})
816
+ def get_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_id, options = {})
817
+ opts = options.dup
808
818
  if @api_client.config.debugging
809
819
  @api_client.config.logger.debug 'Calling API: ProjectApi.get_time_entry ...'
810
820
  end
@@ -886,7 +896,8 @@ module XeroRuby
886
896
  # @param project_patch [ProjectPatch] Update the status of an existing Project
887
897
  # @param [Hash] opts the optional parameters
888
898
  # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
889
- def patch_project_with_http_info(xero_tenant_id, project_id, project_patch, opts = {})
899
+ def patch_project_with_http_info(xero_tenant_id, project_id, project_patch, options = {})
900
+ opts = options.dup
890
901
  if @api_client.config.debugging
891
902
  @api_client.config.logger.debug 'Calling API: ProjectApi.patch_project ...'
892
903
  end
@@ -970,7 +981,8 @@ module XeroRuby
970
981
  # @param project_create_or_update [ProjectCreateOrUpdate] Request of type ProjectCreateOrUpdate
971
982
  # @param [Hash] opts the optional parameters
972
983
  # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
973
- def update_project_with_http_info(xero_tenant_id, project_id, project_create_or_update, opts = {})
984
+ def update_project_with_http_info(xero_tenant_id, project_id, project_create_or_update, options = {})
985
+ opts = options.dup
974
986
  if @api_client.config.debugging
975
987
  @api_client.config.logger.debug 'Calling API: ProjectApi.update_project ...'
976
988
  end
@@ -1056,7 +1068,8 @@ module XeroRuby
1056
1068
  # @param time_entry_create_or_update [TimeEntryCreateOrUpdate] The time entry object you are updating
1057
1069
  # @param [Hash] opts the optional parameters
1058
1070
  # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
1059
- def update_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_id, time_entry_create_or_update, opts = {})
1071
+ def update_time_entry_with_http_info(xero_tenant_id, project_id, time_entry_id, time_entry_create_or_update, options = {})
1072
+ opts = options.dup
1060
1073
  if @api_client.config.debugging
1061
1074
  @api_client.config.logger.debug 'Calling API: ProjectApi.update_time_entry ...'
1062
1075
  end
@@ -16,6 +16,8 @@ require 'tempfile'
16
16
  require 'find'
17
17
  require 'faraday'
18
18
  require 'base64'
19
+ require 'cgi'
20
+ require 'json/jwt'
19
21
 
20
22
  module XeroRuby
21
23
  class ApiClient
@@ -31,13 +33,15 @@ module XeroRuby
31
33
 
32
34
  # Initializes the ApiClient
33
35
  # @option config [Configuration] Configuration for initializing the object, default to Configuration.default
34
- def initialize(config: Configuration.default, credentials: {})
36
+ def initialize(config: {}, credentials: {})
35
37
  @client_id = credentials[:client_id]
36
38
  @client_secret = credentials[:client_secret]
37
39
  @redirect_uri = credentials[:redirect_uri]
38
40
  @scopes = credentials[:scopes]
39
41
  @state = credentials[:state]
40
- @config = config
42
+ default_config = Configuration.default.clone
43
+ @config = append_to_default_config(default_config, config)
44
+
41
45
  @user_agent = "xero-ruby-#{VERSION}"
42
46
  @default_headers = {
43
47
  'Content-Type' => 'application/json',
@@ -45,8 +49,14 @@ module XeroRuby
45
49
  }
46
50
  end
47
51
 
52
+ def append_to_default_config(default_config, user_config)
53
+ config = default_config
54
+ user_config.each{|k,v| config.send("#{k}=", v)}
55
+ config
56
+ end
57
+
48
58
  def authorization_url
49
- url = "#{@config.login_url}?response_type=code&client_id=#{@client_id}&redirect_uri=#{@redirect_uri}&scope=#{@scopes}"
59
+ url = "#{@config.login_url}?response_type=code&client_id=#{@client_id}&redirect_uri=#{@redirect_uri}&scope=#{CGI.escape(@scopes)}"
50
60
  url << "&state=#{@state}" if @state
51
61
  return url
52
62
  end
@@ -88,22 +98,41 @@ module XeroRuby
88
98
 
89
99
  # Token Helpers
90
100
  def token_set
91
- XeroRuby.configure.token_set
101
+ @config.token_set
92
102
  end
93
103
 
94
104
  def access_token
95
- XeroRuby.configure.access_token
105
+ @config.access_token
106
+ end
107
+
108
+ def id_token
109
+ @config.id_token
110
+ end
111
+
112
+ def decoded_access_token
113
+ decode_jwt(@config.access_token)
114
+ end
115
+
116
+ def decoded_id_token
117
+ decode_jwt(@config.id_token)
96
118
  end
97
119
 
98
120
  def set_token_set(token_set)
99
- # helper to set the token_set on a client once the user
100
- # has a valid token set ( access_token & refresh_token )
101
- XeroRuby.configure.token_set = token_set
102
- set_access_token(token_set['access_token'])
121
+ token_set = token_set.with_indifferent_access
122
+ @config.token_set = token_set
123
+
124
+ set_access_token(token_set[:access_token]) if token_set[:access_token]
125
+ set_id_token(token_set[:id_token]) if token_set[:id_token]
126
+
127
+ return true
103
128
  end
104
129
 
105
130
  def set_access_token(access_token)
106
- XeroRuby.configure.access_token = access_token
131
+ @config.access_token = access_token
132
+ end
133
+
134
+ def set_id_token(id_token)
135
+ @config.id_token = id_token
107
136
  end
108
137
 
109
138
  def get_token_set_from_callback(params)
@@ -112,20 +141,52 @@ module XeroRuby
112
141
  code: params['code'],
113
142
  redirect_uri: @redirect_uri
114
143
  }
115
- return token_request(data, '/token')
144
+ token_set = token_request(data, '/token')
145
+
146
+ validate_tokens(token_set)
147
+ validate_state(params)
148
+ return token_set
149
+ end
150
+
151
+ def validate_tokens(token_set)
152
+ id_token = token_set[:id_token]
153
+ access_token = token_set[:access_token]
154
+ if id_token || access_token
155
+ decode_jwt(access_token) if access_token
156
+ decode_jwt(id_token) if id_token
157
+ end
158
+ return true
159
+ end
160
+
161
+ def validate_state(params)
162
+ if params[:state] != @state
163
+ raise StandardError.new "WARNING: @config.state: #{@state} and OAuth callback state: #{params['state']} do not match!"
164
+ end
165
+ return true
166
+ end
167
+
168
+ def decode_jwt(tkn)
169
+ jwks_data = JSON.parse(Faraday.get('https://identity.xero.com/.well-known/openid-configuration/jwks').body)
170
+ jwk_set = JSON::JWK::Set.new(jwks_data)
171
+ JSON::JWT.decode(tkn, jwk_set)
172
+ end
173
+
174
+ def token_expired?
175
+ token_expiry = Time.at(decoded_access_token['exp'])
176
+ token_expiry < Time.now
116
177
  end
117
178
 
118
179
  def refresh_token_set(token_set)
119
180
  data = {
120
181
  grant_type: 'refresh_token',
121
- refresh_token: token_set['refresh_token']
182
+ refresh_token: token_set[:refresh_token]
122
183
  }
123
184
  return token_request(data, '/token')
124
185
  end
125
186
 
126
187
  def revoke_token(token_set)
127
188
  data = {
128
- token: token_set['refresh_token']
189
+ token: token_set[:refresh_token]
129
190
  }
130
191
  return token_request(data, '/revocation')
131
192
  end
@@ -174,7 +235,26 @@ module XeroRuby
174
235
  :client_key => @config.ssl_client_key
175
236
  }
176
237
 
177
- connection = Faraday.new(:url => config.base_url, :ssl => ssl_options) do |conn|
238
+ case api_client
239
+ when "AccountingApi"
240
+ method_base_url = @config.accounting_url
241
+ when "AssetApi"
242
+ method_base_url = @config.asset_url
243
+ when "FilesApi"
244
+ method_base_url = @config.files_url
245
+ when "PayrollAuApi"
246
+ method_base_url = @config.payroll_au_url
247
+ when "PayrollNzApi"
248
+ method_base_url = @config.payroll_nz_url
249
+ when "PayrollUkApi"
250
+ method_base_url = @config.payroll_uk_url
251
+ when "ProjectApi"
252
+ method_base_url = @config.project_url
253
+ else
254
+ method_base_url = @config.accounting_url
255
+ end
256
+
257
+ connection = Faraday.new(:url => method_base_url, :ssl => ssl_options) do |conn|
178
258
  conn.basic_auth(config.username, config.password)
179
259
  if opts[:header_params]["Content-Type"] == "multipart/form-data"
180
260
  conn.request :multipart
@@ -257,6 +337,8 @@ module XeroRuby
257
337
  end
258
338
  end
259
339
  request.headers = header_params
340
+ timeout = @config.timeout
341
+ request.options.timeout = timeout if timeout > 0
260
342
  request.body = req_body
261
343
  request.url url
262
344
  request.params = query_params
@@ -60,8 +60,11 @@ module XeroRuby
60
60
  # @return [String]
61
61
  attr_accessor :password
62
62
 
63
- # Defines the access token (Bearer) used with OAuth2.
63
+ # Defines the access token (Bearer) used with OAuth2 authorization
64
64
  attr_accessor :access_token
65
+
66
+ # Defines OpenID Connect id_token containing Xero user authentication detail
67
+ attr_accessor :id_token
65
68
 
66
69
  # Defines the token set used with OAuth2. May include id/access/refresh token & other meta info.
67
70
  attr_accessor :token_set
@@ -146,6 +149,8 @@ module XeroRuby
146
149
  @payroll_au_url = 'https://api.xero.com/payroll.xro/1.0/'
147
150
  @payroll_nz_url = 'https://api.xero.com/payroll.xro/2.0/'
148
151
  @payroll_uk_url = 'https://api.xero.com/payroll.xro/2.0/'
152
+ @access_token = nil
153
+ @id_token = nil
149
154
  @api_key = {}
150
155
  @api_key_prefix = {}
151
156
  @timeout = 0
@@ -191,6 +196,14 @@ module XeroRuby
191
196
  def base_url=(api_url)
192
197
  @base_url = api_url
193
198
  end
199
+
200
+ def access_token=(access_token)
201
+ @access_token = access_token
202
+ end
203
+
204
+ def id_token=(id_token)
205
+ @id_token = id_token
206
+ end
194
207
 
195
208
  # Gets API key (with prefix if set).
196
209
  # @param [String] param_name the parameter name of API key auth
@@ -68,6 +68,9 @@ module XeroRuby::Accounting
68
68
  # Booelan that tells you if the batch payment has been reconciled (read-only)
69
69
  attr_accessor :is_reconciled
70
70
 
71
+ # Displays array of validation error messages from the API
72
+ attr_accessor :validation_errors
73
+
71
74
  class EnumAttributeValidator
72
75
  attr_reader :datatype
73
76
  attr_reader :allowable_values
@@ -108,7 +111,8 @@ module XeroRuby::Accounting
108
111
  :'status' => :'Status',
109
112
  :'total_amount' => :'TotalAmount',
110
113
  :'updated_date_utc' => :'UpdatedDateUTC',
111
- :'is_reconciled' => :'IsReconciled'
114
+ :'is_reconciled' => :'IsReconciled',
115
+ :'validation_errors' => :'ValidationErrors'
112
116
  }
113
117
  end
114
118
 
@@ -130,7 +134,8 @@ module XeroRuby::Accounting
130
134
  :'status' => :'String',
131
135
  :'total_amount' => :'String',
132
136
  :'updated_date_utc' => :'DateTime',
133
- :'is_reconciled' => :'String'
137
+ :'is_reconciled' => :'String',
138
+ :'validation_errors' => :'Array<ValidationError>'
134
139
  }
135
140
  end
136
141
 
@@ -214,6 +219,12 @@ module XeroRuby::Accounting
214
219
  if attributes.key?(:'is_reconciled')
215
220
  self.is_reconciled = attributes[:'is_reconciled']
216
221
  end
222
+
223
+ if attributes.key?(:'validation_errors')
224
+ if (value = attributes[:'validation_errors']).is_a?(Array)
225
+ self.validation_errors = value
226
+ end
227
+ end
217
228
  end
218
229
 
219
230
  # Show invalid properties with the reasons. Usually used together with valid?
@@ -333,7 +344,8 @@ module XeroRuby::Accounting
333
344
  status == o.status &&
334
345
  total_amount == o.total_amount &&
335
346
  updated_date_utc == o.updated_date_utc &&
336
- is_reconciled == o.is_reconciled
347
+ is_reconciled == o.is_reconciled &&
348
+ validation_errors == o.validation_errors
337
349
  end
338
350
 
339
351
  # @see the `==` method
@@ -345,7 +357,7 @@ module XeroRuby::Accounting
345
357
  # Calculates hash code according to all attributes.
346
358
  # @return [Integer] Hash code
347
359
  def hash
348
- [account, reference, particulars, code, details, narrative, batch_payment_id, date_string, date, amount, payments, type, status, total_amount, updated_date_utc, is_reconciled].hash
360
+ [account, reference, particulars, code, details, narrative, batch_payment_id, date_string, date, amount, payments, type, status, total_amount, updated_date_utc, is_reconciled, validation_errors].hash
349
361
  end
350
362
 
351
363
  # Builds the object from hash
@@ -62,15 +62,15 @@ module XeroRuby::Accounting
62
62
  # Attribute type mapping.
63
63
  def self.openapi_types
64
64
  {
65
- :'total' => :'Float',
66
- :'new' => :'Float',
67
- :'updated' => :'Float',
68
- :'deleted' => :'Float',
69
- :'locked' => :'Float',
70
- :'system' => :'Float',
71
- :'errored' => :'Float',
65
+ :'total' => :'Integer',
66
+ :'new' => :'Integer',
67
+ :'updated' => :'Integer',
68
+ :'deleted' => :'Integer',
69
+ :'locked' => :'Integer',
70
+ :'system' => :'Integer',
71
+ :'errored' => :'Integer',
72
72
  :'present' => :'Boolean',
73
- :'new_or_updated' => :'Float'
73
+ :'new_or_updated' => :'Integer'
74
74
  }
75
75
  end
76
76
 
@@ -15,7 +15,7 @@ require 'date'
15
15
  module XeroRuby::Files
16
16
  require 'bigdecimal'
17
17
 
18
- class InlineObject
18
+ class UploadObject
19
19
 
20
20
  attr_accessor :body
21
21
 
@@ -52,13 +52,13 @@ module XeroRuby::Files
52
52
  # @param [Hash] attributes Model attributes in the form of hash
53
53
  def initialize(attributes = {})
54
54
  if (!attributes.is_a?(Hash))
55
- fail ArgumentError, "The input argument (attributes) must be a hash in `XeroRuby::Files::InlineObject` initialize method"
55
+ fail ArgumentError, "The input argument (attributes) must be a hash in `XeroRuby::Files::UploadObject` initialize method"
56
56
  end
57
57
 
58
58
  # check to see if the attribute exists and convert string to symbol for hash key
59
59
  attributes = attributes.each_with_object({}) { |(k, v), h|
60
60
  if (!self.class.attribute_map.key?(k.to_sym))
61
- fail ArgumentError, "`#{k}` is not a valid attribute in `XeroRuby::Files::InlineObject`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
61
+ fail ArgumentError, "`#{k}` is not a valid attribute in `XeroRuby::Files::UploadObject`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
62
62
  end
63
63
  h[k.to_sym] = v
64
64
  }
@@ -84,12 +84,27 @@ module XeroRuby::Files
84
84
  # @return Array for valid properties with the reasons
85
85
  def list_invalid_properties
86
86
  invalid_properties = Array.new
87
+ if @body.nil?
88
+ invalid_properties.push('invalid value for "body", body cannot be nil.')
89
+ end
90
+
91
+ if @name.nil?
92
+ invalid_properties.push('invalid value for "name", name cannot be nil.')
93
+ end
94
+
95
+ if @filename.nil?
96
+ invalid_properties.push('invalid value for "filename", filename cannot be nil.')
97
+ end
98
+
87
99
  invalid_properties
88
100
  end
89
101
 
90
102
  # Check to see if the all the properties in the model are valid
91
103
  # @return true if the model is valid
92
104
  def valid?
105
+ return false if @body.nil?
106
+ return false if @name.nil?
107
+ return false if @filename.nil?
93
108
  true
94
109
  end
95
110