levelup 0.9.2 → 0.9.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fffe35cc46fcd692944cc88cceb1685b374cec2f
4
- data.tar.gz: fc77b72ad732430eae0d59cc57149293d5139ff4
3
+ metadata.gz: 238e90b50ace8d0dda415d36dcd75b7d0af2023f
4
+ data.tar.gz: a6d9b1a494b008804eafece8a06e45a788c61dd3
5
5
  SHA512:
6
- metadata.gz: 0ea9f4468368ea50a351f85538c6017cb959bf682ea53e64fa5763b18f0945d44907094caf073a4cbf28813f0029e8e177a83856820f57a92e0d01d079586f34
7
- data.tar.gz: 76119e8ab76d59bfd30c9069b2886237bc7d83778dd8d469338efe078898bebf25d71c2ca1b80ae2c7f07cccd40d3c0cfb04084436b2081801e461b24010773d
6
+ metadata.gz: 32ccd34e752ccdd08d5e474a68522bc16259dd4d50341f6550bbdcedc68196a00854bdc2a40928d71b1316073ad637830f3215fd6688e39fab33da17579a3006
7
+ data.tar.gz: 4779600aa8094b8af4fca1a07d5580feffe665e5fa0b76f8b2a17c5821c36e78107de0219a31450bdf36654c7f34f1a07b2603d2c0bd3349291c8717044bcb34
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- levelup (0.9.2)
4
+ levelup (0.9.3)
5
5
  httparty (~> 0.13.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -73,8 +73,28 @@ response = api.orders.create(
73
73
  user_access_token: 'user-token')
74
74
  ```
75
75
 
76
- All other functions of the Ruby SDK mirror the v15 LevelUp API described at http://developer.thelevelup.com/
77
- as well as a very small number of v14 endpoints.
76
+ The LevelUp Ruby SDK mirrors the API as closely as possible, so the call for any given endpoint can be inferred from its URL.
77
+ For instance:
78
+ ```ruby
79
+ api.apps.permissions_requests.create # points to /v15/apps/permissions_requests/ POST
80
+ api.user_addresses.list # points to /v15/user_addresses/ GET
81
+ api.orders(uuid).refund # points to /v15/orders/:uuid/refund/ POST
82
+ ```
83
+
84
+ ## Pagination
85
+
86
+ Some requests that return large lists are paginated and only return a small number of values per request.
87
+ The LevelUp Ruby SDK handles this by allowing you to request the next page from the paginated response.
88
+
89
+ For instance:
90
+ ```ruby
91
+ locs_response = api.apps(123).locations.list # gets a page of locations associated with an app
92
+ locs_response.locations # => [location 1, location 2...location 10]
93
+
94
+ locs_response.next_page? # => true if there is another page of results to load
95
+
96
+ next_page_response = locs_response.next # gets the next page of results
97
+ ```
78
98
 
79
99
  ## Errors
80
100
 
@@ -6,6 +6,7 @@ require 'levelup/configuration'
6
6
 
7
7
  require 'levelup/templates/data_parcel'
8
8
  require 'levelup/templates/user_address_data'
9
+ require 'levelup/templates/app_authenticated'
9
10
  require 'levelup/templates/merchant_authenticated'
10
11
  require 'levelup/templates/merchant_and_user_authenticated'
11
12
  require 'levelup/templates/user_authenticated'
@@ -21,6 +22,7 @@ require 'levelup/requests/get_order'
21
22
  require 'levelup/requests/get_qr_code'
22
23
  require 'levelup/requests/get_user'
23
24
  require 'levelup/requests/give_merchant_credit'
25
+ require 'levelup/requests/list_app_locations'
24
26
  require 'levelup/requests/list_addresses'
25
27
  require 'levelup/requests/list_locations'
26
28
  require 'levelup/requests/list_orders'
@@ -30,10 +32,12 @@ require 'levelup/requests/request_permissions'
30
32
  require 'levelup/requests/show_permissions_request'
31
33
 
32
34
  require 'levelup/responses/success'
35
+ require 'levelup/responses/success_paginated'
33
36
  require 'levelup/responses/error'
34
37
 
35
38
  require 'levelup/endpoints/base'
36
39
  require 'levelup/endpoints/access_tokens'
40
+ require 'levelup/endpoints/app_locations'
37
41
  require 'levelup/endpoints/app_users'
38
42
  require 'levelup/endpoints/apps'
39
43
  require 'levelup/endpoints/credit_cards'
@@ -44,6 +48,7 @@ require 'levelup/endpoints/merchant_orders'
44
48
  require 'levelup/endpoints/orders'
45
49
  require 'levelup/endpoints/permissions_requests'
46
50
  require 'levelup/endpoints/qr_codes'
51
+ require 'levelup/endpoints/specific_app'
47
52
  require 'levelup/endpoints/specific_location'
48
53
  require 'levelup/endpoints/specific_merchant'
49
54
  require 'levelup/endpoints/specific_order'
@@ -30,8 +30,12 @@ module Levelup
30
30
  end
31
31
 
32
32
  # Generates an interface for the +apps+ endpoint.
33
- def apps
34
- Endpoints::Apps.new(app_access_token)
33
+ def apps(app_id = nil)
34
+ if app_id
35
+ Endpoints::SpecificApp.new(app_id)
36
+ else
37
+ Endpoints::Apps.new(app_access_token)
38
+ end
35
39
  end
36
40
 
37
41
  # Verifies if an access token is present for app-authenticated endpoints
@@ -1,6 +1,6 @@
1
1
  module Levelup
2
2
  class Configuration
3
- VERSION = '0.9.2'
3
+ VERSION = '0.9.3'
4
4
  DEFAULT_API_VERSION = :v15
5
5
 
6
6
  class << self
@@ -0,0 +1,27 @@
1
+ module Levelup
2
+ module Endpoints
3
+ # The endpoint holding all functions relating to a specific app's locations.
4
+ # This endpoint is a v14 endpoint and should not be expected to remain
5
+ # accessible indefinitely.
6
+ class AppLocations < Base
7
+ def initialize(id)
8
+ self.id = id
9
+ end
10
+
11
+ # Provides a list of locations controlled by this app. This list is
12
+ # paginated.
13
+ def list
14
+ request = Requests::ListAppLocations.new
15
+ request.send_to_api(:get, endpoint_path(:v14))
16
+ end
17
+
18
+ private
19
+
20
+ attr_accessor :id
21
+
22
+ def path
23
+ "apps/#{id}/locations"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -4,7 +4,7 @@ module Levelup
4
4
  # requests.
5
5
  class PermissionsRequests < Base
6
6
  def initialize(app_access_token)
7
- @app_access_token = app_access_token
7
+ self.app_access_token = app_access_token
8
8
  end
9
9
 
10
10
  # Requests a set of permissions from the specified user.
@@ -18,7 +18,7 @@ module Levelup
18
18
 
19
19
  private
20
20
 
21
- attr_reader :app_access_token
21
+ attr_accessor :app_access_token
22
22
 
23
23
  def path
24
24
  'apps/permissions_requests'
@@ -0,0 +1,23 @@
1
+ module Levelup
2
+ module Endpoints
3
+ # The endpoint serving as a bucket for all functions related to a specific
4
+ # app.
5
+ class SpecificApp < Base
6
+ def initialize(id)
7
+ self.id = id
8
+ end
9
+
10
+ def locations
11
+ AppLocations.new(id)
12
+ end
13
+
14
+ private
15
+
16
+ attr_accessor :id
17
+
18
+ def path
19
+ "apps/#{id}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,9 +2,8 @@ module Levelup
2
2
  module Endpoints
3
3
  # Endpoint holding all functions relating to a specified order.
4
4
  class SpecificOrder < Base
5
- attr_reader :uuid
6
5
  def initialize(order_uuid)
7
- @uuid = order_uuid
6
+ self.uuid = order_uuid
8
7
  end
9
8
 
10
9
  # Refunds the order specified by this endpoint.
@@ -20,6 +19,8 @@ module Levelup
20
19
 
21
20
  private
22
21
 
22
+ attr_accessor :uuid
23
+
23
24
  def path
24
25
  "orders/#{uuid}"
25
26
  end
@@ -8,9 +8,9 @@ module Levelup
8
8
  self.request_id = request_id
9
9
  end
10
10
 
11
- def show
11
+ def show(app_token = nil)
12
12
  request = Requests::ShowPermissionsRequest.
13
- new(app_access_token: app_access_token)
13
+ new(app_access_token: app_access_token || app_token)
14
14
  request.send_to_api(:get, endpoint_path)
15
15
  end
16
16
 
@@ -40,10 +40,22 @@ module Levelup
40
40
  raise NotImplementedError, 'Response generator not defined.'
41
41
  end
42
42
 
43
- # Makes a call by the specified method to the specified endpoint, sending
44
- # this request object. If successful, builds a response object according
45
- # to response_from_hash. If unsuccessful, simply returns an ErrorResponse.
43
+ # Calls send_via_httparty, returning either an error response or the
44
+ # response as generated by this request's response_from_hash function.
45
+ # This function can be overridden to control how a request builds its
46
+ # response.
46
47
  def send_to_api(method, endpoint)
48
+ send_via_httparty(method, endpoint) do |response|
49
+ response_from_hash(response.parsed_response)
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Makes a call by the specified method to the specified endpoint, sending
56
+ # this request object. If successful, yields the HTTParty response to the
57
+ # calling method. If unsuccessful, simply returns an ErrorResponse.
58
+ def send_via_httparty(method, endpoint)
47
59
  unless ALLOWED_REQUEST_METHODS.include?(method)
48
60
  raise Errors::InvalidRequest, 'Attempted to send a request to'\
49
61
  " LevelUp API via invalid method #{method}"
@@ -53,15 +65,13 @@ module Levelup
53
65
  body: JSON.generate(body), headers: headers)
54
66
 
55
67
  if response.success?
56
- response_from_hash(response.parsed_response)
68
+ yield response
57
69
  else
58
70
  Responses::Error.new(response.headers, response.parsed_response,
59
71
  response.code)
60
72
  end
61
73
  end
62
74
 
63
- private
64
-
65
75
  DEFAULT_HEADERS = {
66
76
  'Accept' => 'application/json',
67
77
  'Content-Type' => 'application/json'
@@ -15,7 +15,11 @@ module Levelup
15
15
  attr_accessor :spend_amount
16
16
 
17
17
  def body
18
- items = @items.map do |item|
18
+ items = (@items || []).map do |item|
19
+ if item.empty?
20
+ next
21
+ end
22
+
19
23
  { item: item }
20
24
  end
21
25
 
@@ -3,7 +3,7 @@ module Levelup
3
3
  # Represents a request to create a new user with the specified list of
4
4
  # permissions.
5
5
  class CreateUser < Base
6
- attr_accessor :app_access_token
6
+ include Templates::AppAuthenticated
7
7
  # An array of Item objects (or hashes representing them) representing all
8
8
  # items purchased by this order.
9
9
  attr_accessor :email
@@ -11,10 +11,6 @@ module Levelup
11
11
  attr_accessor :last_name
12
12
  attr_accessor :permission_keynames
13
13
 
14
- def auth_type
15
- :app
16
- end
17
-
18
14
  def body
19
15
  user_hash = {
20
16
  email: email,
@@ -7,10 +7,6 @@ module Levelup
7
7
  include Templates::MerchantAuthenticated
8
8
  attr_accessor :email, :value_amount
9
9
 
10
- def auth_type
11
- :merchant
12
- end
13
-
14
10
  def body
15
11
  { merchant_funded_credit: to_hash }
16
12
  end
@@ -0,0 +1,35 @@
1
+ module Levelup
2
+ module Requests
3
+ # Represents a request to list all locations under
4
+ # a specified app. The list is paginated.
5
+ class ListAppLocations < Base
6
+ def auth_type
7
+ :none
8
+ end
9
+
10
+ def response_from_hash(hash)
11
+ if hash.nil? # no locations found for this app
12
+ Responses::SuccessPaginated.new(locations: [])
13
+ else
14
+ locations =
15
+ hash.map { |location| OpenStruct.new(location['location']) }
16
+ Responses::SuccessPaginated.new(locations: locations)
17
+ end
18
+ end
19
+
20
+ def send_to_api(method, endpoint)
21
+ send_via_httparty(method, endpoint) do |response|
22
+ paginated_response = response_from_hash(response)
23
+
24
+ if response.headers['Link']
25
+ paginated_response.next_page =
26
+ /\<([^>]+)\>/.match(response.headers['Link'])[1]
27
+ paginated_response.next_page_request = ListAppLocations.new
28
+ end
29
+
30
+ paginated_response
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -3,7 +3,7 @@ module Levelup
3
3
  # Represents a request to request a set of permissions
4
4
  # from a specified account (merchant or user).
5
5
  class RequestPermissions < Base
6
- attr_accessor :app_access_token
6
+ include Templates::AppAuthenticated
7
7
  # The email address of the requested user or merchant.
8
8
  attr_accessor :email
9
9
  # An array of strings representing desired permissions from the user or
@@ -11,10 +11,6 @@ module Levelup
11
11
  # 'manage_merchant_orders'
12
12
  attr_accessor :permission_keynames
13
13
 
14
- def auth_type
15
- :app
16
- end
17
-
18
14
  def body
19
15
  { permissions_request: to_hash }
20
16
  end
@@ -3,11 +3,7 @@ module Levelup
3
3
  # Represents a request to show the status of a specified permissions
4
4
  # request.
5
5
  class ShowPermissionsRequest < Base
6
- attr_accessor :app_access_token
7
-
8
- def auth_type
9
- :app
10
- end
6
+ include Templates::AppAuthenticated
11
7
 
12
8
  def body
13
9
  {}
@@ -21,7 +21,8 @@ module Levelup
21
21
  OpenStruct.new(error['error'])
22
22
  end
23
23
  else
24
- @errors = [{ message: 'Could not parse error body' }]
24
+ @errors = [OpenStruct.new(message: 'The API returned an unexpected '\
25
+ 'response. This is likely due to an incorrectly defined base URL.')]
25
26
  end
26
27
 
27
28
  @status_code = status_code
@@ -0,0 +1,26 @@
1
+ module Levelup
2
+ module Responses
3
+ # Class that encapsulates a successful response from a paginated endpoint
4
+ # of the LevelUp API.
5
+ class SuccessPaginated < Success
6
+ attr_writer :next_page_request, :next_page
7
+
8
+ def next_page?
9
+ !next_page_request.nil? && !next_page.nil?
10
+ end
11
+
12
+ def next
13
+ unless next_page?
14
+ raise Errors::InvalidRequest, 'Attempted to fetch next page at '\
15
+ 'final page of list'
16
+ end
17
+
18
+ next_page_request.send_to_api(:get, next_page)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :next_page_request, :next_page
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ module Levelup
2
+ module Templates
3
+ # A template to apply to any requests requiring app authentication.
4
+ #
5
+ # Authentication template - only apply one authentication template per
6
+ # request.
7
+ module AppAuthenticated
8
+ # An access token for an app.
9
+ attr_accessor :app_access_token
10
+
11
+ def auth_type
12
+ :app
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Levelup::Responses::SuccessPaginated', vcr: true do
4
+ before do
5
+ example_paginated_url = "#{Levelup::Configuration.api_url(:v14)}/apps/"\
6
+ "#{TestConfig.app_id}/locations"
7
+ @has_next_response = Levelup::Responses::SuccessPaginated.new
8
+ @has_next_response.next_page = example_paginated_url
9
+ @has_next_response.next_page_request =
10
+ Levelup::Requests::ListAppLocations.new
11
+
12
+ @no_next_response = Levelup::Responses::SuccessPaginated.new
13
+ end
14
+
15
+ describe '#success?' do
16
+ it 'returns true' do
17
+ expect(@has_next_response).to be_success
18
+ end
19
+ end
20
+
21
+ describe '#next_page?' do
22
+ context 'with no next page' do
23
+ it 'returns false' do
24
+ expect(@no_next_response.next_page?).to be_false
25
+ end
26
+ end
27
+
28
+ context 'with another page to retrieve' do
29
+ it 'returns true' do
30
+ expect(@has_next_response.next_page?).to be_true
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#next' do
36
+ context 'with no next page' do
37
+ it 'raises an InvalidRequest error' do
38
+ expect { @no_next_response.next }.
39
+ to raise_error(Levelup::Errors::InvalidRequest)
40
+ end
41
+ end
42
+
43
+ context 'with a next page' do
44
+ it 'successfully returns the next page' do
45
+ next_page_response = @has_next_response.next
46
+
47
+ expect(next_page_response).to be_success
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Levelup::Endpoints::AppLocations', vcr: true do
4
+ describe '#list' do
5
+ it 'fetches a list of locations' do
6
+ response = @test_client.apps(TestConfig.app_id).locations.list
7
+
8
+ expect(response).to be_success
9
+ expect(response.locations.length).to be > 0
10
+ end
11
+
12
+ it 'fetches a second page of locations' do
13
+ next_response = @test_client.apps(TestConfig.app_id).locations.list.next
14
+
15
+ expect(next_response).to be_success
16
+ end
17
+ end
18
+ end
@@ -2,6 +2,7 @@
2
2
  api_key_valid: key
3
3
  secret_valid: secret
4
4
  location_id: 123
5
+ app_id: 456
5
6
  merchant_token_with_grant_credit_perms: token
6
7
  merchant_token_with_manage_orders_perms: token (can be same as other merchant token)
7
8
  merchant_api_key: token_v14
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: levelup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - LevelUp POS Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-19 00:00:00.000000000 Z
11
+ date: 2014-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -150,7 +150,6 @@ files:
150
150
  - ".rubocop.yml"
151
151
  - Gemfile
152
152
  - Gemfile.lock
153
- - LICENSE
154
153
  - LICENSE.txt
155
154
  - README.md
156
155
  - Rakefile
@@ -159,6 +158,7 @@ files:
159
158
  - lib/levelup/api.rb
160
159
  - lib/levelup/configuration.rb
161
160
  - lib/levelup/endpoints/access_tokens.rb
161
+ - lib/levelup/endpoints/app_locations.rb
162
162
  - lib/levelup/endpoints/app_users.rb
163
163
  - lib/levelup/endpoints/apps.rb
164
164
  - lib/levelup/endpoints/base.rb
@@ -170,6 +170,7 @@ files:
170
170
  - lib/levelup/endpoints/orders.rb
171
171
  - lib/levelup/endpoints/permissions_requests.rb
172
172
  - lib/levelup/endpoints/qr_codes.rb
173
+ - lib/levelup/endpoints/specific_app.rb
173
174
  - lib/levelup/endpoints/specific_location.rb
174
175
  - lib/levelup/endpoints/specific_merchant.rb
175
176
  - lib/levelup/endpoints/specific_order.rb
@@ -191,6 +192,7 @@ files:
191
192
  - lib/levelup/requests/get_user.rb
192
193
  - lib/levelup/requests/give_merchant_credit.rb
193
194
  - lib/levelup/requests/list_addresses.rb
195
+ - lib/levelup/requests/list_app_locations.rb
194
196
  - lib/levelup/requests/list_locations.rb
195
197
  - lib/levelup/requests/list_orders.rb
196
198
  - lib/levelup/requests/list_user_orders.rb
@@ -199,6 +201,8 @@ files:
199
201
  - lib/levelup/requests/show_permissions_request.rb
200
202
  - lib/levelup/responses/error.rb
201
203
  - lib/levelup/responses/success.rb
204
+ - lib/levelup/responses/success_paginated.rb
205
+ - lib/levelup/templates/app_authenticated.rb
202
206
  - lib/levelup/templates/data_parcel.rb
203
207
  - lib/levelup/templates/merchant_and_user_authenticated.rb
204
208
  - lib/levelup/templates/merchant_authenticated.rb
@@ -214,7 +218,9 @@ files:
214
218
  - spec/data_objects/requests/request_permissions_spec.rb
215
219
  - spec/data_objects/responses/error_spec.rb
216
220
  - spec/data_objects/responses/response_spec.rb
221
+ - spec/data_objects/responses/success_paginated_spec.rb
217
222
  - spec/endpoints/access_tokens_spec.rb
223
+ - spec/endpoints/app_locations_spec.rb
218
224
  - spec/endpoints/app_users_spec.rb
219
225
  - spec/endpoints/location_orders_spec.rb
220
226
  - spec/endpoints/merchant_funded_credits_spec.rb
@@ -264,7 +270,9 @@ test_files:
264
270
  - spec/data_objects/requests/request_permissions_spec.rb
265
271
  - spec/data_objects/responses/error_spec.rb
266
272
  - spec/data_objects/responses/response_spec.rb
273
+ - spec/data_objects/responses/success_paginated_spec.rb
267
274
  - spec/endpoints/access_tokens_spec.rb
275
+ - spec/endpoints/app_locations_spec.rb
268
276
  - spec/endpoints/app_users_spec.rb
269
277
  - spec/endpoints/location_orders_spec.rb
270
278
  - spec/endpoints/merchant_funded_credits_spec.rb
data/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2014 LevelUp
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.