spree_api 5.4.0.beta4 → 5.4.0.beta6
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/Rakefile +4 -4
- data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/error_handler.rb +12 -2
- data/app/controllers/concerns/spree/api/v3/http_caching.rb +10 -2
- data/app/controllers/concerns/spree/api/v3/idempotent.rb +82 -0
- data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +4 -1
- data/app/controllers/concerns/spree/api/v3/order_concern.rb +1 -6
- data/app/controllers/concerns/spree/api/v3/rate_limit_headers.rb +31 -0
- data/app/controllers/concerns/spree/api/v3/resource_serializer.rb +30 -2
- data/app/controllers/concerns/spree/api/v3/security_headers.rb +4 -0
- data/app/controllers/spree/api/v3/admin/base_controller.rb +28 -0
- data/app/controllers/spree/api/v3/admin/resource_controller.rb +28 -0
- data/app/controllers/spree/api/v3/base_controller.rb +20 -1
- data/app/controllers/spree/api/v3/resource_controller.rb +35 -3
- data/app/controllers/spree/api/v3/store/auth_controller.rb +4 -24
- data/app/controllers/spree/api/v3/store/base_controller.rb +0 -11
- data/app/controllers/spree/api/v3/store/cart_controller.rb +6 -2
- data/app/controllers/spree/api/v3/store/categories/products_controller.rb +37 -0
- data/app/controllers/spree/api/v3/store/{taxons_controller.rb → categories_controller.rb} +8 -6
- data/app/controllers/spree/api/v3/store/countries_controller.rb +6 -0
- data/app/controllers/spree/api/v3/store/currencies_controller.rb +4 -0
- data/app/controllers/spree/api/v3/store/customers_controller.rb +102 -0
- data/app/controllers/spree/api/v3/store/locales_controller.rb +4 -0
- data/app/controllers/spree/api/v3/store/markets/countries_controller.rb +6 -0
- data/app/controllers/spree/api/v3/store/markets_controller.rb +8 -0
- data/app/controllers/spree/api/v3/store/orders/payments_controller.rb +38 -0
- data/app/controllers/spree/api/v3/store/orders_controller.rb +3 -2
- data/app/controllers/spree/api/v3/store/products/filters_controller.rb +9 -8
- data/app/controllers/spree/api/v3/store/products_controller.rb +12 -19
- data/app/jobs/spree/webhook_delivery_job.rb +4 -1
- data/app/serializers/spree/api/v3/admin/address_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +36 -0
- data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/asset_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/admin/category_serializer.rb +33 -0
- data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +22 -0
- data/app/serializers/spree/api/v3/admin/customer_serializer.rb +8 -6
- data/app/serializers/spree/api/v3/admin/digital_link_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/admin/image_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +36 -1
- data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/admin/order_promotion_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +47 -6
- data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +14 -0
- data/app/serializers/spree/api/v3/admin/payment_serializer.rb +56 -0
- data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +23 -6
- data/app/serializers/spree/api/v3/admin/refund_serializer.rb +21 -0
- data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/admin/shipment_serializer.rb +44 -0
- data/app/serializers/spree/api/v3/admin/shipping_category_serializer.rb +14 -0
- data/app/serializers/spree/api/v3/admin/shipping_method_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/shipping_rate_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +27 -0
- data/app/serializers/spree/api/v3/admin/tax_category_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/variant_serializer.rb +11 -14
- data/app/serializers/spree/api/v3/base_serializer.rb +21 -4
- data/app/serializers/spree/api/v3/category_serializer.rb +71 -0
- data/app/serializers/spree/api/v3/country_serializer.rb +2 -1
- data/app/serializers/spree/api/v3/customer_serializer.rb +2 -1
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +5 -21
- data/app/serializers/spree/api/v3/order_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/payment_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/product_serializer.rb +11 -11
- data/app/serializers/spree/api/v3/shipping_category_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/shipping_rate_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/tax_category_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/variant_serializer.rb +4 -4
- data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
- data/app/services/spree/api/v3/filters_aggregator.rb +31 -25
- data/app/services/spree/webhooks/deliver_webhook.rb +23 -17
- data/app/subscribers/spree/webhook_event_subscriber.rb +1 -1
- data/config/initializers/alba.rb +1 -1
- data/config/initializers/typelizer.rb +26 -16
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +10 -10
- data/lib/spree/api/configuration.rb +3 -1
- data/lib/spree/api/dependencies.rb +31 -5
- data/lib/spree/api/engine.rb +15 -0
- data/lib/spree/api/openapi/schema_helper.rb +27 -7
- data/lib/spree/api/testing_support/v3/base.rb +24 -1
- metadata +43 -19
- data/app/controllers/spree/api/v3/store/customer/account_controller.rb +0 -38
- data/app/controllers/spree/api/v3/store/stores_controller.rb +0 -26
- data/app/controllers/spree/api/v3/store/taxonomies_controller.rb +0 -19
- data/app/controllers/spree/api/v3/store/taxons/products_controller.rb +0 -37
- data/app/serializers/spree/api/v3/admin/taxon_serializer.rb +0 -20
- data/app/serializers/spree/api/v3/admin/taxonomy_serializer.rb +0 -15
- data/app/serializers/spree/api/v3/store_serializer.rb +0 -38
- data/app/serializers/spree/api/v3/taxon_serializer.rb +0 -78
- data/app/serializers/spree/api/v3/taxonomy_serializer.rb +0 -33
- data/app/services/spree/api/v3/orders/update.rb +0 -105
|
@@ -4,7 +4,7 @@ module Spree
|
|
|
4
4
|
# Store API Order Serializer
|
|
5
5
|
# Customer-facing order data
|
|
6
6
|
class OrderSerializer < BaseSerializer
|
|
7
|
-
typelize number: :string, state: :string, token: :string, email: [:string, nullable: true],
|
|
7
|
+
typelize number: :string, state: :string, checkout_steps: 'string[]', token: :string, email: [:string, nullable: true],
|
|
8
8
|
special_instructions: [:string, nullable: true], currency: :string, locale: [:string, nullable: true], item_count: :number,
|
|
9
9
|
state_lock_version: :number, shipment_state: [:string, nullable: true], payment_state: [:string, nullable: true],
|
|
10
10
|
item_total: :string, display_item_total: :string,
|
|
@@ -17,7 +17,7 @@ module Spree
|
|
|
17
17
|
total: :string, display_total: :string, completed_at: [:string, nullable: true],
|
|
18
18
|
bill_address: { nullable: true }, ship_address: { nullable: true }
|
|
19
19
|
|
|
20
|
-
attributes :number, :state, :token, :email, :special_instructions,
|
|
20
|
+
attributes :number, :state, :checkout_steps, :token, :email, :special_instructions,
|
|
21
21
|
:currency, :locale, :item_count, :state_lock_version, :shipment_state, :payment_state,
|
|
22
22
|
:item_total, :display_item_total, :ship_total, :display_ship_total,
|
|
23
23
|
:adjustment_total, :display_adjustment_total, :promo_total, :display_promo_total,
|
|
@@ -6,7 +6,7 @@ module Spree
|
|
|
6
6
|
number: :string, amount: :string, display_amount: :string,
|
|
7
7
|
source_type: [:string, nullable: true, enum: %w[credit_card store_credit payment_source]],
|
|
8
8
|
source_id: [:string, nullable: true],
|
|
9
|
-
source: '
|
|
9
|
+
source: 'CreditCard | StoreCredit | PaymentSource | null'
|
|
10
10
|
|
|
11
11
|
attribute :payment_method_id do |payment|
|
|
12
12
|
payment.payment_method&.prefixed_id
|
|
@@ -11,8 +11,8 @@ module Spree
|
|
|
11
11
|
thumbnail_url: [:string, nullable: true],
|
|
12
12
|
available_on: [:string, nullable: true],
|
|
13
13
|
purchasable: :boolean, in_stock: :boolean, backorderable: :boolean, available: :boolean,
|
|
14
|
-
price: '
|
|
15
|
-
original_price: ['
|
|
14
|
+
price: 'Price',
|
|
15
|
+
original_price: ['Price', nullable: true],
|
|
16
16
|
tags: [:string, multi: true]
|
|
17
17
|
|
|
18
18
|
attributes :name, :description, :slug,
|
|
@@ -71,37 +71,37 @@ module Spree
|
|
|
71
71
|
many :variant_images,
|
|
72
72
|
key: :images,
|
|
73
73
|
resource: Spree.api.image_serializer,
|
|
74
|
-
if: proc {
|
|
74
|
+
if: proc { expand?('images') }
|
|
75
75
|
|
|
76
76
|
many :variants,
|
|
77
77
|
resource: Spree.api.variant_serializer,
|
|
78
|
-
if: proc {
|
|
78
|
+
if: proc { expand?('variants') }
|
|
79
79
|
|
|
80
80
|
one :default_variant,
|
|
81
81
|
resource: Spree.api.variant_serializer,
|
|
82
|
-
if: proc {
|
|
82
|
+
if: proc { expand?('default_variant') }
|
|
83
83
|
|
|
84
84
|
one :master,
|
|
85
85
|
key: :master_variant,
|
|
86
86
|
resource: Spree.api.variant_serializer,
|
|
87
|
-
if: proc {
|
|
87
|
+
if: proc { expand?('master_variant') }
|
|
88
88
|
|
|
89
89
|
many :option_types,
|
|
90
90
|
resource: Spree.api.option_type_serializer,
|
|
91
|
-
if: proc {
|
|
91
|
+
if: proc { expand?('option_types') }
|
|
92
92
|
|
|
93
93
|
many :taxons,
|
|
94
94
|
proc { |taxons, params|
|
|
95
95
|
taxons.select { |t| t.taxonomy.store_id == params[:store].id }
|
|
96
96
|
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
key: :categories,
|
|
98
|
+
resource: Spree.api.category_serializer,
|
|
99
|
+
if: proc { expand?('categories') }
|
|
100
100
|
|
|
101
101
|
many :public_metafields,
|
|
102
102
|
key: :metafields,
|
|
103
103
|
resource: Spree.api.metafield_serializer,
|
|
104
|
-
if: proc {
|
|
104
|
+
if: proc { expand?('metafields') }
|
|
105
105
|
end
|
|
106
106
|
end
|
|
107
107
|
end
|
|
@@ -3,17 +3,13 @@ module Spree
|
|
|
3
3
|
module V3
|
|
4
4
|
class ShippingRateSerializer < BaseSerializer
|
|
5
5
|
typelize name: :string, selected: :boolean, shipping_method_id: :string,
|
|
6
|
-
cost: :
|
|
6
|
+
cost: :string, display_cost: :string
|
|
7
7
|
|
|
8
8
|
attribute :shipping_method_id do |shipping_rate|
|
|
9
9
|
shipping_rate.shipping_method&.prefixed_id
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
attributes :name, :selected
|
|
13
|
-
|
|
14
|
-
attribute :cost do |shipping_rate|
|
|
15
|
-
shipping_rate.cost.to_f
|
|
16
|
-
end
|
|
12
|
+
attributes :name, :selected, :cost
|
|
17
13
|
|
|
18
14
|
attribute :display_cost do |shipping_rate|
|
|
19
15
|
shipping_rate.display_cost.to_s
|
|
@@ -9,8 +9,8 @@ module Spree
|
|
|
9
9
|
thumbnail: [:string, nullable: true],
|
|
10
10
|
purchasable: :boolean, in_stock: :boolean, backorderable: :boolean,
|
|
11
11
|
weight: [:number, nullable: true], height: [:number, nullable: true], width: [:number, nullable: true], depth: [:number, nullable: true],
|
|
12
|
-
price: '
|
|
13
|
-
original_price: ['
|
|
12
|
+
price: 'Price',
|
|
13
|
+
original_price: ['Price', nullable: true]
|
|
14
14
|
|
|
15
15
|
attribute :product_id do |variant|
|
|
16
16
|
variant.product&.prefixed_id
|
|
@@ -72,14 +72,14 @@ module Spree
|
|
|
72
72
|
# Conditional associations
|
|
73
73
|
many :images,
|
|
74
74
|
resource: Spree.api.image_serializer,
|
|
75
|
-
if: proc {
|
|
75
|
+
if: proc { expand?('images') }
|
|
76
76
|
|
|
77
77
|
many :option_values, resource: Spree.api.option_value_serializer
|
|
78
78
|
|
|
79
79
|
many :public_metafields,
|
|
80
80
|
key: :metafields,
|
|
81
81
|
resource: Spree.api.metafield_serializer,
|
|
82
|
-
if: proc {
|
|
82
|
+
if: proc { expand?('metafields') }
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
end
|
|
@@ -2,22 +2,20 @@ module Spree
|
|
|
2
2
|
module Api
|
|
3
3
|
module V3
|
|
4
4
|
class FiltersAggregator
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# @param scope [ActiveRecord::Relation] Base product scope (already filtered by store, availability, taxon, etc.)
|
|
5
|
+
# @param scope [ActiveRecord::Relation] Base product scope (already filtered by store, availability, category, etc.)
|
|
8
6
|
# @param currency [String] Currency for price range
|
|
9
|
-
# @param
|
|
10
|
-
def initialize(scope:, currency:,
|
|
7
|
+
# @param category [Spree::Category, nil] Optional category for default_sort and category filtering context
|
|
8
|
+
def initialize(scope:, currency:, category: nil)
|
|
11
9
|
@scope = scope
|
|
12
10
|
@currency = currency
|
|
13
|
-
@
|
|
11
|
+
@category = category
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def call
|
|
17
15
|
{
|
|
18
16
|
filters: build_filters,
|
|
19
17
|
sort_options: sort_options,
|
|
20
|
-
default_sort: @
|
|
18
|
+
default_sort: to_api_sort(@category&.sort_order || 'manual'),
|
|
21
19
|
total_count: @scope.distinct.count
|
|
22
20
|
}
|
|
23
21
|
end
|
|
@@ -29,12 +27,20 @@ module Spree
|
|
|
29
27
|
price_filter,
|
|
30
28
|
availability_filter,
|
|
31
29
|
*option_type_filters,
|
|
32
|
-
|
|
30
|
+
category_filter
|
|
33
31
|
].compact
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
def sort_options
|
|
37
|
-
|
|
35
|
+
Spree::Taxon::SORT_ORDERS.map { |id| { id: to_api_sort(id) } }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Converts internal sort format ('price asc') to API format ('price', '-price')
|
|
39
|
+
def to_api_sort(sort_value)
|
|
40
|
+
return sort_value unless sort_value.include?(' ')
|
|
41
|
+
|
|
42
|
+
field, direction = sort_value.split(' ', 2)
|
|
43
|
+
direction == 'desc' ? "-#{field}" : field
|
|
38
44
|
end
|
|
39
45
|
|
|
40
46
|
|
|
@@ -87,7 +93,7 @@ module Spree
|
|
|
87
93
|
|
|
88
94
|
def option_value_data(option_type, option_value)
|
|
89
95
|
# Count products in scope that have this option value
|
|
90
|
-
# We use a subquery approach to avoid GROUP BY conflicts when scope includes joins (like
|
|
96
|
+
# We use a subquery approach to avoid GROUP BY conflicts when scope includes joins (like in_category)
|
|
91
97
|
# Join directly to option_value_variants for efficiency (skips joining through option_values table)
|
|
92
98
|
count = Spree::Product
|
|
93
99
|
.where(id: base_scope_product_ids)
|
|
@@ -109,31 +115,31 @@ module Spree
|
|
|
109
115
|
@base_scope_product_ids ||= @scope.reorder('').distinct.pluck(:id)
|
|
110
116
|
end
|
|
111
117
|
|
|
112
|
-
def
|
|
113
|
-
return nil if @
|
|
118
|
+
def category_filter
|
|
119
|
+
return nil if @category.nil?
|
|
114
120
|
|
|
115
|
-
# Get child
|
|
116
|
-
|
|
117
|
-
# Only include
|
|
118
|
-
@scope.
|
|
121
|
+
# Get child categories at the next depth level
|
|
122
|
+
child_categories = @category.children.order(:lft).select do |child|
|
|
123
|
+
# Only include categories that have products in the current scope
|
|
124
|
+
@scope.in_category(child).exists?
|
|
119
125
|
end
|
|
120
126
|
|
|
121
|
-
return nil if
|
|
127
|
+
return nil if child_categories.empty?
|
|
122
128
|
|
|
123
129
|
{
|
|
124
|
-
id: '
|
|
125
|
-
type: '
|
|
126
|
-
options:
|
|
130
|
+
id: 'categories',
|
|
131
|
+
type: 'category',
|
|
132
|
+
options: child_categories.map { |c| category_option_data(c) }
|
|
127
133
|
}
|
|
128
134
|
end
|
|
129
135
|
|
|
130
|
-
def
|
|
131
|
-
count = @scope.
|
|
136
|
+
def category_option_data(category)
|
|
137
|
+
count = @scope.in_category(category).distinct.count
|
|
132
138
|
|
|
133
139
|
{
|
|
134
|
-
id:
|
|
135
|
-
name:
|
|
136
|
-
permalink:
|
|
140
|
+
id: category.prefixed_id,
|
|
141
|
+
name: category.name,
|
|
142
|
+
permalink: category.permalink,
|
|
137
143
|
count: count
|
|
138
144
|
}
|
|
139
145
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
3
|
+
require 'ssrf_filter'
|
|
4
4
|
require 'openssl'
|
|
5
5
|
|
|
6
6
|
module Spree
|
|
@@ -49,32 +49,38 @@ module Spree
|
|
|
49
49
|
private
|
|
50
50
|
|
|
51
51
|
def make_request
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
52
|
+
SsrfFilter.post(
|
|
53
|
+
@delivery.url,
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type' => 'application/json',
|
|
56
|
+
'User-Agent' => 'Spree-Webhooks/1.0',
|
|
57
|
+
'X-Spree-Webhook-Signature' => generate_signature,
|
|
58
|
+
'X-Spree-Webhook-Timestamp' => webhook_timestamp.to_s,
|
|
59
|
+
'X-Spree-Webhook-Event' => @delivery.event_name
|
|
60
|
+
},
|
|
61
|
+
body: @delivery.payload.to_json,
|
|
62
|
+
http_options: {
|
|
63
|
+
open_timeout: TIMEOUT,
|
|
64
|
+
read_timeout: TIMEOUT,
|
|
65
|
+
verify_mode: ssl_verify_mode
|
|
66
|
+
}
|
|
67
|
+
)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
def generate_signature
|
|
70
71
|
payload_json = @delivery.payload.to_json
|
|
71
|
-
OpenSSL::HMAC.hexdigest('SHA256', @secret_key, payload_json)
|
|
72
|
+
OpenSSL::HMAC.hexdigest('SHA256', @secret_key, "#{webhook_timestamp}.#{payload_json}")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def webhook_timestamp
|
|
76
|
+
@webhook_timestamp ||= Time.current.to_i
|
|
72
77
|
end
|
|
73
78
|
|
|
74
79
|
def ssl_verify_mode
|
|
75
80
|
if Spree::Api::Config.webhooks_verify_ssl
|
|
76
81
|
OpenSSL::SSL::VERIFY_PEER
|
|
77
82
|
else
|
|
83
|
+
Rails.logger.warn('[Spree] Webhook SSL verification is disabled. This is not recommended for production environments.')
|
|
78
84
|
OpenSSL::SSL::VERIFY_NONE
|
|
79
85
|
end
|
|
80
86
|
end
|
|
@@ -48,7 +48,7 @@ module Spree
|
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
# Queue the delivery job
|
|
51
|
-
Spree::WebhookDeliveryJob.perform_later(delivery.id
|
|
51
|
+
Spree::WebhookDeliveryJob.perform_later(delivery.id)
|
|
52
52
|
rescue StandardError => e
|
|
53
53
|
Rails.logger.error "[Spree Webhooks] Error queuing delivery for endpoint #{endpoint.id}: #{e.message}"
|
|
54
54
|
Rails.error.report(e)
|
data/config/initializers/alba.rb
CHANGED
|
@@ -2,24 +2,34 @@
|
|
|
2
2
|
# via `bundle exec rake typelizer:generate`. Set ENABLE_TYPELIZER=1 to enable.
|
|
3
3
|
ENV["DISABLE_TYPELIZER"] ||= "true" unless ENV["ENABLE_TYPELIZER"]
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Rails.application.config.after_initialize do
|
|
6
6
|
api_root = Spree::Api::Engine.root
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
api_root.join('app/serializers/spree/api/v3')
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
config.output_dir = api_root.join('../../packages/sdk/src/types/generated')
|
|
13
|
-
config.comments = true
|
|
8
|
+
Typelizer.configure do |config|
|
|
9
|
+
config.dirs = [api_root.join('app/serializers/spree/api/v3')]
|
|
10
|
+
config.comments = true
|
|
11
|
+
config.listen = false
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
.
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
# Store SDK — no prefix, package provides namespace
|
|
14
|
+
config.writer(:store) do |c|
|
|
15
|
+
c.output_dir = api_root.join('../../packages/sdk/src/types/generated')
|
|
16
|
+
c.reject_class = ->(serializer:) { serializer.name.to_s.include?('::Admin::') }
|
|
17
|
+
c.serializer_name_mapper = ->(serializer) {
|
|
18
|
+
serializer.name.to_s
|
|
19
|
+
.sub(/\ASpree::Api::V3::/, '')
|
|
20
|
+
.sub(/Serializer\z/, '')
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
# Admin SDK — no prefix, package provides namespace
|
|
25
|
+
config.writer(:admin) do |c|
|
|
26
|
+
c.output_dir = api_root.join('../../packages/admin-sdk/src/types/generated')
|
|
27
|
+
c.reject_class = ->(serializer:) { !serializer.name.to_s.include?('::Admin::') }
|
|
28
|
+
c.serializer_name_mapper = ->(serializer) {
|
|
29
|
+
serializer.name.to_s
|
|
30
|
+
.sub(/\ASpree::Api::V3::Admin::/, '')
|
|
31
|
+
.sub(/Serializer\z/, '')
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
25
35
|
end
|
data/config/locales/en.yml
CHANGED
|
@@ -6,6 +6,7 @@ en:
|
|
|
6
6
|
invalid_api_key: Invalid API key (%{key}) specified.
|
|
7
7
|
invalid_resource: Invalid resource. Please fix errors and try again.
|
|
8
8
|
invalid_taxonomy_id: Invalid taxonomy id.
|
|
9
|
+
current_password_invalid: Current password is invalid or missing
|
|
9
10
|
must_specify_api_key: You must specify an API key.
|
|
10
11
|
negative_quantity: quantity is negative
|
|
11
12
|
order:
|
|
@@ -23,6 +24,10 @@ en:
|
|
|
23
24
|
shipment_transfer_success: Variants successfully transferred
|
|
24
25
|
stock_location_required: A stock_location_id parameter must be provided in order to retrieve stock movements.
|
|
25
26
|
unauthorized: You are not authorized to perform that action.
|
|
27
|
+
v3:
|
|
28
|
+
payments:
|
|
29
|
+
session_required: This payment method requires a payment session. Use the payment sessions endpoint instead.
|
|
30
|
+
method_unavailable: This payment method is not available for this order.
|
|
26
31
|
v2:
|
|
27
32
|
cart:
|
|
28
33
|
no_coupon_code: No coupon code provided and the Order doesn't have any coupon code promotions applied
|
data/config/routes.rb
CHANGED
|
@@ -4,12 +4,11 @@ Spree::Core::Engine.add_routes do
|
|
|
4
4
|
namespace :store do
|
|
5
5
|
# Authentication
|
|
6
6
|
post 'auth/login', to: 'auth#create'
|
|
7
|
-
post 'auth/register', to: 'auth#register'
|
|
8
7
|
post 'auth/refresh', to: 'auth#refresh'
|
|
9
8
|
post 'auth/oauth/callback', to: 'auth#oauth_callback'
|
|
10
9
|
|
|
11
|
-
#
|
|
12
|
-
|
|
10
|
+
# Customer registration
|
|
11
|
+
resources :customers, only: [:create]
|
|
13
12
|
|
|
14
13
|
# Markets
|
|
15
14
|
resources :markets, only: [:index, :show] do
|
|
@@ -30,9 +29,8 @@ Spree::Core::Engine.add_routes do
|
|
|
30
29
|
get :filters, to: 'products/filters#index'
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
|
-
resources :
|
|
34
|
-
|
|
35
|
-
resources :products, only: [:index], controller: 'taxons/products'
|
|
32
|
+
resources :categories, only: [:index, :show], id: /.+/ do
|
|
33
|
+
resources :products, only: [:index], controller: 'categories/products'
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
# Cart
|
|
@@ -53,7 +51,7 @@ Spree::Core::Engine.add_routes do
|
|
|
53
51
|
resource :store_credits, only: [:create, :destroy], controller: 'orders/store_credits'
|
|
54
52
|
resources :line_items, only: [:create, :update, :destroy], controller: 'orders/line_items'
|
|
55
53
|
resources :coupon_codes, only: [:create, :destroy], controller: 'orders/coupon_codes'
|
|
56
|
-
resources :payments, only: [:index, :show], controller: 'orders/payments'
|
|
54
|
+
resources :payments, only: [:index, :show, :create], controller: 'orders/payments'
|
|
57
55
|
resources :payment_methods, only: [:index], controller: 'orders/payment_methods'
|
|
58
56
|
resources :payment_sessions, only: [:create, :show, :update], controller: 'orders/payment_sessions' do
|
|
59
57
|
member do
|
|
@@ -63,10 +61,12 @@ Spree::Core::Engine.add_routes do
|
|
|
63
61
|
resources :shipments, only: [:index, :show, :update], controller: 'orders/shipments'
|
|
64
62
|
end
|
|
65
63
|
|
|
66
|
-
# Customer
|
|
64
|
+
# Customer (current user profile)
|
|
65
|
+
get 'customer', to: 'customers#show'
|
|
66
|
+
patch 'customer', to: 'customers#update'
|
|
67
|
+
|
|
68
|
+
# Customer nested resources
|
|
67
69
|
namespace :customer, path: 'customer' do
|
|
68
|
-
get '/', to: 'account#show'
|
|
69
|
-
patch '/', to: 'account#update'
|
|
70
70
|
resources :addresses, only: [:index, :show, :create, :update, :destroy] do
|
|
71
71
|
member do
|
|
72
72
|
patch :mark_as_default
|
|
@@ -10,9 +10,11 @@ module Spree
|
|
|
10
10
|
preference :api_v2_per_page_limit, :integer, default: 500
|
|
11
11
|
|
|
12
12
|
preference :jwt_expiration, :integer, default: 3600 # 1 hour in seconds
|
|
13
|
+
preference :jwt_secret_key, :string, default: nil
|
|
13
14
|
|
|
14
|
-
# Rate limiting
|
|
15
|
+
# Rate limiting
|
|
15
16
|
preference :rate_limit_per_key, :integer, default: 300 # per publishable API key
|
|
17
|
+
preference :rate_limit_window, :integer, default: 60 # window in seconds
|
|
16
18
|
preference :rate_limit_login, :integer, default: 5 # per IP
|
|
17
19
|
preference :rate_limit_register, :integer, default: 3 # per IP
|
|
18
20
|
preference :rate_limit_refresh, :integer, default: 10 # per IP
|
|
@@ -4,6 +4,7 @@ module Spree
|
|
|
4
4
|
module Api
|
|
5
5
|
class ApiDependencies
|
|
6
6
|
INJECTION_POINTS_WITH_DEFAULTS = {
|
|
7
|
+
# Legacy API v2 dependencies - will be removed in Spree 6
|
|
7
8
|
# cart services
|
|
8
9
|
storefront_cart_create_service: -> { Spree::Dependencies.cart_create_service },
|
|
9
10
|
storefront_cart_add_item_service: -> { Spree::Dependencies.cart_add_item_service },
|
|
@@ -66,6 +67,8 @@ module Spree
|
|
|
66
67
|
storefront_estimated_shipment_serializer: 'Spree::V2::Storefront::EstimatedShippingRateSerializer',
|
|
67
68
|
storefront_store_serializer: 'Spree::V2::Storefront::StoreSerializer',
|
|
68
69
|
storefront_policy_serializer: 'Spree::V2::Storefront::PolicySerializer',
|
|
70
|
+
storefront_post_category_serializer: 'Spree::V2::Storefront::PostCategorySerializer',
|
|
71
|
+
storefront_post_serializer: 'Spree::V2::Storefront::PostSerializer',
|
|
69
72
|
storefront_order_serializer: 'Spree::V2::Storefront::OrderSerializer',
|
|
70
73
|
storefront_variant_serializer: 'Spree::V2::Storefront::VariantSerializer',
|
|
71
74
|
storefront_image_serializer: 'Spree::V2::Storefront::ImageSerializer',
|
|
@@ -109,21 +112,21 @@ module Spree
|
|
|
109
112
|
country_serializer: 'Spree::Api::V3::CountrySerializer',
|
|
110
113
|
market_serializer: 'Spree::Api::V3::MarketSerializer',
|
|
111
114
|
state_serializer: 'Spree::Api::V3::StateSerializer',
|
|
112
|
-
store_serializer: 'Spree::Api::V3::StoreSerializer',
|
|
113
115
|
wishlist_serializer: 'Spree::Api::V3::WishlistSerializer',
|
|
114
116
|
wished_item_serializer: 'Spree::Api::V3::WishedItemSerializer',
|
|
115
117
|
payment_method_serializer: 'Spree::Api::V3::PaymentMethodSerializer',
|
|
116
118
|
shipping_method_serializer: 'Spree::Api::V3::ShippingMethodSerializer',
|
|
117
119
|
shipping_rate_serializer: 'Spree::Api::V3::ShippingRateSerializer',
|
|
118
120
|
stock_location_serializer: 'Spree::Api::V3::StockLocationSerializer',
|
|
119
|
-
|
|
120
|
-
taxon_serializer: 'Spree::Api::V3::TaxonSerializer',
|
|
121
|
+
category_serializer: 'Spree::Api::V3::CategorySerializer',
|
|
121
122
|
order_promotion_serializer: 'Spree::Api::V3::OrderPromotionSerializer',
|
|
122
123
|
digital_link_serializer: 'Spree::Api::V3::DigitalLinkSerializer',
|
|
123
124
|
gift_card_serializer: 'Spree::Api::V3::GiftCardSerializer',
|
|
124
125
|
currency_serializer: 'Spree::Api::V3::CurrencySerializer',
|
|
125
126
|
locale_serializer: 'Spree::Api::V3::LocaleSerializer',
|
|
126
127
|
metafield_serializer: 'Spree::Api::V3::MetafieldSerializer',
|
|
128
|
+
shipping_category_serializer: 'Spree::Api::V3::ShippingCategorySerializer',
|
|
129
|
+
tax_category_serializer: 'Spree::Api::V3::TaxCategorySerializer',
|
|
127
130
|
|
|
128
131
|
# v3 event serializers (for models without Store API endpoints yet)
|
|
129
132
|
asset_serializer: 'Spree::Api::V3::AssetSerializer',
|
|
@@ -152,9 +155,32 @@ module Spree
|
|
|
152
155
|
admin_variant_serializer: 'Spree::Api::V3::Admin::VariantSerializer',
|
|
153
156
|
admin_price_serializer: 'Spree::Api::V3::Admin::PriceSerializer',
|
|
154
157
|
admin_metafield_serializer: 'Spree::Api::V3::Admin::MetafieldSerializer',
|
|
155
|
-
|
|
158
|
+
admin_category_serializer: 'Spree::Api::V3::Admin::CategorySerializer',
|
|
156
159
|
admin_line_item_serializer: 'Spree::Api::V3::Admin::LineItemSerializer',
|
|
157
|
-
|
|
160
|
+
admin_option_type_serializer: 'Spree::Api::V3::Admin::OptionTypeSerializer',
|
|
161
|
+
admin_option_value_serializer: 'Spree::Api::V3::Admin::OptionValueSerializer',
|
|
162
|
+
admin_image_serializer: 'Spree::Api::V3::Admin::ImageSerializer',
|
|
163
|
+
admin_asset_serializer: 'Spree::Api::V3::Admin::AssetSerializer',
|
|
164
|
+
admin_stock_item_serializer: 'Spree::Api::V3::Admin::StockItemSerializer',
|
|
165
|
+
admin_shipment_serializer: 'Spree::Api::V3::Admin::ShipmentSerializer',
|
|
166
|
+
admin_payment_serializer: 'Spree::Api::V3::Admin::PaymentSerializer',
|
|
167
|
+
admin_refund_serializer: 'Spree::Api::V3::Admin::RefundSerializer',
|
|
168
|
+
admin_adjustment_serializer: 'Spree::Api::V3::Admin::AdjustmentSerializer',
|
|
169
|
+
admin_shipping_category_serializer: 'Spree::Api::V3::Admin::ShippingCategorySerializer',
|
|
170
|
+
admin_tax_category_serializer: 'Spree::Api::V3::Admin::TaxCategorySerializer',
|
|
171
|
+
admin_return_authorization_serializer: 'Spree::Api::V3::Admin::ReturnAuthorizationSerializer',
|
|
172
|
+
admin_reimbursement_serializer: 'Spree::Api::V3::Admin::ReimbursementSerializer',
|
|
173
|
+
admin_admin_user_serializer: 'Spree::Api::V3::Admin::AdminUserSerializer',
|
|
174
|
+
admin_address_serializer: 'Spree::Api::V3::Admin::AddressSerializer',
|
|
175
|
+
admin_shipping_method_serializer: 'Spree::Api::V3::Admin::ShippingMethodSerializer',
|
|
176
|
+
admin_stock_location_serializer: 'Spree::Api::V3::Admin::StockLocationSerializer',
|
|
177
|
+
admin_shipping_rate_serializer: 'Spree::Api::V3::Admin::ShippingRateSerializer',
|
|
178
|
+
admin_order_promotion_serializer: 'Spree::Api::V3::Admin::OrderPromotionSerializer',
|
|
179
|
+
admin_payment_method_serializer: 'Spree::Api::V3::Admin::PaymentMethodSerializer',
|
|
180
|
+
admin_credit_card_serializer: 'Spree::Api::V3::Admin::CreditCardSerializer',
|
|
181
|
+
admin_store_credit_serializer: 'Spree::Api::V3::Admin::StoreCreditSerializer',
|
|
182
|
+
admin_payment_source_serializer: 'Spree::Api::V3::Admin::PaymentSourceSerializer',
|
|
183
|
+
admin_digital_link_serializer: 'Spree::Api::V3::Admin::DigitalLinkSerializer',
|
|
158
184
|
|
|
159
185
|
# platform serializers
|
|
160
186
|
platform_metafield_serializer: 'Spree::Api::V2::Platform::MetafieldSerializer',
|
data/lib/spree/api/engine.rb
CHANGED
|
@@ -24,6 +24,21 @@ module Spree
|
|
|
24
24
|
Spree.subscribers << Spree::WebhookEventSubscriber
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# Warn in production if no dedicated JWT secret key is configured
|
|
28
|
+
config.after_initialize do
|
|
29
|
+
next unless Rails.env.production?
|
|
30
|
+
|
|
31
|
+
if Spree::Api::Config[:jwt_secret_key].blank? &&
|
|
32
|
+
Rails.application.credentials.jwt_secret_key.blank? &&
|
|
33
|
+
ENV['JWT_SECRET_KEY'].blank?
|
|
34
|
+
Rails.logger.warn(
|
|
35
|
+
'[Spree] No dedicated JWT secret key configured. Falling back to Rails.application.secret_key_base. ' \
|
|
36
|
+
'Set Spree::Api::Config[:jwt_secret_key], Rails credentials jwt_secret_key, or ENV["JWT_SECRET_KEY"] ' \
|
|
37
|
+
'for improved security.'
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
27
42
|
def self.root
|
|
28
43
|
@root ||= Pathname.new(File.expand_path('../../..', __dir__))
|
|
29
44
|
end
|