spree_api 4.5.5 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/concerns/spree/api/v2/product_list_includes.rb +2 -1
- data/app/controllers/spree/api/v2/base_controller.rb +2 -0
- data/app/controllers/spree/api/v2/data_feeds/google_controller.rb +24 -0
- data/app/controllers/spree/api/v2/platform/data_feeds_controller.rb +15 -0
- data/app/controllers/spree/api/v2/resource_controller.rb +1 -1
- data/app/controllers/spree/api/v2/storefront/products_controller.rb +1 -1
- data/app/controllers/spree/api/v2/storefront/taxons_controller.rb +4 -3
- data/app/helpers/spree/api/v2/collection_options_helpers.rb +1 -1
- data/app/models/spree/webhooks/event.rb +8 -0
- data/app/models/spree/webhooks/event_signature.rb +33 -0
- data/app/models/spree/webhooks/subscriber.rb +2 -1
- data/app/serializers/spree/api/v2/platform/data_feed_serializer.rb +13 -0
- data/app/serializers/spree/api/v2/platform/user_serializer.rb +1 -1
- data/app/serializers/spree/v2/storefront/product_serializer.rb +4 -0
- data/app/serializers/spree/v2/storefront/taxon_serializer.rb +4 -0
- data/app/serializers/spree/v2/storefront/user_serializer.rb +1 -1
- data/app/services/spree/webhooks/subscribers/handle_request.rb +5 -1
- data/app/services/spree/webhooks/subscribers/make_request.rb +3 -2
- data/brakeman.ignore +7 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20221221122100_add_secret_key_to_spree_webhooks_subscribers.rb +5 -0
- data/db/migrate/20230116204600_backfill_secret_key_for_spree_webhooks_subscribers.rb +5 -0
- data/db/migrate/20230116205000_change_secret_key_to_non_null_column.rb +5 -0
- data/docs/oauth/index.yml +5 -5
- data/docs/v2/platform/index.yaml +329 -1
- data/docs/v2/storefront/index.yaml +129 -105
- data/lib/spree/api/dependencies.rb +86 -129
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6324feb2fed1bf0f72361c80626006ad1de52f6516c0799993ab83ae61251166
|
4
|
+
data.tar.gz: c0006992c93b9bdafcc04cd0ac4934f92b08d0c5056b5981e54cbe847cb0a969
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4e71a7c23dc66e6a93df0fea81e8882bf2934de213ecc0d4eee6a260622dbdd82a71c46d8bddcb71147b8b8c3395786ea06dbd3b2f8f23353adf5c8a2139238
|
7
|
+
data.tar.gz: cc8b2ecef98e57554dce21a75608562389d65c4a9a8b049ea26cdf8e38d1729ddf30fde834b1cf4c928b1ae970597a2039a303ef2fd7a5cd665eadafc9f4fc75
|
@@ -82,6 +82,8 @@ module Spree
|
|
82
82
|
@spree_current_user ||= doorkeeper_token.resource_owner
|
83
83
|
end
|
84
84
|
|
85
|
+
alias try_spree_current_user spree_current_user # for compatibility with spree_legacy_frontend
|
86
|
+
|
85
87
|
def spree_authorize!(action, subject, *args)
|
86
88
|
authorize!(action, subject, *args)
|
87
89
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module DataFeeds
|
5
|
+
class GoogleController < ::Spree::Api::V2::BaseController
|
6
|
+
def rss_feed
|
7
|
+
send_data data_feeds_google_rss_service.value[:file], filename: 'products.rss', type: 'text/xml'
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def settings
|
13
|
+
@settings ||= Spree::DataFeed::Google.find_by!(store: current_store, slug: params[:slug], active: true)
|
14
|
+
end
|
15
|
+
|
16
|
+
def data_feeds_google_rss_service
|
17
|
+
Spree::Dependencies.data_feeds_google_rss_service.constantize.new.call(settings)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -35,7 +35,7 @@ module Spree
|
|
35
35
|
base_scope = model_class.for_store(current_store)
|
36
36
|
base_scope = base_scope.accessible_by(current_ability, :show) unless skip_cancancan
|
37
37
|
base_scope = base_scope.includes(scope_includes) if scope_includes.any? && action_name == 'index'
|
38
|
-
base_scope
|
38
|
+
model_class.include?(TranslatableResource) ? base_scope.i18n : base_scope
|
39
39
|
end
|
40
40
|
|
41
41
|
def scope_includes
|
@@ -16,7 +16,7 @@ module Spree
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def resource
|
19
|
-
@resource ||= scope.find_by(slug: params[:id]) || scope.find(params[:id])
|
19
|
+
@resource ||= find_with_fallback_default_locale { scope.find_by(slug: params[:id]) } || scope.find(params[:id])
|
20
20
|
end
|
21
21
|
|
22
22
|
def collection_sorter
|
@@ -22,7 +22,7 @@ module Spree
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def resource
|
25
|
-
@resource ||= scope.find_by(permalink: params[:id]) || scope.find(params[:id])
|
25
|
+
@resource ||= find_with_fallback_default_locale { scope.find_by(permalink: params[:id]) } || scope.find(params[:id])
|
26
26
|
end
|
27
27
|
|
28
28
|
def model_class
|
@@ -30,13 +30,14 @@ module Spree
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def scope_includes
|
33
|
-
node_includes = %i[icon parent taxonomy]
|
33
|
+
node_includes = %i[icon parent taxonomy translations]
|
34
34
|
|
35
35
|
{
|
36
36
|
parent: node_includes,
|
37
37
|
children: node_includes,
|
38
38
|
taxonomy: [root: node_includes],
|
39
|
-
icon: [attachment_attachment: :blob]
|
39
|
+
icon: [attachment_attachment: :blob],
|
40
|
+
translations: []
|
40
41
|
}
|
41
42
|
end
|
42
43
|
|
@@ -23,7 +23,7 @@ module Spree
|
|
23
23
|
# leaving this method in public scope so it's still possible to modify
|
24
24
|
# those params to support non-standard non-JSON API parameters
|
25
25
|
def collection_permitted_params
|
26
|
-
params.permit(:format, :page, :per_page, :sort, :include, fields: {}, filter: {})
|
26
|
+
params.permit(:format, :page, :per_page, :sort, :include, :locale, fields: {}, filter: {})
|
27
27
|
end
|
28
28
|
|
29
29
|
private
|
@@ -7,6 +7,14 @@ module Spree
|
|
7
7
|
|
8
8
|
self.whitelisted_ransackable_associations = %w[subscriber]
|
9
9
|
self.whitelisted_ransackable_attributes = %w[name request_errors response_code success url]
|
10
|
+
|
11
|
+
# Computes the base64-encoded HMAC SHA256 signature of the event for the given payload.
|
12
|
+
#
|
13
|
+
# @param payload [Hash, String] The payload for to the webhook subscriber.
|
14
|
+
# @return [String]
|
15
|
+
def signature_for(payload)
|
16
|
+
EventSignature.new(self, payload).computed_signature
|
17
|
+
end
|
10
18
|
end
|
11
19
|
end
|
12
20
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module Spree
|
5
|
+
module Webhooks
|
6
|
+
class EventSignature
|
7
|
+
def initialize(event, payload)
|
8
|
+
@event = event
|
9
|
+
@payload = payload
|
10
|
+
end
|
11
|
+
|
12
|
+
# Generates a base64-encoded HMAC SHA256 signature for the payload of the event.
|
13
|
+
#
|
14
|
+
# By using the stringified payload, the signature is made tamper-proof as any
|
15
|
+
# alterations of the data during transit will lead to an incorrect signature
|
16
|
+
# comparison by the client.
|
17
|
+
#
|
18
|
+
# @return [String] The computed signature
|
19
|
+
def computed_signature
|
20
|
+
@computed_signature ||=
|
21
|
+
Base64.strict_encode64(
|
22
|
+
OpenSSL::HMAC.digest('sha256', @event.subscriber.secret_key, payload)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def payload
|
29
|
+
@payload.is_a?(String) ? @payload : @payload.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -5,10 +5,11 @@ module Spree
|
|
5
5
|
include Spree::VendorConcern
|
6
6
|
end
|
7
7
|
|
8
|
+
has_secure_token :secret_key
|
9
|
+
|
8
10
|
has_many :events, inverse_of: :subscriber
|
9
11
|
|
10
12
|
validates :url, 'spree/url': true, presence: true
|
11
|
-
|
12
13
|
validate :check_uri_path
|
13
14
|
|
14
15
|
self.whitelisted_ransackable_attributes = %w[active subscriptions url]
|
@@ -5,7 +5,7 @@ module Spree
|
|
5
5
|
class UserSerializer < BaseSerializer
|
6
6
|
set_type :user
|
7
7
|
|
8
|
-
attributes :email, :first_name, :last_name, :created_at, :updated_at, :public_metadata, :private_metadata
|
8
|
+
attributes :email, :first_name, :last_name, :created_at, :updated_at, :public_metadata, :private_metadata, :selected_locale
|
9
9
|
|
10
10
|
attribute :average_order_value do |user, params|
|
11
11
|
price_stats(user.report_values_for(:average_order_value, params[:store]))
|
@@ -44,6 +44,10 @@ module Spree
|
|
44
44
|
display_compare_at_price(product, params[:currency])
|
45
45
|
end
|
46
46
|
|
47
|
+
attribute :localized_slugs do |product, params|
|
48
|
+
product.localized_slugs_for_store(params[:store])
|
49
|
+
end
|
50
|
+
|
47
51
|
has_many :variants
|
48
52
|
has_many :option_types
|
49
53
|
has_many :product_properties
|
@@ -19,6 +19,10 @@ module Spree
|
|
19
19
|
taxon.leaf?
|
20
20
|
end
|
21
21
|
|
22
|
+
attribute :localized_slugs do |taxon, params|
|
23
|
+
taxon.localized_slugs_for_store(params[:store])
|
24
|
+
end
|
25
|
+
|
22
26
|
belongs_to :parent, record_type: :taxon, serializer: :taxon
|
23
27
|
belongs_to :taxonomy, record_type: :taxonomy
|
24
28
|
|
@@ -4,7 +4,7 @@ module Spree
|
|
4
4
|
class UserSerializer < BaseSerializer
|
5
5
|
set_type :user
|
6
6
|
|
7
|
-
attributes :email, :first_name, :last_name, :public_metadata
|
7
|
+
attributes :email, :first_name, :selected_locale, :last_name, :public_metadata
|
8
8
|
|
9
9
|
attribute :store_credits do |user|
|
10
10
|
user.total_available_store_credit
|
@@ -39,7 +39,11 @@ module Spree
|
|
39
39
|
|
40
40
|
def request
|
41
41
|
@request ||=
|
42
|
-
Spree::Webhooks::Subscribers::MakeRequest.new(
|
42
|
+
Spree::Webhooks::Subscribers::MakeRequest.new(
|
43
|
+
signature: event.signature_for(body_with_event_metadata),
|
44
|
+
url: url,
|
45
|
+
webhook_payload_body: body_with_event_metadata
|
46
|
+
)
|
43
47
|
end
|
44
48
|
alias make_request request
|
45
49
|
|
@@ -4,8 +4,9 @@ module Spree
|
|
4
4
|
module Webhooks
|
5
5
|
module Subscribers
|
6
6
|
class MakeRequest
|
7
|
-
def initialize(url:, webhook_payload_body:)
|
7
|
+
def initialize(signature:, url:, webhook_payload_body:)
|
8
8
|
@execution_time_in_milliseconds = 0
|
9
|
+
@signature = signature
|
9
10
|
@url = url
|
10
11
|
@webhook_payload_body = webhook_payload_body
|
11
12
|
@webhooks_timeout = ENV['SPREE_WEBHOOKS_TIMEOUT']
|
@@ -49,7 +50,7 @@ module Spree
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def request
|
52
|
-
req = Net::HTTP::Post.new(uri_path, HEADERS)
|
53
|
+
req = Net::HTTP::Post.new(uri_path, HEADERS.merge('X-Spree-Hmac-SHA256' => @signature))
|
53
54
|
req.body = webhook_payload_body
|
54
55
|
@request ||= begin
|
55
56
|
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
data/brakeman.ignore
ADDED
data/config/routes.rb
CHANGED
@@ -196,6 +196,9 @@ Spree::Core::Engine.add_routes do
|
|
196
196
|
# Store API
|
197
197
|
resources :stores
|
198
198
|
|
199
|
+
# Data Feeds API
|
200
|
+
resources :data_feeds
|
201
|
+
|
199
202
|
# Configurations API
|
200
203
|
resources :payment_methods
|
201
204
|
resources :shipping_categories
|
@@ -207,6 +210,11 @@ Spree::Core::Engine.add_routes do
|
|
207
210
|
resources :subscribers
|
208
211
|
end
|
209
212
|
end
|
213
|
+
|
214
|
+
namespace :data_feeds do
|
215
|
+
# google data feed API
|
216
|
+
get '/google/:slug', to: 'google#rss_feed'
|
217
|
+
end
|
210
218
|
end
|
211
219
|
end
|
212
220
|
end
|
data/docs/oauth/index.yml
CHANGED
@@ -2,7 +2,7 @@ openapi: 3.0.3
|
|
2
2
|
servers:
|
3
3
|
- url: 'https://demo.spreecommerce.org'
|
4
4
|
description: demo
|
5
|
-
- url: 'http://localhost:
|
5
|
+
- url: 'http://localhost:4000'
|
6
6
|
description: localhost
|
7
7
|
info:
|
8
8
|
version: 1.0.0
|
@@ -139,7 +139,7 @@ components:
|
|
139
139
|
- expires_in
|
140
140
|
- refresh_token
|
141
141
|
- created_at
|
142
|
-
x-internal:
|
142
|
+
x-internal: false
|
143
143
|
CreateTokenBody:
|
144
144
|
type: object
|
145
145
|
x-examples:
|
@@ -152,7 +152,7 @@ components:
|
|
152
152
|
username: spree@example.com
|
153
153
|
password: spree123
|
154
154
|
scope: admin
|
155
|
-
x-internal:
|
155
|
+
x-internal: false
|
156
156
|
title: 'Create a new token (grant_type: password)'
|
157
157
|
description: ''
|
158
158
|
properties:
|
@@ -186,7 +186,7 @@ components:
|
|
186
186
|
example-1:
|
187
187
|
grant_type: refresh_token
|
188
188
|
refresh_token: SqJDIwX00fehqHxS6xmb-kzqAlrYe_0EHgekMexVT8k
|
189
|
-
x-internal:
|
189
|
+
x-internal: false
|
190
190
|
title: 'Create a new token (grant_type: client_credentials)'
|
191
191
|
description: ''
|
192
192
|
properties:
|
@@ -213,7 +213,7 @@ components:
|
|
213
213
|
example-1:
|
214
214
|
grant_type: refresh_token
|
215
215
|
refresh_token: SqJDIwX00fehqHxS6xmb-kzqAlrYe_0EHgekMexVT8k
|
216
|
-
x-internal:
|
216
|
+
x-internal: false
|
217
217
|
title: 'Refresh an existing token (grant_type: refresh_token)'
|
218
218
|
description: ''
|
219
219
|
properties:
|