muffin_man 1.2.0 → 1.4.1

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: bed4f016d8045bd0f40bfe4e4ca1be2467fac83ff0549674610c20ad3cba9795
4
- data.tar.gz: f955bc7597541ed72eeaeb343d42d83a26892acf31fd3041a287697ae05c6828
3
+ metadata.gz: 70bef5fd30926ae053d7a8e2cb36b85b5ad763e0c9ef540254a68d14d90e790d
4
+ data.tar.gz: d7762e45d0663c1f6305dd41eed16fe3eed9265469f11c031a52de1f6dbae4c8
5
5
  SHA512:
6
- metadata.gz: faed598abf08c41f6e68b627fddaf35e2ccf1a64b95585167827aff7dd996093e6051c2f8caa7e939fe9545b8c91876c8df50bf74f97620b9cb9137934ff5b36
7
- data.tar.gz: 0b9a3a286fcd8dc499fc209a276a11f933270f8e430910281f729b817d2f1eebe684d835e0b73250127888550f0f190353c2f84fe51513d65711136e7b7c90a0
6
+ metadata.gz: 4be6ad20196556290c59054fc3216e8723e25c0c02c8bfb8fef4f78207a885c1e97b07027a41c06279fe83fa816b413a24c9155e13d2f2f76b78f24ab558d4c1
7
+ data.tar.gz: 46fcfc5c8d8007b2c4a552516a65bc8c4cb8fe2a07f6d48c17237a77ae4521dc2f5121bfb329ba21e9ef8a7186355d89b7d88c8657cda8856599982241559a67
data/.gitignore CHANGED
@@ -14,3 +14,6 @@
14
14
  Gemfile.lock
15
15
  *.gem
16
16
  .ruby-version
17
+ .byebug_history
18
+
19
+ .DS_store
data/.rubocop.yml CHANGED
@@ -11,3 +11,6 @@ Style/StringLiteralsInInterpolation:
11
11
 
12
12
  Layout/LineLength:
13
13
  Max: 120
14
+
15
+ Metrics/MethodLength:
16
+ Max: 30
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # 1.4.0
2
+
3
+ - Pass cache key to client for caching access tokens [#11](https://github.com/patterninc/muffin_man/pull/11)
data/README.md CHANGED
@@ -40,6 +40,7 @@ credentials = {
40
40
  aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
41
41
  region: REGION, # This can be one of ['na', 'eu', 'fe'] and defaults to 'na'
42
42
  sts_iam_role_arn: STS_IAM_ROLE_ARN, # Optional
43
+ access_token_cache_key: SELLING_PARTNER_ID, # Optional if you want access token caching
43
44
  }
44
45
  client = MuffinMan::Solicitations::V1.new(credentials)
45
46
  response = client.create_product_review_and_seller_feedback_solicitation(amazon_order_id, marketplace_ids)
@@ -48,6 +49,8 @@ JSON.parse(response.body)
48
49
 
49
50
  You can optionally use Amazon's sandbox environment by specifying `client = MuffinMan::Solicitations.new(credentials, sandbox = true)`
50
51
 
52
+ ### Access Token Caching
53
+
51
54
  You can save and retrieve the LWA refresh token by defining a lambda in your initializers.
52
55
 
53
56
  For example, if you are using Redis as your cache you could define:
@@ -55,14 +58,35 @@ For example, if you are using Redis as your cache you could define:
55
58
  ```ruby
56
59
  @@redis = Redis.new
57
60
  MuffinMan.configure do |config|
58
- config.save_access_token = -> (client_id, token) do
59
- @@redis.set("SP-TOKEN-#{client_id}", token['access_token'], ex: token['expires_in'])
61
+ config.save_access_token = -> (access_token_cache_key, token) do
62
+ @@redis.set("SP-TOKEN-#{access_token_cache_key}", token['access_token'], ex: token['expires_in'])
60
63
  end
61
64
 
62
- config.get_access_token = -> (client_id) { @@redis.get("SP-TOKEN-#{client_id}") }
65
+ config.get_access_token = -> (access_token_cache_key) { @@redis.get("SP-TOKEN-#{access_token_cache_key}") }
63
66
  end
64
67
  ```
65
68
 
69
+ ### Retrieiving the refresh token
70
+
71
+ To retrieve the refresh token from an LWA Website authorization workflow, you can use the LWA helper:
72
+
73
+ ```ruby
74
+ # Get your auth code first, either through the Website oauth flow or Authorization API
75
+ credentials = {
76
+ client_id: CLIENT_ID,
77
+ client_secret: CLIENT_SECRET,
78
+ aws_access_key_id: AWS_ACCESS_KEY_ID,
79
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
80
+ sts_iam_role_arn: STS_IAM_ROLE_ARN, # Optional
81
+ scope: 'sellingpartnerapi::migration' # Grantless scope for MWS migration
82
+ }
83
+ client = MuffinMan::Authorization::V1.new(credentials)
84
+ resp = JSON.parse(client.get_authorization_code(seller_id, developer_id, mws_auth_token).body)
85
+ auth_code = resp['payload']['authorizationCode']
86
+ # Then query retrieve the refresh token to store
87
+ refresh_token = MuffinMan::Lwa::AuthHelper.get_refresh_token(CLIENT_ID, CLIENT_SECRET, auth_code)
88
+ ```
89
+
66
90
  ## Contributing
67
91
 
68
92
  Bug reports and pull requests are welcome on GitHub at https://github.com/patterninc/muffin_man. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/patterninc/muffin_man/blob/master/CODE_OF_CONDUCT.md).
@@ -7,7 +7,6 @@ module MuffinMan
7
7
  "developerId" => developer_id,
8
8
  "mwsAuthToken" => mws_auth_token
9
9
  }
10
- @query_params = {} if sandbox
11
10
  @request_type = "GET"
12
11
  @local_var_path = "/authorization/v1/authorizationCode"
13
12
  call_api
@@ -1,14 +1,19 @@
1
1
  module MuffinMan
2
2
  module Finances
3
3
  class V0 < SpApiClient
4
-
5
4
  def list_financial_event_groups(max_results_per_page = nil, financial_event_group_started_before = nil, financial_event_group_started_after = nil, next_token = nil)
6
5
  @local_var_path = "/finances/v0/financialEventGroups"
7
6
  @query_params = {}
8
- @query_params['MaxResultsPerPage'] = max_results_per_page unless max_results_per_page.nil?
9
- @query_params['FinancialEventGroupStartedBefore'] = financial_event_group_started_before unless financial_event_group_started_before.nil?
10
- @query_params['FinancialEventGroupStartedAfter'] = financial_event_group_started_after unless financial_event_group_started_after.nil?
11
- @query_params['NextToken'] = next_token unless next_token.nil?
7
+ @query_params["MaxResultsPerPage"] = max_results_per_page unless max_results_per_page.nil?
8
+ unless financial_event_group_started_before.nil?
9
+ @query_params["FinancialEventGroupStartedBefore"] =
10
+ financial_event_group_started_before
11
+ end
12
+ unless financial_event_group_started_after.nil?
13
+ @query_params["FinancialEventGroupStartedAfter"] =
14
+ financial_event_group_started_after
15
+ end
16
+ @query_params["NextToken"] = next_token unless next_token.nil?
12
17
  @request_type = "GET"
13
18
  call_api
14
19
  end
@@ -16,10 +21,10 @@ module MuffinMan
16
21
  def list_financial_events_by_group_id(event_group_id, max_results_per_page = nil, posted_after = nil, posted_before = nil, next_token = nil)
17
22
  @local_var_path = "/finances/v0/financialEventGroups/#{event_group_id}/financialEvents"
18
23
  @query_params = {}
19
- @query_params['MaxResultsPerPage'] = max_results_per_page unless max_results_per_page.nil?
20
- @query_params['PostedAfter'] = posted_after unless posted_after.nil?
21
- @query_params['PostedBefore'] = posted_before unless posted_before.nil?
22
- @query_params['NextToken'] = next_token unless next_token.nil?
24
+ @query_params["MaxResultsPerPage"] = max_results_per_page unless max_results_per_page.nil?
25
+ @query_params["PostedAfter"] = posted_after unless posted_after.nil?
26
+ @query_params["PostedBefore"] = posted_before unless posted_before.nil?
27
+ @query_params["NextToken"] = next_token unless next_token.nil?
23
28
  @request_type = "GET"
24
29
  call_api
25
30
  end
@@ -0,0 +1,27 @@
1
+ module MuffinMan::Lwa
2
+ class AuthHelper
3
+ ACCESS_TOKEN_URL = "https://api.amazon.com/auth/o2/token".freeze
4
+
5
+ def self.get_refresh_token(client_id, client_secret, auth_code)
6
+ body = {
7
+ grant_type: "authorization_code",
8
+ code: auth_code,
9
+ client_id: client_id,
10
+ client_secret: client_secret
11
+ }
12
+ response = Typhoeus.post(
13
+ ACCESS_TOKEN_URL,
14
+ body: URI.encode_www_form(body),
15
+ headers: {
16
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
17
+ }
18
+ )
19
+ if response.code != 200
20
+ error_body = JSON.parse(response.body)
21
+ error = "#{error_body["error"]}: #{error_body["error_description"]}"
22
+ raise MuffinMan::Error, error
23
+ end
24
+ JSON.parse(response.body)["refresh_token"]
25
+ end
26
+ end
27
+ end
@@ -44,7 +44,7 @@ module MuffinMan
44
44
  @local_var_path = "/reports/2021-06-30/reports"
45
45
  @request_body = {
46
46
  "reportType" => report_type,
47
- "marketplaceIds" => marketplace_ids,
47
+ "marketplaceIds" => marketplace_ids
48
48
  }
49
49
  @request_body["dataStartTime"] = start_time unless start_time.nil?
50
50
  @request_body["dataEndTime"] = end_time unless end_time.nil?
@@ -73,6 +73,17 @@ module MuffinMan
73
73
  @request_type = "GET"
74
74
  call_api
75
75
  end
76
+
77
+ def get_report_document_body(report_document_id)
78
+ response = get_report_document(report_document_id)
79
+ parsed_response=JSON.parse(response.body)
80
+ report=Net::HTTP.get(URI.parse(parsed_response['url']))
81
+ unless (parsed_response['compressionAlgorithm']).nil?
82
+ input = StringIO.new(report)
83
+ report = Zlib::GzipReader.new(input).read
84
+ end
85
+ report
86
+ end
76
87
  end
77
88
  end
78
89
  end
@@ -11,9 +11,11 @@ module MuffinMan
11
11
  def create_product_review_and_seller_feedback_solicitation(amazon_order_id, marketplace_ids)
12
12
  @amazon_order_id = sandbox ? SANDBOX_AMAZON_ORDER_ID : amazon_order_id
13
13
  @marketplace_ids = sandbox ? SANDBOX_MARKETPLACE_IDS : marketplace_ids
14
- @local_var_path = '/solicitations/v1/orders/{amazonOrderId}/solicitations/productReviewAndSellerFeedback'.sub('{' + 'amazonOrderId' + '}', @amazon_order_id)
14
+ @local_var_path = "/solicitations/v1/orders/{amazonOrderId}/solicitations/productReviewAndSellerFeedback".sub(
15
+ "{" + "amazonOrderId" + "}", @amazon_order_id
16
+ )
15
17
  @query_params = { "marketplaceIds" => @marketplace_ids }
16
- @request_type = 'POST'
18
+ @request_type = "POST"
17
19
  call_api
18
20
  end
19
21
  end
@@ -1,20 +1,22 @@
1
- require 'aws-sigv4'
2
- require 'uri'
3
- require 'aws-sdk-core'
4
- require 'typhoeus'
5
- require 'securerandom'
1
+ require "aws-sigv4"
2
+ require "uri"
3
+ require "aws-sdk-core"
4
+ require "typhoeus"
5
+ require "securerandom"
6
6
 
7
7
  module MuffinMan
8
8
  class SpApiClient
9
9
  attr_reader :refresh_token, :client_id, :client_secret, :aws_access_key_id,
10
- :aws_secret_access_key, :sts_iam_role_arn, :sandbox, :config, :region, :request_type,
11
- :local_var_path, :query_params, :request_body, :scope
12
- ACCESS_TOKEN_URL = 'https://api.amazon.com/auth/o2/token'.freeze
13
- SERVICE_NAME = 'execute-api'.freeze
10
+ :aws_secret_access_key, :sts_iam_role_arn, :sandbox, :config,
11
+ :region, :request_type, :local_var_path, :query_params,
12
+ :request_body, :scope, :access_token_cache_key
13
+
14
+ ACCESS_TOKEN_URL = "https://api.amazon.com/auth/o2/token".freeze
15
+ SERVICE_NAME = "execute-api".freeze
14
16
  AWS_REGION_MAP = {
15
- 'na' => 'us-east-1',
16
- 'eu' => 'eu-west-1',
17
- 'fe' => 'us-west-2'
17
+ "na" => "us-east-1",
18
+ "eu" => "eu-west-1",
19
+ "fe" => "us-west-2"
18
20
  }.freeze
19
21
 
20
22
  def initialize(credentials, sandbox = false)
@@ -24,10 +26,11 @@ module MuffinMan
24
26
  @aws_access_key_id = credentials[:aws_access_key_id]
25
27
  @aws_secret_access_key = credentials[:aws_secret_access_key]
26
28
  @sts_iam_role_arn = credentials[:sts_iam_role_arn]
27
- @region = credentials[:region] || 'na'
29
+ @region = credentials[:region] || "na"
28
30
  @scope = credentials[:scope]
31
+ @access_token_cache_key = credentials[:access_token_cache_key]
29
32
  @sandbox = sandbox
30
- Typhoeus::Config.user_agent = ''
33
+ Typhoeus::Config.user_agent = ""
31
34
  @config = MuffinMan.configuration
32
35
  end
33
36
 
@@ -39,9 +42,7 @@ module MuffinMan
39
42
 
40
43
  def request_opts
41
44
  opts = { headers: headers }
42
- if request_body
43
- opts[:body] = request_body.to_json
44
- end
45
+ opts[:body] = request_body.to_json if request_body
45
46
  opts
46
47
  end
47
48
 
@@ -64,20 +65,25 @@ module MuffinMan
64
65
  end
65
66
 
66
67
  def retrieve_lwa_access_token
67
- return request_lwa_access_token['access_token'] unless defined?(config.get_access_token)
68
- stored_token = config.get_access_token.call(client_id)
68
+ return request_lwa_access_token["access_token"] unless use_cache?
69
+
70
+ stored_token = config.get_access_token.call(access_token_cache_key)
69
71
  if stored_token.nil?
70
72
  new_token = request_lwa_access_token
71
- config.save_access_token.call(client_id, new_token) if defined?(config.save_access_token)
72
- return new_token['access_token']
73
+ config.save_access_token.call(access_token_cache_key, new_token)
74
+ new_token["access_token"]
73
75
  else
74
- return stored_token
76
+ stored_token
75
77
  end
76
78
  end
77
79
 
80
+ def use_cache?
81
+ defined?(config.save_access_token) && defined?(config.get_access_token) && access_token_cache_key
82
+ end
83
+
78
84
  def request_lwa_access_token
79
85
  body = {
80
- grant_type: 'refresh_token',
86
+ grant_type: "refresh_token",
81
87
  refresh_token: refresh_token,
82
88
  client_id: client_id,
83
89
  client_secret: client_secret
@@ -86,7 +92,7 @@ module MuffinMan
86
92
  ACCESS_TOKEN_URL,
87
93
  body: URI.encode_www_form(body),
88
94
  headers: {
89
- 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
95
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
90
96
  }
91
97
  )
92
98
  JSON.parse(response.body)
@@ -142,16 +148,20 @@ module MuffinMan
142
148
  def headers
143
149
  access_token = scope ? retrieve_grantless_access_token : retrieve_lwa_access_token
144
150
  headers = {
145
- 'x-amz-access-token' => access_token,
146
- 'user-agent' => "MuffinMan/#{VERSION} (Language=Ruby)",
147
- 'content-type' => "application/json"
151
+ "x-amz-access-token" => access_token,
152
+ "user-agent" => "MuffinMan/#{VERSION} (Language=Ruby)",
153
+ "content-type" => "application/json"
148
154
  }
149
155
  signed_request.headers.merge(headers)
150
156
  end
151
157
 
152
158
  def derive_aws_region
153
159
  @aws_region ||= AWS_REGION_MAP[region]
154
- raise MuffinMan::Error.new("#{region} is not supported or does not exist. Region must be one of the following: #{AWS_REGION_MAP.keys.join(', ')}") unless @aws_region
160
+ unless @aws_region
161
+ raise MuffinMan::Error,
162
+ "#{region} is not supported or does not exist. Region must be one of the following: #{AWS_REGION_MAP.keys.join(", ")}"
163
+ end
164
+
155
165
  @aws_region
156
166
  end
157
167
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MuffinMan
4
- VERSION = "1.2.0"
4
+ VERSION = "1.4.1"
5
5
  end
data/lib/muffin_man.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "muffin_man/version"
2
2
  require "muffin_man/sp_api_client"
3
+ require "muffin_man/lwa/auth_helper"
3
4
  require "muffin_man/solicitations/v1"
4
5
  require "muffin_man/reports/v20210630"
5
6
  require "muffin_man/catalog_items/v20201201"
data/muffin_man.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "rspec", "~> 3.2"
22
22
  spec.add_development_dependency 'webmock', '~> 2.1'
23
+ spec.add_development_dependency 'byebug'
23
24
  spec.add_development_dependency 'mock_redis', '>=0.14'
24
25
  spec.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'
25
26
  spec.add_runtime_dependency 'aws-sigv4', '>= 1.1'
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: muffin_man
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin
8
8
  - Jason
9
9
  - Nate
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-04-21 00:00:00.000000000 Z
13
+ date: 2022-06-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -40,6 +40,20 @@ dependencies:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '2.1'
43
+ - !ruby/object:Gem::Dependency
44
+ name: byebug
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
43
57
  - !ruby/object:Gem::Dependency
44
58
  name: mock_redis
45
59
  requirement: !ruby/object:Gem::Requirement
@@ -102,7 +116,7 @@ dependencies:
102
116
  - - ">="
103
117
  - !ruby/object:Gem::Version
104
118
  version: 2.4.4
105
- description:
119
+ description:
106
120
  email:
107
121
  - gavin@pattern.com
108
122
  - jason@pattern.com
@@ -115,6 +129,7 @@ files:
115
129
  - ".gitignore"
116
130
  - ".rspec"
117
131
  - ".rubocop.yml"
132
+ - CHANGELOG.md
118
133
  - CODE_OF_CONDUCT.md
119
134
  - Gemfile
120
135
  - LICENSE.txt
@@ -126,6 +141,7 @@ files:
126
141
  - lib/muffin_man/authorization/v1.rb
127
142
  - lib/muffin_man/catalog_items/v20201201.rb
128
143
  - lib/muffin_man/finances/v0.rb
144
+ - lib/muffin_man/lwa/auth_helper.rb
129
145
  - lib/muffin_man/reports/v20210630.rb
130
146
  - lib/muffin_man/solicitations/v1.rb
131
147
  - lib/muffin_man/sp_api_client.rb
@@ -135,7 +151,7 @@ homepage: https://github.com/patterninc/muffin_man
135
151
  licenses:
136
152
  - MIT
137
153
  metadata: {}
138
- post_install_message:
154
+ post_install_message:
139
155
  rdoc_options: []
140
156
  require_paths:
141
157
  - lib
@@ -150,8 +166,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
166
  - !ruby/object:Gem::Version
151
167
  version: '0'
152
168
  requirements: []
153
- rubygems_version: 3.1.6
154
- signing_key:
169
+ rubygems_version: 3.0.3
170
+ signing_key:
155
171
  specification_version: 4
156
172
  summary: Amazon Selling Partner API client
157
173
  test_files: []