whiplash-app 0.5.1 → 0.7.0

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