xeroizer 2.20.0 → 3.0.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.
Files changed (117) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +126 -185
  3. data/lib/xeroizer/connection.rb +49 -0
  4. data/lib/xeroizer/exceptions.rb +2 -0
  5. data/lib/xeroizer/generic_application.rb +8 -3
  6. data/lib/xeroizer/http.rb +5 -80
  7. data/lib/xeroizer/http_response.rb +154 -0
  8. data/lib/xeroizer/models/bank_transaction.rb +1 -0
  9. data/lib/xeroizer/models/batch_payment.rb +4 -1
  10. data/lib/xeroizer/models/contact.rb +10 -4
  11. data/lib/xeroizer/models/credit_note.rb +20 -20
  12. data/lib/xeroizer/models/history_record.rb +72 -0
  13. data/lib/xeroizer/models/invoice.rb +5 -1
  14. data/lib/xeroizer/models/line_item.rb +4 -2
  15. data/lib/xeroizer/models/manual_journal.rb +2 -1
  16. data/lib/xeroizer/models/option.rb +1 -1
  17. data/lib/xeroizer/models/payroll/address.rb +53 -0
  18. data/lib/xeroizer/models/payroll/bank_account.rb +18 -6
  19. data/lib/xeroizer/models/payroll/benefit_line.rb +26 -0
  20. data/lib/xeroizer/models/payroll/benefit_type.rb +45 -0
  21. data/lib/xeroizer/models/payroll/deduction_line.rb +32 -0
  22. data/lib/xeroizer/models/payroll/deduction_type.rb +49 -0
  23. data/lib/xeroizer/models/payroll/earnings_line.rb +39 -0
  24. data/lib/xeroizer/models/payroll/earnings_type.rb +53 -0
  25. data/lib/xeroizer/models/payroll/employee.rb +30 -8
  26. data/lib/xeroizer/models/payroll/leave_application.rb +27 -0
  27. data/lib/xeroizer/models/payroll/leave_line.rb +30 -0
  28. data/lib/xeroizer/models/payroll/leave_period.rb +15 -0
  29. data/lib/xeroizer/models/payroll/pay_items.rb +22 -0
  30. data/lib/xeroizer/models/payroll/pay_run.rb +33 -0
  31. data/lib/xeroizer/models/payroll/pay_schedule.rb +40 -0
  32. data/lib/xeroizer/models/payroll/pay_template.rb +24 -0
  33. data/lib/xeroizer/models/payroll/payment_method.rb +24 -0
  34. data/lib/xeroizer/models/payroll/paystub.rb +44 -0
  35. data/lib/xeroizer/models/payroll/reimbursement_line.rb +21 -0
  36. data/lib/xeroizer/models/payroll/reimbursement_type.rb +22 -0
  37. data/lib/xeroizer/models/payroll/salary_and_wage.rb +29 -0
  38. data/lib/xeroizer/models/payroll/super_line.rb +40 -0
  39. data/lib/xeroizer/models/payroll/tax_declaration.rb +50 -0
  40. data/lib/xeroizer/models/payroll/time_off_line.rb +20 -0
  41. data/lib/xeroizer/models/payroll/time_off_type.rb +32 -0
  42. data/lib/xeroizer/models/payroll/work_location.rb +25 -0
  43. data/lib/xeroizer/models/quote.rb +76 -0
  44. data/lib/xeroizer/models/tax_component.rb +1 -0
  45. data/lib/xeroizer/oauth.rb +12 -1
  46. data/lib/xeroizer/oauth2.rb +82 -0
  47. data/lib/xeroizer/oauth2_application.rb +49 -0
  48. data/lib/xeroizer/payroll_application.rb +8 -3
  49. data/lib/xeroizer/record/base_model.rb +1 -1
  50. data/lib/xeroizer/record/base_model_http_proxy.rb +1 -0
  51. data/lib/xeroizer/record/payroll_base.rb +4 -0
  52. data/lib/xeroizer/record/record_association_helper.rb +4 -4
  53. data/lib/xeroizer/record/validators/associated_validator.rb +1 -0
  54. data/lib/xeroizer/record/xml_helper.rb +16 -16
  55. data/lib/xeroizer/response.rb +22 -17
  56. data/lib/xeroizer/version.rb +1 -1
  57. data/lib/xeroizer.rb +31 -4
  58. data/test/acceptance/about_creating_bank_transactions_test.rb +80 -82
  59. data/test/acceptance/about_creating_prepayment_test.rb +25 -30
  60. data/test/acceptance/about_fetching_bank_transactions_test.rb +10 -10
  61. data/test/acceptance/about_online_invoice_test.rb +6 -10
  62. data/test/acceptance/acceptance_test.rb +28 -26
  63. data/test/acceptance/bank_transfer_test.rb +12 -17
  64. data/test/acceptance/bulk_operations_test.rb +18 -16
  65. data/test/acceptance/connections_test.rb +11 -0
  66. data/test/stub_responses/bad_request.json +6 -0
  67. data/test/stub_responses/connections.json +16 -0
  68. data/test/stub_responses/expired_oauth2_token.json +6 -0
  69. data/test/stub_responses/generic_response_error.json +6 -0
  70. data/test/stub_responses/invalid_oauth2_request_token.json +6 -0
  71. data/test/stub_responses/invalid_tenant_header.json +6 -0
  72. data/test/stub_responses/object_not_found.json +6 -0
  73. data/test/test_helper.rb +16 -11
  74. data/test/unit/generic_application_test.rb +21 -10
  75. data/test/unit/http_test.rb +281 -9
  76. data/test/unit/models/address_test.rb +2 -2
  77. data/test/unit/models/bank_transaction_model_parsing_test.rb +2 -2
  78. data/test/unit/models/bank_transaction_test.rb +1 -1
  79. data/test/unit/models/bank_transaction_validation_test.rb +1 -1
  80. data/test/unit/models/contact_test.rb +2 -2
  81. data/test/unit/models/credit_note_test.rb +8 -8
  82. data/test/unit/models/employee_test.rb +4 -4
  83. data/test/unit/models/invoice_test.rb +12 -12
  84. data/test/unit/models/journal_line_test.rb +6 -6
  85. data/test/unit/models/journal_test.rb +4 -4
  86. data/test/unit/models/line_item_sum_test.rb +1 -1
  87. data/test/unit/models/line_item_test.rb +19 -2
  88. data/test/unit/models/manual_journal_test.rb +3 -3
  89. data/test/unit/models/organisation_test.rb +2 -2
  90. data/test/unit/models/payment_service_test.rb +2 -2
  91. data/test/unit/models/phone_test.rb +7 -7
  92. data/test/unit/models/prepayment_test.rb +4 -4
  93. data/test/unit/models/repeating_invoice_test.rb +2 -2
  94. data/test/unit/models/tax_rate_test.rb +2 -2
  95. data/test/unit/oauth2_test.rb +171 -0
  96. data/test/unit/oauth_config_test.rb +1 -1
  97. data/test/unit/record/base_model_test.rb +13 -13
  98. data/test/unit/record/base_test.rb +5 -4
  99. data/test/unit/record/block_validator_test.rb +1 -1
  100. data/test/unit/record/connection_test.rb +60 -0
  101. data/test/unit/record/model_definition_test.rb +36 -36
  102. data/test/unit/record/parse_params_test.rb +2 -2
  103. data/test/unit/record/parse_where_hash_test.rb +13 -13
  104. data/test/unit/record/record_association_test.rb +14 -14
  105. data/test/unit/record/validators_test.rb +43 -43
  106. data/test/unit/record_definition_test.rb +7 -7
  107. data/test/unit/report_definition_test.rb +7 -7
  108. data/test/unit/report_test.rb +20 -20
  109. data/test/unit_test_helper.rb +16 -0
  110. metadata +106 -23
  111. data/lib/xeroizer/models/payroll/home_address.rb +0 -24
  112. data/lib/xeroizer/partner_application.rb +0 -51
  113. data/lib/xeroizer/private_application.rb +0 -25
  114. data/lib/xeroizer/public_application.rb +0 -21
  115. data/test/unit/http_tsl_12_upgrade_test.rb +0 -31
  116. data/test/unit/oauth_test.rb +0 -118
  117. data/test/unit/private_application_test.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7a2ed7ed5abbb823dc78470a4a50e31768592a42
4
- data.tar.gz: 828b5d4e36a703a6f6944f3f183964cf59c19ed8
2
+ SHA256:
3
+ metadata.gz: 1dad6570c636b1273f3569cda927b6c997a1ca6e2cf2ad629cd88c730e57935a
4
+ data.tar.gz: e4d31e8555ca3a986241f5395cc2f9bba6adaba088a48bf286c552cda7008f40
5
5
  SHA512:
6
- metadata.gz: f66a004449f5e9570fed2098ebdb4deb1d55aa0c27e8b355e05bb79989d20171e849a45b33118d9ddbdde9908c20ece199e16b3eceff10188e7c71b0a2dc620e
7
- data.tar.gz: 6a6a3316543a58ec13f448cbeead6ce143f02a6e8799f0eeb125801e2553da2acb1152cd12797906bf53aa33869ad892ddfdf8f312fbd365838f39e6ad06d787
6
+ metadata.gz: 3f8bb7c9cbbfd1792285b4c4bd3d73a24100222dc41f86eba5344e5a84b7d1ffd75ef787fbf43a130a2c17d5f8ac16204b518949872bf6107d889d0e14cb2c4c
7
+ data.tar.gz: bade0622cf61bdff9e444c9ae931c9e8c985c4185c9b0c69c88f285c3869b4df8c83f29294b2087e1b9b045bb2aaa9b171340ab5f63c23d7bae6ac860eb4a769
data/README.md CHANGED
@@ -1,14 +1,21 @@
1
- Xeroizer API Library ![Project status](http://stillmaintained.com/waynerobinson/xeroizer.png) [![Build Status](https://travis-ci.org/waynerobinson/xeroizer.svg)](https://travis-ci.org/waynerobinson/xeroizer)
1
+ Xeroizer API Library
2
2
  ====================
3
3
 
4
4
  **Homepage**: [http://waynerobinson.github.com/xeroizer](http://waynerobinson.github.com/xeroizer)
5
+
5
6
  **Git**: [git://github.com/waynerobinson/xeroizer.git](git://github.com/waynerobinson/xeroizer.git)
7
+
6
8
  **Github**: [https://github.com/waynerobinson/xeroizer](https://github.com/waynerobinson/xeroizer)
9
+
7
10
  **Author**: Wayne Robinson [http://www.wayne-robinson.com](http://www.wayne-robinson.com)
11
+
8
12
  **Contributors**: See Contributors section below
13
+
9
14
  **Copyright**: 2007-2013
15
+
10
16
  **License**: MIT License
11
17
 
18
+
12
19
  Introduction
13
20
  ------------
14
21
 
@@ -29,7 +36,7 @@ require 'rubygems'
29
36
  require 'xeroizer'
30
37
 
31
38
  # Create client (used to communicate with the API).
32
- client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
39
+ client = Xeroizer::OAuth2Application.new(YOUR_OAUTH2_CLIENT_ID, YOUR_OAUTH2_CLIENT_SECRET)
33
40
 
34
41
  # Retrieve list of contacts (note: all communication must be made through the client).
35
42
  contacts = client.Contact.all(:order => 'Name')
@@ -38,55 +45,6 @@ contacts = client.Contact.all(:order => 'Name')
38
45
  Authentication
39
46
  --------------
40
47
 
41
- Xero uses OAuth to authenticate API clients. The OAuth gem (with minor modification) by John Nunemaker ([http://github.com/jnunemaker/twitter](http://github.com/jnunemaker/twitter)) is used in this library. If you've used this before, things will all seem very familar.
42
-
43
- There are three methods of authentication detailed below:
44
-
45
- ### All: Consumer Key/Secret
46
-
47
- All methods of authentication require your OAuth consumer key and secret. This can be found for your application
48
- in the API management console at [http://api.xero.com](http://api.xero.com).
49
-
50
- ### Public Applications
51
-
52
- Public applications use a 3-legged authorisation process. A user will need to authorise your
53
- application against each organisation that you want access to. Your application can have access
54
- to many organisations at once by going through the authorisation process for each organisation.
55
-
56
- The access token received will expire after 30 minutes. If you want access for longer you will need
57
- the user to re-authorise your application.
58
-
59
- Authentication occurs in 3 steps:
60
-
61
- ```ruby
62
- client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
63
-
64
- # 1. Get a RequestToken from Xero. :oauth_callback is the URL the user will be redirected to
65
- # after they have authenticated your application.
66
- #
67
- # Note: The callback URL's domain must match that listed for your application in http://api.xero.com
68
- # otherwise the user will not be redirected and only be shown the authentication code.
69
- request_token = client.request_token(:oauth_callback => 'http://yourapp.com/oauth/callback')
70
-
71
- # 2. Redirect the user to the URL specified by the RequestToken.
72
- #
73
- # Note: example uses redirect_to method defined in Rails controllers.
74
- redirect_to request_token.authorize_url
75
-
76
- # 3. Exchange RequestToken for AccessToken.
77
- # This access token will be used for all subsequent requests but it is stored within the client
78
- # application so you don't have to record it.
79
- #
80
- # Note: This example assumes the callback URL is a Rails action.
81
- client.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
82
- ```
83
-
84
- You can now use the client to access the Xero API methods, e.g.
85
-
86
- ```ruby
87
- contacts = client.Contact.all
88
- ```
89
-
90
48
  #### Example Rails Controller
91
49
 
92
50
  ```ruby
@@ -97,25 +55,32 @@ class XeroSessionController < ApplicationController
97
55
  public
98
56
 
99
57
  def new
100
- request_token = @xero_client.request_token(:oauth_callback => 'http://yourapp.com/xero_session/create')
101
- session[:request_token] = request_token.token
102
- session[:request_secret] = request_token.secret
103
-
104
- redirect_to request_token.authorize_url
58
+ url = @xero_client.authorize_url(
59
+ # The URL's domain must match that listed for your application
60
+ # otherwise the user will see an invalid redirect_uri error
61
+ redirect_uri: YOUR_CALLBACK_URL,
62
+ # space separated, see all scopes at https://developer.xero.com/documentation/oauth2/scopes.
63
+ # note that `offline_access` is required to get a refresh token, otherwise the access only lasts for 30 mins and cannot be refreshed.
64
+ scope: "accounting.settings.read offline_access"
65
+ )
66
+
67
+ redirect_to url
105
68
  end
106
69
 
107
70
  def create
108
- @xero_client.authorize_from_request(
109
- session[:request_token],
110
- session[:request_secret],
111
- :oauth_verifier => params[:oauth_verifier] )
71
+ token = @xero_client.authorize_from_code(
72
+ params[:code],
73
+ redirect_uri: YOUR_CALLBACK_URL
74
+ )
75
+
76
+ connections = @xero_client.current_connections
112
77
 
113
78
  session[:xero_auth] = {
114
- :access_token => @xero_client.access_token.token,
115
- :access_key => @xero_client.access_token.secret }
79
+ :access_token => token[:access_token],
80
+ :refresh_token => token[:refresh_token],
81
+ :tenant_id => connections[1][:tenant_id]
82
+ }
116
83
 
117
- session.data.delete(:request_token)
118
- session.data.delete(:request_secret)
119
84
  end
120
85
 
121
86
  def destroy
@@ -125,150 +90,130 @@ class XeroSessionController < ApplicationController
125
90
  private
126
91
 
127
92
  def get_xero_client
128
- @xero_client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
93
+ @xero_client = Xeroizer::OAuth2Application.new(
94
+ YOUR_OAUTH2_CLIENT_ID,
95
+ YOUR_OAUTH2_CLIENT_SECRET,
96
+ )
129
97
 
130
98
  # Add AccessToken if authorised previously.
131
99
  if session[:xero_auth]
132
- @xero_client.authorize_from_access(
133
- session[:xero_auth][:access_token],
134
- session[:xero_auth][:access_key] )
100
+ @xero_client.tenant_id = session[:xero_auth][:tenant_id]
101
+
102
+ @xero_client.authorize_from_access(session[:xero_auth][:acesss_token])
135
103
  end
136
104
  end
137
105
  end
138
106
  ```
139
107
 
140
- #### Storing AccessToken
141
-
142
- You can store the access token/secret pair so you can access the API again without user intervention. Currently these
143
- tokens are only valid for 30 minutes and will raise a `Xeroizer::OAuth::TokenExpired` exception if you try to access
144
- the API beyond the token's expiry time.
108
+ ### OAuth2 Applications
145
109
 
146
- If you want API access for longer consider creating a PartnerApplication which will allow you to renew tokens.
110
+ For more details, checkout Xero's [documentation](https://developer.xero.com/documentation/oauth2/auth-flow)
147
111
 
112
+ 1. Generate the authorization url and redirect the user to authenticate
148
113
  ```ruby
149
- access_key = client.access_token.token
150
- access_secret = client.access_token.secret
151
- ```
152
-
153
- ### Private Applications
154
-
155
- Private applications use a 2-legged authorisation process. When you register your application, you will select
156
- the organisation that is authorised to your application. This cannot be changed afterwards, although you can
157
- register another private application if you have multiple organisations.
158
-
159
- Note: You can only register organisations you are authorised to yourself.
160
-
161
- Private applications require a private RSA keypair which is used to sign each request to the API. You can
162
- generate this keypair on Mac OSX or Linux with OpenSSL. For example:
163
-
164
- openssl genrsa -out privatekey.pem 1024
165
- openssl req -newkey rsa:1024 -x509 -key privatekey.pem -out publickey.cer -days 365
166
- openssl pkcs12 -export -out public_privatekey.pfx -inkey privatekey.pem -in publickey.cer
167
-
168
- You need to upload this `public_privatekey.pfx` file to your private application in [http://api.xero.com](http://api.xero.com).
169
-
170
- Example usage:
114
+ client = Xeroizer::OAuth2Application.new(
115
+ YOUR_OAUTH2_CLIENT_ID,
116
+ YOUR_OAUTH2_CLIENT_SECRET,
117
+ )
118
+ url = client.authorize_url(
119
+ # The URL's domain must match that listed for your application
120
+ # otherwise the user will see an invalid redirect_uri error
121
+ redirect_uri: YOUR_CALLBACK_URL,
122
+ # space separated, see all scopes at https://developer.xero.com/documentation/oauth2/scopes.
123
+ # note that `offline_access` is required to get a refresh token, otherwise the access only lasts for 30 mins and cannot be refreshed.
124
+ scope: "accounting.settings.read offline_access"
125
+ )
171
126
 
172
- ```ruby
173
- client = Xeroizer::PrivateApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET, "/path/to/privatekey.pem")
174
- contacts = client.Contact.all
127
+ # Rails as an example
128
+ redirect_to url
175
129
  ```
176
130
 
177
- To provide a private key directly, set the path to nil and pass in a `private_key` option instead. For example:
131
+ 2. In the callback route, use the provided code to retrieve an access token.
178
132
 
179
133
  ```ruby
180
- # Using environment variables (e.g. Heroku):
181
- client = Xeroizer::PrivateApplication.new(key, secret, nil, private_key: ENV["XERO_PRIVATE_KEY"])
134
+ token = client.authorize_from_code(
135
+ params[:code],
136
+ redirect_uri: YOUR_CALLBACK_URL
137
+ )
138
+ token.to_hash
139
+ # {
140
+ # "token_type"=>"Bearer",
141
+ # "scope"=>"accounting.transactions.read accounting.settings.read",
142
+ # :access_token=>"...",
143
+ # :refresh_token=>nil,
144
+ # :expires_at=>1615220292
145
+ # }
182
146
 
183
- # Using Rails Credentials (Rails 5.2+):
184
- client = Xeroizer::PrivateApplication.new(key, secret, nil, private_key: Rails.application.credentials.xero_private_key)
147
+ # Save the access_token, refresh_token...
185
148
  ```
186
149
 
187
- ### Partner Applications
188
-
189
- Partner applications use a combination of 3-legged authorisation and private key message signing.
190
-
191
- Visit the [https://developer.xero.com/partner/app-partner](Becoming an app partner) page to get permission to create a partner application.
192
-
193
- After you have followed the instructions provided by Xero for partner applications and uploaded your certificate you can
194
- access the partner application in a similar way to public applications.
195
-
196
- Authentication occcurs in 3 steps:
197
-
150
+ 3. Retrieve the tenant ids.
198
151
  ```ruby
199
- client = Xeroizer::PartnerApplication.new(
200
- YOUR_OAUTH_CONSUMER_KEY,
201
- YOUR_OAUTH_CONSUMER_SECRET,
202
- "/path/to/privatekey.pem"
203
- )
152
+ connections = client.current_connections
153
+ # returns Xeroizer::Connection instances
204
154
 
205
- # 1. Get a RequestToken from Xero. :oauth_callback is the URL the user will be redirected to
206
- # after they have authenticated your application.
207
- #
208
- # Note: The callback URL's domain must match that listed for your application in http://api.xero.com
209
- # otherwise the user will not be redirected and only be shown the authentication code.
210
- request_token = client.request_token(:oauth_callback => 'http://yourapp.com/oauth/callback')
155
+ # Save the tenant ids
211
156
 
212
- # 2. Redirect the user to the URL specified by the RequestToken.
213
- #
214
- # Note: example uses redirect_to method defined in Rails controllers.
215
- redirect_to request_token.authorize_url
216
-
217
- # 3. Exchange RequestToken for AccessToken.
218
- # This access token will be used for all subsequent requests but it is stored within the client
219
- # application so you don't have to record it.
220
- #
221
- # Note: This example assumes the callback URL is a Rails action.
222
- client.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
223
157
  ```
224
158
 
225
- This AccessToken will last for 30 minutes however, when using the partner application API you can
226
- renew this token. To be able to renew this token, you need to save the following data from this organisation's
227
- AccessToken:
228
-
159
+ 4. Use access token and tenant ids to retrieve data.
229
160
  ```ruby
230
- session_handle = client.session_handle
231
- access_key = client.access_token.token
232
- access_secret = client.access_token.secret
233
- ```
234
-
235
- Two other interesting attributes of the PartnerApplication client are:
161
+ client = Xeroizer::OAuth2Application.new(
162
+ YOUR_OAUTH2_CLIENT_ID,
163
+ YOUR_OAUTH2_CLIENT_SECRET,
164
+ access_token: access_token,
165
+ tenant_id: tenant_id
166
+ )
167
+ # OR
168
+ client = Xeroizer::OAuth2Application.new(
169
+ YOUR_OAUTH2_CLIENT_ID,
170
+ YOUR_OAUTH2_CLIENT_SECRET,
171
+ tenant_id: tenant_id
172
+ ).authorize_from_access(access_token)
236
173
 
237
- > **`#expires_at`**: Time this AccessToken will expire (usually 30 minutes into the future).
238
- > **`#authorization_expires_at`**: How long this organisation has authorised you to access their data (usually 10 years into the future).
174
+ # use the client
175
+ client.Organisation.first
176
+ ```
239
177
 
240
178
  #### AccessToken Renewal
241
-
242
- Renewal of an access token requires knowledge of the previous access token generated for this organisation. To renew:
179
+ Renewal of an access token requires the refresh token generated for this organisation. To renew:
243
180
 
244
181
  ```ruby
245
- # If you still have a client instance.
246
- client.renew_access_token
182
+ client = Xeroizer::OAuth2Application.new(
183
+ YOUR_OAUTH2_CLIENT_ID,
184
+ YOUR_OAUTH2_CLIENT_SECRET,
185
+ access_token: access_token,
186
+ refresh_token: refresh_token,
187
+ tenant_id: tenant_id
188
+ )
247
189
 
248
- # If you are renewing from stored token/session details.
249
- client.renew_access_token(access_token, access_secret, session_handle)
190
+ client.renew_access_token
250
191
  ```
192
+ If you lose these details at any stage you can always reauthorise by redirecting the user back to the Xero OAuth gateway.
251
193
 
252
- This will invalidate the previous token and refresh the `access_key` and `access_secret` as specified in the
253
- initial authorisation process. You must always know the previous token's details to renew access to this
254
- session.
194
+ #### Custom Connections
195
+ Custom Connections are a paid-for option for private M2M applications. The generated token expires and needs recreating if expired.
255
196
 
256
- If you lose these details at any stage you can always reauthorise by redirecting the user back to the Xero OAuth gateway.
197
+ ```ruby
198
+ client = Xeroizer::OAuth2Application.new(
199
+ YOUR_OAUTH2_CLIENT_ID,
200
+ YOUR_OAUTH2_CLIENT_SECRET
201
+ )
257
202
 
258
- #### Branding Themes API
203
+ token = client.authorize_from_client_credentials
204
+ ```
205
+ You can check the status of the token with the `expires?` and `expired?` methods.
259
206
 
260
- Once you are approved as a Xero Partner you can request unofficial documentation to do with customizing Payment Services and Branding Themes using the API. There is more info on that [here]( https://github.com/waynerobinson/xeroizer/pull/439).
261
207
 
262
208
  Retrieving Data
263
209
  ---------------
264
210
 
265
211
  Each of the below record types is implemented within this library. To allow for multiple access tokens to be used at the same
266
- time in a single application, the model classes are accessed from the instance of PublicApplication, PrivateApplication
267
- or PartnerApplication. All class-level operations occur on this singleton. For example:
212
+ time in a single application, the model classes are accessed from the instance of OAuth2Application. All class-level operations occur on this singleton. For example:
268
213
 
269
214
  ```ruby
270
- xero = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
271
- xero.authorize_from_access(session[:xero_auth][:access_token], session[:xero_auth][:access_key])
215
+ xero = Xeroizer::OAuth2Application.new(YOUR_OAUTH2_CLIENT_ID, YOUR_OAUTH2_CLIENT_SECRET, tenant_id: tenant_id)
216
+ xero.authorize_from_access(session[:xero_auth][:access_token])
272
217
 
273
218
  contacts = xero.Contact.all(:order => 'Name')
274
219
 
@@ -648,8 +593,8 @@ You can set this option when initializing an application:
648
593
 
649
594
  ```ruby
650
595
  # Sleep for 2 seconds every time the rate limit is exceeded.
651
- client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY,
652
- YOUR_OAUTH_CONSUMER_SECRET,
596
+ client = Xeroizer::OAuth2Application.new(YOUR_OAUTH2_CLIENT_ID,
597
+ YOUR_OAUTH2_CLIENT_SECRET,
653
598
  :rate_limit_sleep => 2)
654
599
  ```
655
600
 
@@ -666,8 +611,8 @@ You can set this option when initializing an application:
666
611
 
667
612
  ```ruby
668
613
  # Sleep for 1 second and retry up to 3 times when Xero claims the nonce was used.
669
- client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY,
670
- YOUR_OAUTH_CONSUMER_SECRET,
614
+ client = Xeroizer::OAuth2Application.new(YOUR_OAUTH2_CLIENT_ID,
615
+ YOUR_OAUTH2_CLIENT_SECRET,
671
616
  :nonce_used_max_attempts => 3)
672
617
  ```
673
618
 
@@ -679,8 +624,8 @@ You can add an optional parameter to the Xeroizer Application initialization, to
679
624
 
680
625
  ```ruby
681
626
  XeroLogger = Logger.new('log/xero.log', 'weekly')
682
- client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY,
683
- YOUR_OAUTH_CONSUMER_SECRET,
627
+ client = Xeroizer::OAuth2Application.new(YOUR_OAUTH2_CLIENT_ID,
628
+ YOUR_OAUTH2_CLIENT_SECRET,
684
629
  :logger => XeroLogger)
685
630
  ```
686
631
 
@@ -692,7 +637,7 @@ time Xeroizer makes an HTTP request, which is potentially useful for both
692
637
  throttling and logging:
693
638
 
694
639
  ```ruby
695
- Xeroizer::PublicApplication.new(
640
+ Xeroizer::OAuth2Application.new(
696
641
  credentials[:key], credentials[:secret],
697
642
  before_request: ->(request) { puts "Hitting this URL: #{request.url}" },
698
643
  after_request: ->(request, response) { puts "Got this response: #{response.code}" },
@@ -711,8 +656,8 @@ By default, the API accepts unit prices (UnitAmount) to two decimals places. If
711
656
 
712
657
 
713
658
  ```ruby
714
- client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY,
715
- YOUR_OAUTH_CONSUMER_SECRET,
659
+ client = Xeroizer::OAuth2Application.new(YOUR_OAUTH2_CLIENT_ID,
660
+ YOUR_OAUTH2_CLIENT_SECRET,
716
661
  :unitdp => 4)
717
662
  ```
718
663
 
@@ -721,23 +666,19 @@ This option adds the unitdp=4 query string parameter to all requests for models
721
666
  Tests
722
667
  -----
723
668
 
724
- The tests within the repository can be run by setting up a [Private App](https://developer.xero.com/documentation/auth-and-limits/private-applications). You can create a Private App in the [developer portal](https://developer.xero.com/myapps/), it's suggested that you create it against the [Demo Company (AU)](https://developer.xero.com/documentation/getting-started/development-accounts). Demo Company expires after 28 days, so you will need to reset it and create a new Private App if you Demo Company has expired. Make sure you create the Demo Company in Australia region.
725
-
726
- Once you have created your Private App, set these environment variables:
727
- ```
728
- EXPORT CONSUMER_KEY="your private app's consumer key"
729
- EXPORT CONSUMER_SECRET="your private app's consumer secret"
730
- EXPORT PRIVATE_KEY_PATH="the path to your private app's private key"
731
- ```
669
+ OAuth2 Tests
732
670
 
733
- PRIVATE_KEY_PATH is the path to the private key for your Private App (you uploaded the Public Key when you created the Private App)
671
+ The tests within the repository can be run by setting up a [OAuth2 App](https://developer.xero.com/documentation/guides/oauth2/auth-flow/). You can create a Private App in the [developer portal](https://developer.xero.com/myapps/), it's suggested that you create it against the [Demo Company (AU)](https://developer.xero.com/documentation/getting-started/development-accounts). Demo Company expires after 28 days, so you will need to reset it and re-connect to it if your Demo Company has expired. Make sure you create the Demo Company in Australia region.
734
672
 
735
- Then run the tests
736
673
  ```
674
+ export XERO_CLIENT_ID="asd"
675
+ export XERO_CLIENT_SECRET="asdfg"
676
+ export XERO_ACCESS_TOKEN="sadfsdf"
677
+ export XERO_TENANT_ID="asdfasdfasdfasd"
678
+
737
679
  rake test
738
680
  ```
739
681
 
740
-
741
682
  ### Contributors
742
683
  Xeroizer was inspired by the https://github.com/tlconnor/xero_gateway gem created by Tim Connor
743
684
  and Nik Wakelin and portions of the networking and authentication code are based completely off
@@ -0,0 +1,49 @@
1
+ module Xeroizer
2
+ class Connection
3
+ attr_accessor :attributes
4
+ attr_reader :parent
5
+
6
+ class << self
7
+ def current_connections(client)
8
+ response = do_request(client)
9
+
10
+ if response.success?
11
+ JSON.parse(response.plain_body).map do |connection_json|
12
+ build(connection_json, client)
13
+ end
14
+ else
15
+ raise Xeroizer::OAuth::TokenInvalid, response.plain_body
16
+ end
17
+ end
18
+
19
+ def build(attributes, parent)
20
+ record = new(parent)
21
+ record.attributes = attributes
22
+ record
23
+ end
24
+
25
+ private
26
+
27
+ def do_request(client)
28
+ client.get('https://api.xero.com/connections')
29
+ end
30
+ end
31
+
32
+ def initialize(parent)
33
+ @parent = parent
34
+ @attributes = {}
35
+ end
36
+
37
+ def method_missing(name, *_args)
38
+ @attributes.send(:[], name.to_s.camelcase(:lower))
39
+ end
40
+
41
+ def delete
42
+ parent.delete("https://api.xero.com/connections/#{id}")
43
+ end
44
+
45
+ def to_h
46
+ attributes.transform_keys(&:underscore)
47
+ end
48
+ end
49
+ end
@@ -155,5 +155,7 @@ module Xeroizer
155
155
  end
156
156
 
157
157
  end
158
+
159
+ class InvalidClientError < XeroizerError; end
158
160
 
159
161
  end
@@ -6,9 +6,11 @@ module Xeroizer
6
6
  include Http
7
7
  extend Record::ApplicationHelper
8
8
 
9
- attr_reader :client, :xero_url, :logger, :rate_limit_sleep, :rate_limit_max_attempts,
9
+ attr_reader :client, :logger, :rate_limit_sleep, :rate_limit_max_attempts,
10
10
  :default_headers, :unitdp, :before_request, :after_request, :around_request, :nonce_used_max_attempts
11
11
 
12
+ attr_accessor :xero_url
13
+
12
14
  extend Forwardable
13
15
  def_delegators :client, :access_token
14
16
 
@@ -26,6 +28,7 @@ module Xeroizer
26
28
  record :ExpenseClaim
27
29
  record :Invoice
28
30
  record :InvoiceReminder
31
+ record :HistoryRecord
29
32
  record :OnlineInvoice
30
33
  record :Item
31
34
  record :Journal
@@ -37,6 +40,7 @@ module Xeroizer
37
40
  record :Prepayment
38
41
  record :Overpayment
39
42
  record :PurchaseOrder
43
+ record :Quote
40
44
  record :Receipt
41
45
  record :RepeatingInvoice
42
46
  record :Schedule
@@ -63,7 +67,8 @@ module Xeroizer
63
67
  # @see PublicApplication
64
68
  # @see PrivateApplication
65
69
  # @see PartnerApplication
66
- def initialize(consumer_key, consumer_secret, options = {})
70
+ def initialize(client, options = {})
71
+ raise Xeroizer::InvalidClientError.new unless [OAuth, OAuth2].member?(client.class)
67
72
  @xero_url = options[:xero_url] || "https://api.xero.com/api.xro/2.0"
68
73
  @rate_limit_sleep = options[:rate_limit_sleep] || false
69
74
  @rate_limit_max_attempts = options[:rate_limit_max_attempts] || 5
@@ -72,7 +77,7 @@ module Xeroizer
72
77
  @before_request = options.delete(:before_request)
73
78
  @after_request = options.delete(:after_request)
74
79
  @around_request = options.delete(:around_request)
75
- @client = OAuth.new(consumer_key, consumer_secret, options.merge({default_headers: default_headers}))
80
+ @client = client
76
81
  @logger = options[:logger] || false
77
82
  @unitdp = options[:unitdp] || 2
78
83
  end