easypost 4.4.0 → 4.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: c07c842f7ff2eb209a6f447259afce469b6e1f0f481ea2bf68585869167ea8f9
4
- data.tar.gz: 0ffb89bcb615cd1835f12e70d3c23ffa9ca9033daddddaad9db20a363f483212
3
+ metadata.gz: e9995cfcc5bc7cce1ebefa6343fc31ba18f6f0f4b36dfb7502225b7abb1b40f8
4
+ data.tar.gz: 64d814764933ba53e3de2b01f39ba6fd2195a3a65ec4ec6c01b720078750fc42
5
5
  SHA512:
6
- metadata.gz: f03686d79b7d2023c26dc3c69362955465f3f99efc9b666d101a3499697ed155061afa2e8a47767bd83ae78bdd265d5363339ad4fb7686f47e5cff472483fa6a
7
- data.tar.gz: 25f79bcc1b8c745ae9556c675d3aad56a06518853b4389081325170d2c1c1e425906bb8ded8925d40805ef961c5ccea3394da7bfe1f845117a8701f80526d526
6
+ metadata.gz: 44179f3818dd5d9098eed96f3263b12a67dd7ec415c49fb9efc976b07b858e63ed326c68b0a07415a62da8311cd5b4e72c406bf6650e197ad69956c674b03d76
7
+ data.tar.gz: 86007bac46665593dc205c9c231409698401af9b58da3d2d22049c0510b29528303a625c2be2945814ceffd7ee93838049dba5a8a34dcbf3afe3879f583cee80
@@ -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.0 (2022-08-25)
4
+
5
+ - Moves EndShipper out of beta to the general library namespace
6
+ - Ensure the Easypost object will respond to `.id` when it has one in @values
7
+
8
+ ## v4.6.0 (2022-08-02)
9
+
10
+ - Adds Carbon Offset support
11
+ - Adds ability to create a shipment with carbon_offset
12
+ - Adds ability to buy a shipment with carbon_offset
13
+ - Adds ability to one-call-buy a shipment with carbon_offset
14
+ - Adds ability to rerate a shipment with carbon_offset
15
+ - Adds `validate_webhook` function that returns your webhook or raises an error if there is a `webhook_secret` mismatch
16
+ - Deprecated `PaymentMethod` class, please use `Billing` class for retrieve all payment method function
17
+
18
+ ## v4.5.0 (2022-07-18)
19
+
20
+ - Adds ability to generate shipment forms via `generate_form` function
21
+
3
22
  ## v4.4.0 (2022-07-11)
4
23
 
5
24
  - Adds `Billing.retrieve_payment_methods()`, `Billing.fund_wallet()`, and `Billing.delete_payment_method()` functions
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.4.0
1
+ 4.7.0
@@ -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
@@ -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.
@@ -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.
5
+ # <b>DEPRECATED:</b> Please use <tt>Billing class</tt> instead.
6
+ # Deprecated: v4.5.0 - v6.0.0
6
7
  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)
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
@@ -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
 
@@ -112,4 +128,19 @@ class EasyPost::Shipment < EasyPost::Resource
112
128
 
113
129
  lowest_smartrate
114
130
  end
131
+
132
+ # Generate a form for a Shipment.
133
+ def generate_form(form_type, form_options = {})
134
+ params = {}
135
+ params[:type] = form_type
136
+ merged_params = params.merge(form_options)
137
+ wrapped_params = {
138
+ form: merged_params,
139
+ }
140
+
141
+ response = EasyPost.make_request(:post, "#{url}/forms", @api_key, wrapped_params)
142
+ refresh_from(response, @api_key)
143
+
144
+ self
145
+ end
115
146
  end
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.4.0
4
+ version: 4.7.0
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-11 00:00:00.000000000 Z
11
+ date: 2022-08-25 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