whiplash-app 0.5.1 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3925f8e5706f3b3a36144ad80df98efa751630299d2bbc8f3c3a942fd75e6c8
4
- data.tar.gz: 522d2ed541e7a6a70140de1967bdcc74c1b4a0b13b329495e60fd4b2cf9c1614
3
+ metadata.gz: 216d093d7f7c804c1f6b7563a429e7d0ed70cf31e90eb56266e03c086107863a
4
+ data.tar.gz: bd62a9c2da9f0a603c13c7c40e99a0bfd1e6b48b958cd20f9c74f02613d3dd70
5
5
  SHA512:
6
- metadata.gz: ab92fa0ff5e7c87765a03c2097f0a3dd2f0cbf5d757a60cf54353511bf6571fb2811e71000880e1bcd20482b212bcfb47d8a9b8d69dfaff5b5eb1d8772d22a5b
7
- data.tar.gz: 0e3af57cdab4d9956c38dce8cf1eb55e0f1d53b05ab3e21c31a06a4bb4dc13f15ddb1ef7f886d1ea3ac45920ef0dbd3f0ea4f83e37121ce0536cf345cb2eae7f
6
+ metadata.gz: f3ee8b0c5c9817ddbc3231889abe2d4edd95873234674c8a2da66e418cc262810a5424813f8144439a43fdc40765bc6e0fab10dfcb540cf9d6e2a1896393ae58
7
+ data.tar.gz: a2281f059a7d4c227d7d6a89cedeb75e082dcdaa2fb2799e9a3f36f205881f07813530ac120718035d702476c176a11e1f58a0a084e736790ede55f7991ef00c
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.3
4
- before_install: gem install bundler -v 1.11.2
3
+ - 2.6.7
4
+ before_install: gem install bundler -v 2.2.25
@@ -65,6 +65,10 @@ class WhiplashApiError < StandardError
65
65
  class InternalServerError < WhiplashApiError
66
66
  end
67
67
 
68
+ # 502
69
+ class Timeout < WhiplashApiError
70
+ end
71
+
68
72
  # 503
69
73
  class ServiceUnavailable < WhiplashApiError
70
74
  end
@@ -88,6 +92,7 @@ class WhiplashApiError < StandardError
88
92
  429 => WhiplashApiError::OverRateLimit,
89
93
  495 => WhiplashApiError::SSLError,
90
94
  500 => WhiplashApiError::InternalServerError,
95
+ 502 => WhiplashApiError::Timeout,
91
96
  503 => WhiplashApiError::ServiceUnavailable
92
97
  }
93
98
  end
@@ -7,13 +7,13 @@ module Whiplash
7
7
  def cache_store
8
8
  if ENV["REDIS_HOST"]
9
9
  store = Moneta.new(:Redis, host: ENV["REDIS_HOST"], port: ENV["REDIS_PORT"], password: ENV["REDIS_PASSWORD"], expires: 7200)
10
- Moneta::Namespace.new store, namespace_value
10
+ Moneta::Namespace.new store, Whiplash::App::Caching.namespace_value
11
11
  else
12
12
  Moneta.new(:File, dir: "tmp", expires: 7200)
13
13
  end
14
14
  end
15
15
 
16
- def namespace_value
16
+ def self.namespace_value
17
17
  ENV["REDIS_NAMESPACE"] || ENV["WHIPLASH_CLIENT_ID"]
18
18
  end
19
19
 
@@ -2,6 +2,8 @@ module Whiplash
2
2
  class App
3
3
  module Connections
4
4
 
5
+ PER_PAGE_REQUEST_LIMIT = 50
6
+
5
7
  def base_app_request(options={})
6
8
  if options[:params][:id]
7
9
  endpoint = [options[:endpoint], options[:params].delete(:id)].join('/')
@@ -11,6 +13,7 @@ module Whiplash
11
13
  options[:headers] ||= {}
12
14
  options[:headers][:customer_id] ||= customer_id if customer_id
13
15
  options[:headers][:shop_id] ||= shop_id if shop_id
16
+ options[:headers][:version] ||= 2
14
17
 
15
18
  args = [
16
19
  options[:method],
@@ -32,7 +35,12 @@ module Whiplash
32
35
 
33
36
  def app_request!(options = {})
34
37
  begin
35
- app_request(options)
38
+ response = app_request(options)
39
+ return response if response.success?
40
+ message = response.body if response.body.is_a? String
41
+ message = response.body.dig('error') if response.body.respond_to?(:dig)
42
+ store_whiplash_error!(response.status)
43
+ error_response(response.status, message)
36
44
  rescue Faraday::ConnectionFailed => e
37
45
  case e.message
38
46
  when 'end of file reached'
@@ -49,11 +57,32 @@ module Whiplash
49
57
  raise ProviderError::InternalServerError, e.message
50
58
  end
51
59
  end
52
- return response.body if response.success?
53
- message = response.body if response.body.is_a? String
54
- message = response.body.dig('error') if response.body.respond_to?(:dig)
55
- store_whiplash_error!(response.status)
56
- error_response(response.status, message)
60
+ end
61
+
62
+ def multi_page_get!(endpoint, params = {}, headers = nil)
63
+ results = []
64
+ page = 1
65
+ params[:per_page] = PER_PAGE_REQUEST_LIMIT
66
+
67
+ loop do
68
+ partial_results_request = app_request!(
69
+ method: :get,
70
+ endpoint: endpoint,
71
+ params: params,
72
+ headers: headers
73
+ ).body
74
+
75
+ results << partial_results_request
76
+ results.flatten!
77
+
78
+ page += 1
79
+ params[:page] = page
80
+
81
+ break if partial_results_request.size == 0
82
+ break if partial_results_request.size < PER_PAGE_REQUEST_LIMIT
83
+ end
84
+
85
+ results
57
86
  end
58
87
 
59
88
  def delete(endpoint, params = {}, headers = nil)
@@ -112,10 +141,44 @@ module Whiplash
112
141
  headers: headers)
113
142
  end
114
143
 
144
+ def get_body_or_empty(endpoint, params = {}, headers = nil)
145
+ response = get(endpoint, params, headers)
146
+ if !response.success?
147
+ case response.status
148
+ when 500
149
+ Appsignal.send_error(WhiplashApiError::InternalServerError.new(response.body), {raised: false})
150
+ else
151
+ end
152
+
153
+ case get_context(endpoint)
154
+ when 'collection'
155
+ Rails.logger.info "[WhiplashApi] Returned #{response.status}. Returning an empty array..."
156
+ return []
157
+ when 'member'
158
+ Rails.logger.info "[WhiplashApi] Returned #{response.status}. Returning nil..."
159
+ return nil
160
+ when 'aggregate'
161
+ Rails.logger.info "[WhiplashApi] Returned #{response.status}. Returning an empty hash..."
162
+ return {}
163
+ end
164
+ end
165
+ response.body
166
+ end
167
+
168
+ def get_context(endpoint)
169
+ parts = endpoint.split('/').compact
170
+ return 'member' unless (parts.last =~ /\d+/).nil?
171
+ return 'aggregate' if parts.include?('aggregate')
172
+ 'collection'
173
+ end
174
+
115
175
  def sanitize_headers(headers)
116
- if headers
117
- {}.tap do |hash|
118
- headers.each do |k,v|
176
+ return if headers.nil? || headers.empty?
177
+ out = {}.tap do |hash|
178
+ headers.each do |k,v|
179
+ if k.to_s == 'version'
180
+ hash['Accept-Version'] = "v#{v}"
181
+ else
119
182
  hash["X-#{k.to_s.upcase.gsub('_','-')}"] = v.to_s
120
183
  end
121
184
  end
@@ -124,7 +187,7 @@ module Whiplash
124
187
 
125
188
  def store_whiplash_error!(error, options={})
126
189
  return unless defined?(Appsignal)
127
- options = options.with_indifferent_access
190
+ options.transform_keys!(&:to_sym)
128
191
  Appsignal.increment_counter(
129
192
  "whiplash_error",
130
193
  1.0,
@@ -15,7 +15,11 @@ module Whiplash
15
15
  private
16
16
 
17
17
  def request_body(body)
18
- body.blank? ? ENV["WHIPLASH_CLIENT_ID"] : body
18
+ begin
19
+ (body.nil? || body.empty?) ? ENV["WHIPLASH_CLIENT_ID"] : body
20
+ rescue NoMethodError => e
21
+ ENV["WHIPLASH_CLIENT_ID"]
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -1,5 +1,5 @@
1
1
  module Whiplash
2
2
  class App
3
- VERSION = "0.5.1"
3
+ VERSION = "0.7.0"
4
4
  end
5
5
  end
data/lib/whiplash/app.rb CHANGED
@@ -4,6 +4,7 @@ require "whiplash/app/connections"
4
4
  require "whiplash/app/finder_methods"
5
5
  require "whiplash/app/signing"
6
6
  require "whiplash/app/version"
7
+ require "errors/whiplash_api_error"
7
8
  require "oauth2"
8
9
  require "faraday_middleware"
9
10
 
@@ -18,18 +19,29 @@ module Whiplash
18
19
  attr_accessor :customer_id, :shop_id, :token
19
20
 
20
21
  def initialize(token=nil, options={})
21
- opts = options.with_indifferent_access
22
+ token ||= cache_store["whiplash_api_token"]
22
23
  @token = format_token(token) unless token.nil?
23
24
  @customer_id = options[:customer_id]
24
25
  @shop_id = options[:shop_id]
26
+ @api_version = options[:api_version] || 2 # can be 2_1
27
+ end
28
+
29
+ def self.whiplash_api_token
30
+ store = Moneta.new(:Redis, host: ENV["REDIS_HOST"], port: ENV["REDIS_PORT"], password: ENV["REDIS_PASSWORD"], expires: 7200)
31
+ cache_store = Moneta::Namespace.new store, Whiplash::App::Caching.namespace_value
32
+ cache_store["whiplash_api_token"]
25
33
  end
26
34
 
27
35
  def client
28
36
  OAuth2::Client.new(ENV["WHIPLASH_CLIENT_ID"], ENV["WHIPLASH_CLIENT_SECRET"], site: api_url)
29
37
  end
30
38
 
39
+ def versioned_api_url
40
+ "api/v#{@api_version}"
41
+ end
42
+
31
43
  def connection
32
- out = Faraday.new [api_url, "api/v2"].join("/") do |conn|
44
+ out = Faraday.new [api_url, versioned_api_url].join("/") do |conn|
33
45
  conn.request :oauth2, token.token, token_type: "bearer"
34
46
  conn.request :json
35
47
  conn.response :json, :content_type => /\bjson$/
@@ -44,34 +56,41 @@ module Whiplash
44
56
  end
45
57
 
46
58
  def refresh_token!
47
- if token.blank? # If we're storing locally, grab a new token and cache it
48
- access_token = client.client_credentials.get_token(scope: ENV["WHIPLASH_CLIENT_SCOPE"])
49
- new_token = access_token.to_hash
50
- cache_store["whiplash_api_token"] = new_token
59
+ case ENV["WHIPLASH_CLIENT_SCOPE"]
60
+ when /app_(manage|read)/
61
+ begin
62
+ access_token = client.client_credentials.get_token(scope: ENV["WHIPLASH_CLIENT_SCOPE"])
63
+ new_token = access_token.to_hash
64
+ cache_store["whiplash_api_token"] = new_token
65
+ rescue URI::InvalidURIError => e
66
+ raise StandardError, "The provide URL (#{ENV["WHIPLASH_API_URL"]}) is not valid"
67
+ end
51
68
  else
69
+ raise StandardError, "You must request an access token before you can refresh it" if token.nil?
70
+ raise StandardError, "Token must either be a Hash or an OAuth2::AccessToken" unless token.is_a?(OAuth2::AccessToken)
52
71
  access_token = token.refresh!
53
72
  end
54
73
  self.token = access_token
55
74
  end
56
75
 
57
76
  def token_expired?
58
- return token.expired? unless token.blank?
59
- return true unless cache_store.has_key?("whiplash_api_token")
60
- return true if cache_store["whiplash_api_token"].blank?
77
+ return token.expired? unless token.nil?
78
+ return true unless cache_store.key?("whiplash_api_token")
79
+ return true if cache_store["whiplash_api_token"].nil?
80
+ return true if cache_store["whiplash_api_token"].empty?
61
81
  false
62
82
  end
63
83
 
64
84
  private
65
85
  def format_token(oauth_token)
66
- unless oauth_token.is_a?(OAuth2::AccessToken)
67
- raise StandardError, "Token must either be a Hash or an OAuth2::AccessToken" unless oauth_token.is_a?(Hash)
68
- oauth_token['expires'] = oauth_token['expires'].to_s # from_hash expects 'true'
69
- if oauth_token.has_key?('token')
70
- oauth_token['access_token'] = oauth_token['token']
71
- oauth_token.delete('token')
72
- end
73
- oauth_token = OAuth2::AccessToken.from_hash(client, oauth_token)
86
+ return oauth_token if oauth_token.is_a?(OAuth2::AccessToken)
87
+ raise StandardError, "Token must either be a Hash or an OAuth2::AccessToken" unless oauth_token.is_a?(Hash)
88
+ oauth_token['expires'] = oauth_token['expires'].to_s # from_hash expects 'true'
89
+ if oauth_token.has_key?('token')
90
+ oauth_token['access_token'] = oauth_token['token']
91
+ oauth_token.delete('token')
74
92
  end
93
+ oauth_token = OAuth2::AccessToken.from_hash(client, oauth_token)
75
94
  end
76
95
 
77
96
  end
data/whiplash-app.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "faraday_middleware", "~> 0.11.0"
23
23
  spec.add_dependency "moneta", "~> 0.8.0"
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.11"
25
+ spec.add_development_dependency "bundler", ">= 2.2"
26
26
  spec.add_development_dependency "rake", ">= 12.3.3"
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
28
28
  spec.add_development_dependency "pry" , '~> 0.12.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whiplash-app
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Don Sullivan, Mark Dickson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-20 00:00:00.000000000 Z
11
+ date: 2021-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.11'
61
+ version: '2.2'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.11'
68
+ version: '2.2'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -153,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
155
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.7.6.2
156
+ rubygems_version: 3.0.3.1
158
157
  signing_key:
159
158
  specification_version: 4
160
159
  summary: this gem provides connectivity to the Whiplash API for authentication and