xero-ruby 2.8.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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