xeroizer 2.20.0 → 3.0.0

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