spree_api 5.4.2 → 5.4.4
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 +4 -4
- data/app/controllers/spree/api/v3/store/carts_controller.rb +15 -2
- data/app/jobs/spree/webhook_delivery_job.rb +6 -1
- data/app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb +50 -0
- data/app/serializers/spree/api/v3/product_serializer.rb +1 -1
- data/app/services/spree/webhooks/deliver_webhook.rb +6 -2
- data/app/subscribers/spree/webhook_event_subscriber.rb +5 -2
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60cd4bf73d495ad9c5070f9c589f0e2d7bc4403ea35d01d79f3d00c2208fde26
|
|
4
|
+
data.tar.gz: 5e0517af8dee47eb2c69b465050ddf2db9309bde1130540caa440c076773cfc9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2db9f9ca93c76a1a195219c5af06abcce880cb538d517982700836e9b973b992d14e8ac9c6d77249787fff658410f243e84cdf3b4cd885f376d46e3f03501148
|
|
7
|
+
data.tar.gz: be380eaca399b016e832c5af98985c3183c34a1a8f9d83b8f1354bd9403287e1cc0a22fffabf1f82a05f553c15f34fcc4baf6b339199dfef74b7edeb60cd65e9
|
|
@@ -82,10 +82,15 @@ module Spree
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
# PATCH /api/v3/store/carts/:id/associate
|
|
85
|
-
# Associates a guest cart with the currently authenticated user
|
|
86
|
-
# Requires: JWT authentication + cart ID in URL
|
|
85
|
+
# Associates a guest cart with the currently authenticated user.
|
|
86
|
+
# Requires: JWT authentication + cart ID in URL + possession of the
|
|
87
|
+
# cart's token (x-spree-token). The token is the credential that
|
|
88
|
+
# authorizes claiming the cart, so it is required even when the cart
|
|
89
|
+
# is already the caller's own.
|
|
87
90
|
def associate
|
|
88
91
|
@cart = find_cart_for_association
|
|
92
|
+
authorize!(:update, @cart, cart_token)
|
|
93
|
+
require_cart_token!
|
|
89
94
|
|
|
90
95
|
result = Spree.cart_associate_service.call(guest_order: @cart, user: current_user, guest_only: true)
|
|
91
96
|
|
|
@@ -172,6 +177,14 @@ module Spree
|
|
|
172
177
|
def find_cart_for_association
|
|
173
178
|
current_store.carts.where(user: [nil, current_user]).find_by_prefix_id!(params[:id])
|
|
174
179
|
end
|
|
180
|
+
|
|
181
|
+
# Claiming a cart requires presenting its token, even when the caller
|
|
182
|
+
# already owns it — the token, not ownership, is the claim credential.
|
|
183
|
+
def require_cart_token!
|
|
184
|
+
valid = cart_token.present? && cart_token == @cart.token
|
|
185
|
+
|
|
186
|
+
raise CanCan::AccessDenied.new(nil, :update, @cart) unless valid
|
|
187
|
+
end
|
|
175
188
|
end
|
|
176
189
|
end
|
|
177
190
|
end
|
|
@@ -8,10 +8,15 @@ module Spree
|
|
|
8
8
|
|
|
9
9
|
# Accept optional second argument for backward compatibility with jobs
|
|
10
10
|
# enqueued before this change was deployed.
|
|
11
|
-
|
|
11
|
+
#
|
|
12
|
+
# `payload_secrets` carries credentials withheld from the persisted payload
|
|
13
|
+
# so the outgoing request body stays complete. See
|
|
14
|
+
# {Spree::WebhookPayloadRedaction}.
|
|
15
|
+
def perform(delivery_id, _deprecated_secret_key = nil, payload_secrets: nil)
|
|
12
16
|
delivery = Spree::WebhookDelivery.find_by(id: delivery_id)
|
|
13
17
|
return if delivery.nil?
|
|
14
18
|
|
|
19
|
+
delivery.payload_secrets = payload_secrets
|
|
15
20
|
secret_key = delivery.webhook_endpoint.secret_key
|
|
16
21
|
Spree::Webhooks::DeliverWebhook.call(delivery: delivery, secret_key: secret_key)
|
|
17
22
|
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Api
|
|
5
|
+
module V3
|
|
6
|
+
module Admin
|
|
7
|
+
# Admin API serializer for {Spree::WebhookDelivery}.
|
|
8
|
+
#
|
|
9
|
+
# Surface the delivery log so admins can audit + retry failed webhook
|
|
10
|
+
# attempts. Includes the request payload + response body so they can
|
|
11
|
+
# inspect what was sent and what the endpoint returned.
|
|
12
|
+
class WebhookDeliverySerializer < V3::BaseSerializer
|
|
13
|
+
typelize event_name: :string,
|
|
14
|
+
event_id: [:string, nullable: true],
|
|
15
|
+
response_code: [:number, nullable: true],
|
|
16
|
+
execution_time: [:number, nullable: true],
|
|
17
|
+
error_type: [:string, nullable: true],
|
|
18
|
+
request_errors: [:string, nullable: true],
|
|
19
|
+
response_body: [:string, nullable: true],
|
|
20
|
+
success: [:boolean, nullable: true],
|
|
21
|
+
delivered_at: [:string, nullable: true],
|
|
22
|
+
payload: 'Record<string, unknown>',
|
|
23
|
+
webhook_endpoint_id: :string,
|
|
24
|
+
webhook_endpoint_url: :string
|
|
25
|
+
|
|
26
|
+
attributes :event_name, :event_id, :response_code, :execution_time,
|
|
27
|
+
:error_type, :request_errors, :response_body, :success,
|
|
28
|
+
created_at: :iso8601, updated_at: :iso8601,
|
|
29
|
+
delivered_at: :iso8601
|
|
30
|
+
|
|
31
|
+
# Redacted again on read: deliveries written before payload redaction
|
|
32
|
+
# shipped still hold live credentials in the column.
|
|
33
|
+
attribute :payload do |delivery|
|
|
34
|
+
Spree::WebhookPayloadRedaction.split(delivery.payload).first
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
attribute :webhook_endpoint_id do |delivery|
|
|
38
|
+
delivery.webhook_endpoint&.prefixed_id
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Delegated from the parent endpoint — saves callers from having to
|
|
42
|
+
# join the endpoint payload to show "where did this delivery go?".
|
|
43
|
+
attribute :webhook_endpoint_url do |delivery|
|
|
44
|
+
delivery.webhook_endpoint&.url
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -56,7 +56,7 @@ module Spree
|
|
|
56
56
|
'X-Spree-Webhook-Timestamp' => webhook_timestamp.to_s,
|
|
57
57
|
'X-Spree-Webhook-Event' => @delivery.event_name
|
|
58
58
|
}
|
|
59
|
-
body =
|
|
59
|
+
body = payload_json
|
|
60
60
|
http_options = { open_timeout: TIMEOUT, read_timeout: TIMEOUT, verify_mode: ssl_verify_mode }
|
|
61
61
|
|
|
62
62
|
# SSRF protection is disabled in development so webhooks can reach
|
|
@@ -77,10 +77,14 @@ module Spree
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def generate_signature
|
|
80
|
-
payload_json = @delivery.payload.to_json
|
|
81
80
|
OpenSSL::HMAC.hexdigest('SHA256', @secret_key, "#{webhook_timestamp}.#{payload_json}")
|
|
82
81
|
end
|
|
83
82
|
|
|
83
|
+
# Memoized so the signature is computed over exactly the bytes sent.
|
|
84
|
+
def payload_json
|
|
85
|
+
@payload_json ||= @delivery.deliverable_payload.to_json
|
|
86
|
+
end
|
|
87
|
+
|
|
84
88
|
def webhook_timestamp
|
|
85
89
|
@webhook_timestamp ||= Time.current.to_i
|
|
86
90
|
end
|
|
@@ -50,13 +50,16 @@ module Spree
|
|
|
50
50
|
)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# Live credentials go over the wire but never into the delivery log.
|
|
54
|
+
persisted_payload, secrets = Spree::WebhookPayloadRedaction.split(payload)
|
|
55
|
+
|
|
53
56
|
delivery = endpoint.webhook_deliveries.create!(
|
|
54
57
|
event_name: event.name,
|
|
55
58
|
event_id: event.id,
|
|
56
|
-
payload:
|
|
59
|
+
payload: persisted_payload
|
|
57
60
|
)
|
|
58
61
|
|
|
59
|
-
Spree::WebhookDeliveryJob.perform_later(delivery.id)
|
|
62
|
+
Spree::WebhookDeliveryJob.perform_later(delivery.id, payload_secrets: secrets)
|
|
60
63
|
rescue ActiveRecord::RecordNotUnique
|
|
61
64
|
# Race condition: another thread already created this delivery — safe to ignore
|
|
62
65
|
rescue StandardError => e
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.4.
|
|
4
|
+
version: 5.4.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vendo Connect Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rswag-specs
|
|
@@ -72,14 +72,14 @@ dependencies:
|
|
|
72
72
|
requirements:
|
|
73
73
|
- - '='
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: 5.4.
|
|
75
|
+
version: 5.4.4
|
|
76
76
|
type: :runtime
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
80
|
- - '='
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: 5.4.
|
|
82
|
+
version: 5.4.4
|
|
83
83
|
description: Spree's API
|
|
84
84
|
email:
|
|
85
85
|
- hello@spreecommerce.org
|
|
@@ -180,6 +180,7 @@ files:
|
|
|
180
180
|
- app/serializers/spree/api/v3/admin/store_credit_serializer.rb
|
|
181
181
|
- app/serializers/spree/api/v3/admin/tax_category_serializer.rb
|
|
182
182
|
- app/serializers/spree/api/v3/admin/variant_serializer.rb
|
|
183
|
+
- app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb
|
|
183
184
|
- app/serializers/spree/api/v3/asset_serializer.rb
|
|
184
185
|
- app/serializers/spree/api/v3/base_serializer.rb
|
|
185
186
|
- app/serializers/spree/api/v3/cart_serializer.rb
|
|
@@ -263,9 +264,9 @@ licenses:
|
|
|
263
264
|
- BSD-3-Clause
|
|
264
265
|
metadata:
|
|
265
266
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
266
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.
|
|
267
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.4
|
|
267
268
|
documentation_uri: https://docs.spreecommerce.org/
|
|
268
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.
|
|
269
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.4
|
|
269
270
|
post_install_message:
|
|
270
271
|
rdoc_options: []
|
|
271
272
|
require_paths:
|