easypost 4.5.0 → 4.7.1

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: 10f43ed8bb80d557e81cb7904f2972d5869db45393e18d6d29374d8be9cb84da
4
- data.tar.gz: 1956b7baf66e1906c3e0de4252c0563d914ec115d0eafb60a7b17e11493e9d89
3
+ metadata.gz: 33802b8af58e7efc3e5592c6559dd48dfa5a58cc9338f719c78bc97639f73c51
4
+ data.tar.gz: 1ec9df3da15eb1169817db4d3610f78826388836995615ec928a80d60e17fcf1
5
5
  SHA512:
6
- metadata.gz: 735164cd9f181b41aeca6e9f411ad190b6dfcd11772d8be7fa89f8764330dbb7e7578558c3a03b21253a5e98bc0bb4ce0f99ed87991a838719ff7fcb80464404
7
- data.tar.gz: 5112f6462def1f310ec78ab55fb38c555888ec39adf9d0605e930a01ddbbc282b7635d08a4348b63d562b67dd6fa48111022e8404a330812cd4922f853bf840e
6
+ metadata.gz: 8f66b559d5f34005ad16151f3b32b168254efaff625ab06eba13a97ebe1aade1ff40f3d281fed9f32f80016bf662337be2053dc9a74d0f748bff47c67c3f6dd8
7
+ data.tar.gz: a22e6a0c850f686807aae90db0d81a24f963c045e043dbd497a5078b9b4f5806124782906d78b3e30b760a13cd78daf9c99b4252c58760205d5b7364472f3310
@@ -0,0 +1,2 @@
1
+ # Ping the DevEx team for reviews on every PR
2
+ * @EasyPost/devex
@@ -19,6 +19,8 @@ jobs:
19
19
  with:
20
20
  ruby-version: ${{ matrix.rubyversion }}
21
21
  bundler-cache: true
22
+ - name: Install Dependencies
23
+ run: make install
22
24
  - name: run tests
23
25
  run: EASYPOST_TEST_API_KEY=123 EASYPOST_PROD_API_KEY=123 make test
24
26
  lint:
@@ -35,4 +37,4 @@ jobs:
35
37
  - name: Lint Project
36
38
  run: make lint
37
39
  - name: Run security analysis
38
- run: make brakeman
40
+ run: make scan
data/.gitignore CHANGED
@@ -13,6 +13,7 @@ test/tmp
13
13
  test/version_tmp
14
14
  tmp
15
15
  .idea/
16
+ dist
16
17
 
17
18
  # YARD artifacts
18
19
  .yardoc
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "examples"]
2
+ path = examples
3
+ url = https://github.com/EasyPost/examples
data/.rubocop.yml CHANGED
@@ -3,3 +3,7 @@ inherit_from: easycop.yml
3
3
  # We are ignoring RSpec/FilePath because Simplecov doesn't play nice with nested spec files
4
4
  RSpec/FilePath:
5
5
  Enabled: false
6
+ # TODO: Remove this once we start using keyword arguments
7
+ Style/OptionalBooleanParameter:
8
+ Exclude:
9
+ - 'lib/easypost/shipment.rb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v4.7.1 (2022-09-06)
4
+
5
+ - Makes not implemented `all` calls match the `EasyPost::Resource` interface so that one can call `.to_json` on them and receive the proper error
6
+
7
+ ## v4.7.0 (2022-08-25)
8
+
9
+ - Moves EndShipper out of beta to the general library namespace
10
+ - Ensure the Easypost object will respond to `.id` when it has one in `@values`
11
+
12
+ ## v4.6.0 (2022-08-02)
13
+
14
+ - Adds Carbon Offset support
15
+ - Adds ability to create a shipment with carbon_offset
16
+ - Adds ability to buy a shipment with carbon_offset
17
+ - Adds ability to one-call-buy a shipment with carbon_offset
18
+ - Adds ability to rerate a shipment with carbon_offset
19
+ - Adds `validate_webhook` function that returns your webhook or raises an error if there is a `webhook_secret` mismatch
20
+ - Deprecated `PaymentMethod` class, please use `Billing` class for retrieve all payment method function
21
+
3
22
  ## v4.5.0 (2022-07-18)
4
23
 
5
24
  - Adds ability to generate shipment forms via `generate_form` function
data/Makefile CHANGED
@@ -2,17 +2,15 @@
2
2
  help:
3
3
  @cat Makefile | grep '^## ' --color=never | cut -c4- | sed -e "`printf 's/ - /\t- /;'`" | column -s "`printf '\t'`" -t
4
4
 
5
- ## brakeman - Runs security analysis on the project with Brakeman
6
- brakeman:
7
- brakeman lib --force
8
-
9
5
  ## build - Builds the project
10
6
  build:
11
- gem build easypost.gemspec
7
+ gem build easypost.gemspec --strict
8
+ mkdir -p dist
9
+ mv *.gem dist/
12
10
 
13
11
  ## clean - Cleans the project
14
12
  clean:
15
- rm -rf coverage doc *.gem
13
+ rm -rf coverage doc *.gem dist
16
14
 
17
15
  ## fix - Fix Rubocop errors
18
16
  fix:
@@ -20,18 +18,34 @@ fix:
20
18
 
21
19
  ## install - Install globally from source
22
20
  install:
21
+ git submodule init
22
+ git submodule update
23
23
  bundle install
24
24
 
25
25
  ## lint - Lint the project
26
26
  lint:
27
27
  rubocop
28
28
 
29
- ## push - Pushes the built gem to Rubygems
30
- push:
31
- gem push *.gem
29
+ ## publish - Publishes the built gem to Rubygems
30
+ publish:
31
+ gem push dist/*.gem
32
+
33
+ ## release - Cuts a release for the project on GitHub (requires GitHub CLI)
34
+ # tag = The associated tag title of the release
35
+ release:
36
+ gh release create ${tag} dist/*
37
+
38
+ ## scan - Runs security analysis on the project with Brakeman
39
+ scan:
40
+ brakeman lib --force
32
41
 
33
42
  ## test - Test the project
34
43
  test:
35
44
  bundle exec rspec
36
45
 
37
- .PHONY: help build clean fix install lint push test
46
+ ## update - Updates dependencies
47
+ update:
48
+ git submodule init
49
+ git submodule update --remote
50
+
51
+ .PHONY: help build clean fix install lint publish release scan test update
data/README.md CHANGED
@@ -121,8 +121,18 @@ make install
121
121
  # Lint project
122
122
  make lint
123
123
 
124
+ # Fix linting errors
125
+ make fix
126
+
124
127
  # Run tests (coverage is generated on a successful test suite run)
125
128
  EASYPOST_TEST_API_KEY=123... EASYPOST_PROD_API_KEY=123... make test
129
+
130
+ # Run security analysis
131
+ make scan
132
+
133
+ # Update submodules
134
+ git submodule init
135
+ git submodule update --remote
126
136
  ```
127
137
 
128
138
  ### Testing
@@ -142,9 +152,8 @@ The following are required on every test run:
142
152
  - `EASYPOST_TEST_API_KEY`
143
153
  - `EASYPOST_PROD_API_KEY`
144
154
 
145
- The following are required when you need to re-record cassettes for applicable tests (fallback values are used otherwise):
155
+ Some tests may require an EasyPost user with a particular set of enabled features such as a `Partner` user when creating referrals. We have attempted to call out these functions in their respective docstrings. The following are required when you need to re-record cassettes for applicable tests:
146
156
 
147
157
  - `USPS_CARRIER_ACCOUNT_ID` (eg: one-call buying a shipment for non-EasyPost employees)
158
+ - `PARTNER_USER_PROD_API_KEY` (eg: creating a referral user)
148
159
  - `REFERRAL_USER_PROD_API_KEY` (eg: adding a credit card to a referral user)
149
-
150
- Some tests may require a user with a particular set of enabled features such as a `Partner` user when creating referrals. We have attempted to call out these functions in their respective docstrings.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.5.0
1
+ 4.7.1
@@ -2,26 +2,30 @@
2
2
 
3
3
  # EndShipper objects are fully-qualified Address objects that require all parameters and get verified upon creation.
4
4
  class EasyPost::Beta::EndShipper < EasyPost::Resource
5
- # Create an EndShipper object.
5
+ # <b>DEPRECATED:</b> Please use <tt>EndShipper</tt> in the main namespace instead.
6
6
  def self.create(params = {}, api_key = nil)
7
+ warn '[DEPRECATION] Please use `EndShipper.create` in the main namespace instead.'
7
8
  response = EasyPost.make_request(:post, '/beta/end_shippers', api_key, { address: params })
8
9
  EasyPost::Util.convert_to_easypost_object(response, api_key)
9
10
  end
10
11
 
11
12
  # Retrieves an EndShipper object.
12
13
  def self.retrieve(id, params = {}, api_key = nil)
14
+ warn '[DEPRECATION] Please use `EndShipper.retrieve` in the main namespace instead.'
13
15
  response = EasyPost.make_request(:get, "/beta/end_shippers/#{id}", api_key, params)
14
16
  EasyPost::Util.convert_to_easypost_object(response, api_key)
15
17
  end
16
18
 
17
19
  # Retrieves a list of EndShipper objects.
18
20
  def self.all(params = {}, api_key = nil)
21
+ warn '[DEPRECATION] Please use `EndShipper.all` in the main namespace instead.'
19
22
  response = EasyPost.make_request(:get, '/beta/end_shippers', api_key, params)
20
23
  EasyPost::Util.convert_to_easypost_object(response, api_key)
21
24
  end
22
25
 
23
26
  # Updates (saves) an EndShipper object. This requires all parameters to be set.
24
27
  def save
28
+ warn '[DEPRECATION] Please use `endShipper.save` in the main namespace instead.'
25
29
  if @unsaved_values.length.positive?
26
30
  values = {}
27
31
  @unsaved_values.each { |k| values[k] = @values[k] }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The CarbonOffset object is a summary of carbon offset data for a given rate, including grams, price and currency
4
+ class EasyPost::CarbonOffset < EasyPost::Resource
5
+ end
@@ -3,7 +3,7 @@
3
3
  # CustomsInfo objects contain CustomsItem objects and all necessary information for the generation of customs forms required for international shipping.
4
4
  class EasyPost::CustomsInfo < EasyPost::Resource
5
5
  # Retrieve a list of CustomsInfo objects
6
- def self.all
6
+ def self.all(_filters = {}, _api_key = nil)
7
7
  raise NotImplementedError.new('CustomsInfo.all not implemented.')
8
8
  end
9
9
  end
@@ -3,7 +3,7 @@
3
3
  # A CustomsItem object describes goods for international shipment and should be created then included in a CustomsInfo object.
4
4
  class EasyPost::CustomsItem < EasyPost::Resource
5
5
  # Retrieve a list of CustomsItem objects
6
- def self.all
6
+ def self.all(_filters = {}, _api_key = nil)
7
7
  raise NotImplementedError.new('CustomsItem.all not implemented.')
8
8
  end
9
9
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # EndShipper objects are fully-qualified Address objects that require all parameters and get verified upon creation.
4
+ class EasyPost::EndShipper < EasyPost::Resource
5
+ # Create an EndShipper object.
6
+ def self.create(params = {}, api_key = nil)
7
+ response = EasyPost.make_request(:post, url, api_key, { address: params })
8
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
9
+ end
10
+
11
+ # Updates (saves) an EndShipper object. This requires all parameters to be set.
12
+ def save
13
+ if @unsaved_values.length.positive?
14
+ values = {}
15
+ @unsaved_values.each { |k| values[k] = @values[k] }
16
+
17
+ wrapped_params = { address: values }
18
+
19
+ response = EasyPost.make_request(:put, url, @api_key, wrapped_params)
20
+ refresh_from(response, api_key)
21
+ end
22
+ self
23
+ end
24
+ end
@@ -49,14 +49,18 @@ class EasyPost::EasyPostObject
49
49
  add_accessors(added)
50
50
  end
51
51
 
52
- # IDs don't change, do not update it
53
- @values.delete(:id)
52
+ # IDs should never change. But to be safe, only delete if they are different.
53
+ @values.delete(:id) if values[:id] != @values[:id]
54
54
 
55
55
  values.each do |k, v|
56
56
  @values[k.to_s] = EasyPost::Util.convert_to_easypost_object(v, api_key, self, k)
57
57
  @transient_values.delete(k)
58
58
  @unsaved_values.delete(k)
59
59
  end
60
+
61
+ return if @values[:id] || (values[:id].nil? && values['id'].nil?)
62
+
63
+ @values[:id] = values[:id] || values['id']
60
64
  end
61
65
 
62
66
  # Get element of an array.
@@ -26,7 +26,7 @@ class EasyPost::Order < EasyPost::Resource
26
26
  end
27
27
 
28
28
  # Retrieve a list of Order objects.
29
- def self.all
29
+ def self.all(_filters = {}, _api_key = nil)
30
30
  raise NotImplementedError.new('Order.all not implemented.')
31
31
  end
32
32
 
@@ -3,7 +3,7 @@
3
3
  # Parcel objects represent the physical container being shipped.
4
4
  class EasyPost::Parcel < EasyPost::Resource
5
5
  # Retrieving all Parcel objects is not supported.
6
- def self.all
6
+ def self.all(_filters = {}, _api_key = nil)
7
7
  raise NotImplementedError.new('Parcel.all not implemented.')
8
8
  end
9
9
  end
@@ -2,14 +2,10 @@
2
2
 
3
3
  # PaymentMethod objects represent a payment method of a user.
4
4
  class EasyPost::PaymentMethod < EasyPost::Resource
5
- # Retrieve all payment methods.
6
- def self.all(api_key = nil)
7
- response = EasyPost.make_request(:get, url, api_key)
8
-
9
- if response['id'].nil?
10
- raise EasyPost::Error.new('Billing has not been setup for this user. Please add a payment method.')
11
- end
12
-
13
- EasyPost::Util.convert_to_easypost_object(response, api_key)
5
+ # <b>DEPRECATED:</b> Please use <tt>Billing class</tt> instead.
6
+ # Deprecated: v4.5.0 - v6.0.0
7
+ def self.all(_filters = {}, api_key = nil)
8
+ warn '[DEPRECATION] `all` is deprecated. Please use `Billing.retrieve_payment_methods` instead.'
9
+ EasyPost::Billing.retrieve_payment_methods(api_key)
14
10
  end
15
11
  end
@@ -26,7 +26,7 @@ class EasyPost::Pickup < EasyPost::Resource
26
26
  end
27
27
 
28
28
  # Retrieve a list of all Pickup objects.
29
- def self.all
29
+ def self.all(_filters = {}, _api_key = nil)
30
30
  raise NotImplementedError.new('Pickup.all not implemented.')
31
31
  end
32
32
 
data/lib/easypost/rate.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  # A Rate object contains all the details about the rate of a Shipment.
4
4
  class EasyPost::Rate < EasyPost::Resource
5
5
  # Retrieving all Rate objects is not supported.
6
- def self.all
6
+ def self.all(_filters = {}, _api_key = nil)
7
7
  raise NotImplementedError.new('Rate.all not implemented.')
8
8
  end
9
9
  end
@@ -5,8 +5,22 @@ require 'set'
5
5
  # The workhorse of the EasyPost API, a Shipment is made up of a "to" and "from" Address, the Parcel
6
6
  # being shipped, and any customs forms required for international deliveries.
7
7
  class EasyPost::Shipment < EasyPost::Resource
8
+ # Create a Shipment.
9
+ def self.create(params = {}, api_key = nil, with_carbon_offset = false)
10
+ wrapped_params = {
11
+ shipment: params,
12
+ carbon_offset: with_carbon_offset,
13
+ }
14
+
15
+ response = EasyPost.make_request(:post, url, api_key, wrapped_params)
16
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
17
+ end
18
+
8
19
  # Regenerate the rates of a Shipment.
9
- def regenerate_rates(params = {})
20
+ def regenerate_rates(with_carbon_offset = false)
21
+ params = {}
22
+ params[:carbon_offset] = with_carbon_offset
23
+
10
24
  response = EasyPost.make_request(:post, "#{url}/rerate", @api_key, params)
11
25
  refresh_from(response, @api_key)
12
26
 
@@ -21,13 +35,15 @@ class EasyPost::Shipment < EasyPost::Resource
21
35
  end
22
36
 
23
37
  # Buy a Shipment.
24
- def buy(params = {})
38
+ def buy(params = {}, with_carbon_offset = false)
25
39
  if params.instance_of?(EasyPost::Rate)
26
40
  temp = params.clone
27
41
  params = {}
28
42
  params[:rate] = temp
29
43
  end
30
44
 
45
+ params[:carbon_offset] = with_carbon_offset
46
+
31
47
  response = EasyPost.make_request(:post, "#{url}/buy", @api_key, params)
32
48
  refresh_from(response, @api_key)
33
49
 
data/lib/easypost/util.rb CHANGED
@@ -11,7 +11,7 @@ module EasyPost::Util
11
11
  'ca' => EasyPost::CarrierAccount,
12
12
  'cstinfo' => EasyPost::CustomsInfo,
13
13
  'cstitem' => EasyPost::CustomsItem,
14
- 'es' => EasyPost::Beta::EndShipper,
14
+ 'es' => EasyPost::EndShipper,
15
15
  'evt' => EasyPost::Event,
16
16
  'hook' => EasyPost::Webhook,
17
17
  'ins' => EasyPost::Insurance,
@@ -37,10 +37,11 @@ module EasyPost::Util
37
37
  'Address' => EasyPost::Address,
38
38
  'Batch' => EasyPost::Batch,
39
39
  'Brand' => EasyPost::Brand,
40
+ 'CarbonOffset' => EasyPost::CarbonOffset,
40
41
  'CarrierAccount' => EasyPost::CarrierAccount,
41
42
  'CustomsInfo' => EasyPost::CustomsInfo,
42
43
  'CustomsItem' => EasyPost::CustomsItem,
43
- 'EndShipper' => EasyPost::Beta::EndShipper,
44
+ 'EndShipper' => EasyPost::EndShipper,
44
45
  'Event' => EasyPost::Event,
45
46
  'Insurance' => EasyPost::Insurance,
46
47
  'Order' => EasyPost::Order,
@@ -32,4 +32,26 @@ class EasyPost::Webhook < EasyPost::Resource
32
32
 
33
33
  self
34
34
  end
35
+
36
+ # Validate a webhook by comparing the HMAC signature header sent from EasyPost to your shared secret.
37
+ # If the signatures do not match, an error will be raised signifying the webhook either did not originate
38
+ # from EasyPost or the secrets do not match. If the signatures do match, the `event_body` will be returned
39
+ # as JSON.
40
+ def self.validate_webhook(event_body, headers, webhook_secret)
41
+ easypost_hmac_signature = headers['X-Hmac-Signature']
42
+
43
+ if easypost_hmac_signature.nil?
44
+ raise EasyPost::Error.new('Webhook received does not contain an HMAC signature.')
45
+ end
46
+
47
+ encoded_webhook_secret = webhook_secret.unicode_normalize(:nfkd).encode('utf-8')
48
+
49
+ expected_signature = OpenSSL::HMAC.hexdigest('sha256', encoded_webhook_secret, event_body)
50
+ digest = "hmac-sha256-hex=#{expected_signature}"
51
+ unless digest == easypost_hmac_signature
52
+ raise EasyPost::Error.new('Webhook received did not originate from EasyPost or had a webhook secret mismatch.')
53
+ end
54
+
55
+ JSON.parse(event_body)
56
+ end
35
57
  end
data/lib/easypost.rb CHANGED
@@ -16,10 +16,12 @@ require 'easypost/api_key'
16
16
  require 'easypost/batch'
17
17
  require 'easypost/billing'
18
18
  require 'easypost/brand'
19
+ require 'easypost/carbon_offset'
19
20
  require 'easypost/carrier_account'
20
21
  require 'easypost/carrier_type'
21
22
  require 'easypost/customs_info'
22
23
  require 'easypost/customs_item'
24
+ require 'easypost/end_shipper'
23
25
  require 'easypost/event'
24
26
  require 'easypost/insurance'
25
27
  require 'easypost/order'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easypost
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - EasyPost Developers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-18 00:00:00.000000000 Z
11
+ date: 2022-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: brakeman
@@ -158,11 +158,13 @@ extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
160
  - ".gitattributes"
161
+ - ".github/CODEOWNERS"
161
162
  - ".github/ISSUE_TEMPLATE/bug_report.yml"
162
163
  - ".github/ISSUE_TEMPLATE/feature_request.yml"
163
164
  - ".github/PULL_REQUEST_TEMPLATE.md"
164
165
  - ".github/workflows/ci.yml"
165
166
  - ".gitignore"
167
+ - ".gitmodules"
166
168
  - ".rubocop.yml"
167
169
  - CHANGELOG.md
168
170
  - CODE_OF_CONDUCT.md
@@ -188,11 +190,13 @@ files:
188
190
  - lib/easypost/beta/referral.rb
189
191
  - lib/easypost/billing.rb
190
192
  - lib/easypost/brand.rb
193
+ - lib/easypost/carbon_offset.rb
191
194
  - lib/easypost/carrier_account.rb
192
195
  - lib/easypost/carrier_type.rb
193
196
  - lib/easypost/connection.rb
194
197
  - lib/easypost/customs_info.rb
195
198
  - lib/easypost/customs_item.rb
199
+ - lib/easypost/end_shipper.rb
196
200
  - lib/easypost/error.rb
197
201
  - lib/easypost/event.rb
198
202
  - lib/easypost/insurance.rb