Module: Spree::WebhookPayloadRedaction
- Extended by:
- ActiveSupport::Concern
- Defined in:
- app/models/concerns/spree/webhook_payload_redaction.rb
Overview
Keeps single-use credentials out of the persisted webhook delivery log.
Some events must carry a live credential to their subscriber — a storefront
that owns its transactional emails needs the real password reset token to
build the email. Delivering it over TLS to a merchant-configured endpoint is
intended; keeping a readable copy in spree_webhook_deliveries.payload is
not, because that column is queryable and is served back through the Admin
API delivery log.
Sensitive values are therefore replaced with REDACTION_PLACEHOLDER before the record is written, and re-attached in memory at send time so the outgoing request body is unchanged.
Constant Summary collapse
- SENSITIVE_PAYLOAD_KEYS =
Payload keys under
datawhose values are live credentials. %w[reset_token unsubscribe_token verification_token].freeze
- REDACTION_PLACEHOLDER =
'[REDACTED]'
Class Method Summary collapse
-
.merge(payload, secrets) ⇒ Hash
Re-attaches previously extracted secrets to a redacted payload.
-
.split(payload) ⇒ Array(Hash, Hash)
Splits a payload into the version safe to persist and the secrets held back from it.
Class Method Details
.merge(payload, secrets) ⇒ Hash
Re-attaches previously extracted secrets to a redacted payload.
52 53 54 55 56 57 58 59 60 61 |
# File 'app/models/concerns/spree/webhook_payload_redaction.rb', line 52 def self.merge(payload, secrets) return payload if secrets.blank? transform_data_hashes(payload) do |data| data.to_h do |key, value| secret = secrets[secret_key_for(key)] [key, secret.presence || value] end end end |
.split(payload) ⇒ Array(Hash, Hash)
Splits a payload into the version safe to persist and the secrets held back from it.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'app/models/concerns/spree/webhook_payload_redaction.rb', line 30 def self.split(payload) secrets = {} redacted = transform_data_hashes(payload) do |data| data.to_h do |key, value| if SENSITIVE_PAYLOAD_KEYS.include?(key.to_s) && value.present? secrets[secret_key_for(key)] = value [key, REDACTION_PLACEHOLDER] else [key, value] end end end secrets.empty? ? [payload, {}] : [redacted, secrets] end |