spree_api 6.0.0.beta1 → 6.0.0.beta3

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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/spree/api/v3/admin/embed_permissions.rb +55 -0
  3. data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +34 -5
  4. data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +1 -1
  5. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +11 -0
  6. data/app/controllers/concerns/spree/api/v3/current_password_confirmation.rb +8 -0
  7. data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +2 -2
  8. data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +3 -3
  9. data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +15 -2
  10. data/app/controllers/concerns/spree/api/v3/orders/post_sale_actions.rb +1 -1
  11. data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +3 -3
  12. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +14 -0
  13. data/app/controllers/concerns/spree/api/v3/store/storefront_products.rb +35 -0
  14. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +9 -0
  15. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +2 -2
  16. data/app/controllers/spree/api/v3/admin/base_controller.rb +1 -0
  17. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +8 -3
  18. data/app/controllers/spree/api/v3/admin/customers_controller.rb +0 -14
  19. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +29 -2
  20. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +4 -1
  21. data/app/controllers/spree/api/v3/admin/invitations/acceptance_links_controller.rb +41 -0
  22. data/app/controllers/spree/api/v3/admin/me_controller.rb +11 -0
  23. data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +14 -1
  24. data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +22 -1
  25. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +1 -1
  26. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +1 -1
  27. data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +22 -1
  28. data/app/controllers/spree/api/v3/admin/orders_controller.rb +41 -9
  29. data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +31 -11
  30. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +1 -19
  31. data/app/controllers/spree/api/v3/admin/prices_controller.rb +33 -2
  32. data/app/controllers/spree/api/v3/admin/products_controller.rb +1 -1
  33. data/app/controllers/spree/api/v3/admin/resource_controller.rb +1 -0
  34. data/app/controllers/spree/api/v3/admin/sellers/invitations/acceptance_links_controller.rb +37 -0
  35. data/app/controllers/spree/api/v3/admin/setup_controller.rb +9 -1
  36. data/app/controllers/spree/api/v3/admin/store_controller.rb +5 -0
  37. data/app/controllers/spree/api/v3/admin/translations/batches_controller.rb +1 -1
  38. data/app/controllers/spree/api/v3/admin/translations_controller.rb +1 -1
  39. data/app/controllers/spree/api/v3/admin/webhook_deliveries_controller.rb +12 -0
  40. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +27 -0
  41. data/app/controllers/spree/api/v3/base_controller.rb +22 -3
  42. data/app/controllers/spree/api/v3/resource_controller.rb +27 -2
  43. data/app/controllers/spree/api/v3/seller/auth_controller.rb +1 -1
  44. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +5 -2
  45. data/app/controllers/spree/api/v3/seller/invitations/acceptance_links_controller.rb +34 -0
  46. data/app/controllers/spree/api/v3/seller/me_controller.rb +25 -2
  47. data/app/controllers/spree/api/v3/seller/orders_controller.rb +20 -25
  48. data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +1 -1
  49. data/app/controllers/spree/api/v3/seller/resource_controller.rb +4 -0
  50. data/app/controllers/spree/api/v3/store/carts/items_controller.rb +7 -4
  51. data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +10 -1
  52. data/app/controllers/spree/api/v3/store/carts/payments_controller.rb +5 -1
  53. data/app/controllers/spree/api/v3/store/companies/members_controller.rb +10 -11
  54. data/app/controllers/spree/api/v3/store/companies/orders_controller.rb +6 -0
  55. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +1 -0
  56. data/app/controllers/spree/api/v3/store/products_controller.rb +6 -12
  57. data/app/controllers/spree/api/v3/store/resource_controller.rb +4 -0
  58. data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +11 -0
  59. data/app/controllers/spree/api/v3/webhooks/fulfillments_controller.rb +10 -6
  60. data/app/controllers/spree/api/v3/webhooks/payments_controller.rb +6 -2
  61. data/app/controllers/spree/api/v3/webhooks/payouts_controller.rb +6 -2
  62. data/app/jobs/spree/webhook_delivery_job.rb +18 -4
  63. data/app/serializers/spree/api/v3/admin/actor_serializer.rb +28 -0
  64. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +14 -1
  65. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +3 -4
  66. data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +3 -4
  67. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +6 -0
  68. data/app/serializers/spree/api/v3/admin/invitation_acceptance_link_serializer.rb +15 -0
  69. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +0 -11
  70. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +28 -1
  71. data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +7 -0
  72. data/app/serializers/spree/api/v3/admin/order_serializer.rb +7 -24
  73. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +6 -0
  74. data/app/serializers/spree/api/v3/admin/return_serializer.rb +2 -3
  75. data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +3 -4
  76. data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +2 -3
  77. data/app/serializers/spree/api/v3/admin/store_serializer.rb +10 -0
  78. data/app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb +6 -2
  79. data/app/serializers/spree/api/v3/base_serializer.rb +22 -0
  80. data/app/serializers/spree/api/v3/gift_card_serializer.rb +3 -1
  81. data/app/serializers/spree/api/v3/line_item_serializer.rb +2 -1
  82. data/app/serializers/spree/api/v3/market_serializer.rb +5 -0
  83. data/app/serializers/spree/api/v3/product_filters_serializer.rb +3 -0
  84. data/app/serializers/spree/api/v3/seller/account_serializer.rb +19 -0
  85. data/app/serializers/spree/api/v3/seller/invitation_acceptance_link_serializer.rb +15 -0
  86. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +1 -10
  87. data/app/services/spree/api/v3/filters_aggregator.rb +5 -2
  88. data/config/routes.rb +7 -0
  89. data/lib/spree/api/configuration.rb +19 -14
  90. data/lib/spree/api/dependencies.rb +4 -0
  91. data/lib/spree/api/engine.rb +6 -0
  92. data/lib/spree/api/openapi/schema_helper.rb +10 -4
  93. metadata +15 -6
@@ -20,7 +20,11 @@ module Spree
20
20
  cost_price: [:string, nullable: true],
21
21
  tax_category_id: [:string, nullable: true],
22
22
  price_source: [:string, nullable: true],
23
- catalog_price: [:string, nullable: true]
23
+ catalog_price: [:string, nullable: true],
24
+ price_list_id: [:string, nullable: true],
25
+ price_list_name: [:string, nullable: true],
26
+ catalog_id: [:string, nullable: true],
27
+ catalog_name: [:string, nullable: true]
24
28
 
25
29
  # price_source is operational provenance — admin-only, never on the
26
30
  # store serializer.
@@ -33,6 +37,29 @@ module Spree
33
37
  line_item.variant&.amount_in(line_item.currency)&.to_s
34
38
  end
35
39
 
40
+ # Which agreement priced this line. The list id is stamped on the
41
+ # row and never re-resolved (the same reason `catalog_price` above
42
+ # is a base price); the catalog is whichever one owns that list
43
+ # now, so moving a list between catalogs re-labels past orders.
44
+ # Empty on a shop-price or hand-negotiated line. Names ride along
45
+ # beside the ids so a page of lines does not cost a request each to
46
+ # label, as `company_name` already does.
47
+ attribute :price_list_id do |line_item|
48
+ line_item.price_list&.prefixed_id
49
+ end
50
+
51
+ attribute :price_list_name do |line_item|
52
+ line_item.price_list&.name
53
+ end
54
+
55
+ attribute :catalog_id do |line_item|
56
+ line_item.price_list&.catalog&.prefixed_id
57
+ end
58
+
59
+ attribute :catalog_name do |line_item|
60
+ line_item.price_list&.catalog&.name
61
+ end
62
+
36
63
  attribute :cost_price do |line_item|
37
64
  line_item.cost_price&.to_s
38
65
  end
@@ -13,6 +13,8 @@ module Spree
13
13
  cart_id: 'string | null',
14
14
  seller_count: :number,
15
15
  includes_first_party: :boolean,
16
+ confirmation_delivered: :boolean,
17
+ store_owner_notification_delivered: :boolean,
16
18
  created_at: :string, updated_at: :string
17
19
 
18
20
  attribute :customer_id do |group|
@@ -34,6 +36,11 @@ module Spree
34
36
  group.includes_first_party?
35
37
  end
36
38
 
39
+ # A split checkout is confirmed once, from here — every child order
40
+ # places silently, so their own flags are false and only the group
41
+ # can answer whether the customer was told.
42
+ attributes :confirmation_delivered, :store_owner_notification_delivered
43
+
37
44
  attributes :created_at, :updated_at
38
45
 
39
46
  # Re-declared against the admin serializers. Inheriting the store
@@ -49,7 +49,10 @@ module Spree
49
49
  store_owner_notification_delivered: :boolean,
50
50
  internal_note: [:string, nullable: true], internal_note_html: [:string, nullable: true],
51
51
  approver_id: [:string, nullable: true],
52
+ approver_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
52
53
  canceler_id: [:string, nullable: true], created_by_id: [:string, nullable: true],
54
+ canceler_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
55
+ created_by_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
53
56
  customer_id: [:string, nullable: true],
54
57
  preferred_stock_location_id: [:string, nullable: true],
55
58
  canceled_at: [:string, nullable: true], approved_at: [:string, nullable: true],
@@ -128,13 +131,10 @@ module Spree
128
131
  order.internal_note.presence
129
132
  end
130
133
 
131
- attribute :approver_id do |order|
132
- order.approver&.prefixed_id
133
- end
134
-
135
- attribute :canceler_id do |order|
136
- order.canceler&.prefixed_id
137
- end
134
+ # Who approved, cancelled and opened it — a member of staff, or the
135
+ # API key an integration called with. An order cancelled through a
136
+ # secret key names the key.
137
+ actor_attributes :approver, :canceler, :created_by
138
138
 
139
139
  attribute :cancel_reason_id do |order|
140
140
  order.cancel_reason&.prefixed_id
@@ -147,10 +147,6 @@ module Spree
147
147
  order.cancel_reason&.name
148
148
  end
149
149
 
150
- attribute :created_by_id do |order|
151
- order.created_by&.prefixed_id
152
- end
153
-
154
150
  attribute :customer_id do |order|
155
151
  order.customer&.prefixed_id
156
152
  end
@@ -189,23 +185,10 @@ module Spree
189
185
  resource: proc { Spree.api.admin_customer_serializer },
190
186
  if: proc { expand?('customer') }
191
187
 
192
- # Staff actors, not customers — these point at Spree.admin_user_class.
193
- one :approver,
194
- resource: proc { Spree.api.admin_admin_user_serializer },
195
- if: proc { expand?('approver') }
196
-
197
- one :canceler,
198
- resource: proc { Spree.api.admin_admin_user_serializer },
199
- if: proc { expand?('canceler') }
200
-
201
188
  one :cancel_reason,
202
189
  resource: proc { Spree.api.admin_order_cancellation_reason_serializer },
203
190
  if: proc { expand?('cancel_reason') }
204
191
 
205
- one :created_by,
206
- resource: proc { Spree.api.admin_admin_user_serializer },
207
- if: proc { expand?('created_by') }
208
-
209
192
 
210
193
  many :returns,
211
194
  resource: proc { Spree.api.admin_return_serializer },
@@ -5,11 +5,17 @@ module Spree
5
5
  class RefundSerializer < V3::RefundSerializer
6
6
  typelize payment_id: [:string, nullable: true],
7
7
  refund_reason_id: [:string, nullable: true],
8
+ refunder_id: [:string, nullable: true],
9
+ refunder_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
8
10
  metadata: 'Record<string, unknown>'
9
11
 
10
12
  attributes :metadata,
11
13
  created_at: :iso8601, updated_at: :iso8601
12
14
 
15
+ # Who issued it — an admin user, or the API key an integration
16
+ # refunded through.
17
+ actor_attributes :refunder
18
+
13
19
  one :payment,
14
20
  resource: proc { Spree.api.admin_payment_serializer },
15
21
  if: proc { expand?('payment') }
@@ -10,6 +10,7 @@ module Spree
10
10
  documents: "Array<{ kind: string; url: string }>",
11
11
  stock_location_id: [:string, nullable: true],
12
12
  created_by_id: [:string, nullable: true],
13
+ created_by_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
13
14
  refunded_total: :string,
14
15
  refundable_total: :string
15
16
 
@@ -19,9 +20,7 @@ module Spree
19
20
  return_record.stock_location&.prefixed_id
20
21
  end
21
22
 
22
- attribute :created_by_id do |return_record|
23
- return_record.created_by&.prefixed_id
24
- end
23
+ actor_attributes :created_by
25
24
 
26
25
  attribute :refunded_total do |return_record|
27
26
  return_record.refunded_total.to_s
@@ -20,11 +20,10 @@ module Spree
20
20
  report.user&.prefixed_id
21
21
  end
22
22
 
23
+ # The same "name, else email" rule every actor answers, so a report's
24
+ # author and an order's canceler read alike.
23
25
  attribute :author_name do |report|
24
- user = report.user
25
- next nil unless user
26
-
27
- user.full_name.presence || user.email
26
+ report.user&.actor_label
28
27
  end
29
28
  end
30
29
  end
@@ -12,6 +12,7 @@ module Spree
12
12
  receivable_type: [:string, enum: %w[purchase_order stock_transfer]],
13
13
  receivable_id: :string,
14
14
  received_by_id: 'string | null',
15
+ received_by_type: [:string, nullable: true, enum: Spree::Actor::BUILT_IN_KINDS, enum_type_name: 'ActorKind'],
15
16
  items_count: :number,
16
17
  quantity_accepted_total: :number,
17
18
  quantity_rejected_total: :number,
@@ -31,9 +32,7 @@ module Spree
31
32
  receipt.receivable&.prefixed_id
32
33
  end
33
34
 
34
- attribute :received_by_id do |receipt|
35
- receipt.received_by.try(:prefixed_id)
36
- end
35
+ actor_attributes :received_by
37
36
 
38
37
  attribute :items_count do |receipt|
39
38
  receipt.items.size
@@ -22,6 +22,7 @@ module Spree
22
22
  preferred_unit_system: :string,
23
23
  preferred_storefront_access: :string,
24
24
  preferred_guest_checkout: :boolean,
25
+ preferred_always_include_confirm_step: :boolean,
25
26
  preferred_company_field_enabled: :boolean,
26
27
  preferred_address_requires_company: :boolean,
27
28
  preferred_address_requires_phone: :boolean,
@@ -41,6 +42,10 @@ module Spree
41
42
  preferred_payout_provider: 'string | null',
42
43
  preferred_default_payouts_schedule_interval: :string,
43
44
  preferred_default_minimum_payout_amount: :number,
45
+ preferred_auto_approve_sellers: :boolean,
46
+ preferred_auto_approve_seller_products: :boolean,
47
+ preferred_send_seller_transactional_emails: :boolean,
48
+ preferred_default_commission_tax_rate: :number,
44
49
  preferred_document_number_format: :string,
45
50
  preferred_order_number_prefix: :string,
46
51
  preferred_order_number_suffix: :string,
@@ -69,6 +74,7 @@ module Spree
69
74
  :preferred_unit_system,
70
75
  :preferred_storefront_access,
71
76
  :preferred_guest_checkout,
77
+ :preferred_always_include_confirm_step,
72
78
  :preferred_company_field_enabled,
73
79
  :preferred_address_requires_company,
74
80
  :preferred_address_requires_phone,
@@ -88,6 +94,10 @@ module Spree
88
94
  :preferred_payout_provider,
89
95
  :preferred_default_payouts_schedule_interval,
90
96
  :preferred_default_minimum_payout_amount,
97
+ :preferred_auto_approve_sellers,
98
+ :preferred_auto_approve_seller_products,
99
+ :preferred_send_seller_transactional_emails,
100
+ :preferred_default_commission_tax_rate,
91
101
  :preferred_document_number_format,
92
102
  :preferred_order_number_prefix,
93
103
  :preferred_order_number_suffix,
@@ -19,7 +19,7 @@ module Spree
19
19
  response_body: [:string, nullable: true],
20
20
  success: [:boolean, nullable: true],
21
21
  delivered_at: [:string, nullable: true],
22
- payload: 'Record<string, unknown>',
22
+ payload: ['Record<string, unknown>', nullable: true],
23
23
  webhook_endpoint_id: :string,
24
24
  webhook_endpoint_url: :string
25
25
 
@@ -29,8 +29,12 @@ module Spree
29
29
  delivered_at: :iso8601
30
30
 
31
31
  # Redacted again on read: deliveries written before payload redaction
32
- # shipped still hold live credentials in the column.
32
+ # shipped still hold live credentials in the column. Null when the
33
+ # caller cannot read the record the event is about.
33
34
  attribute :payload do |delivery|
35
+ visible = params[:payload_visible]
36
+ next nil if visible && !visible.call(delivery)
37
+
34
38
  Spree::WebhookPayloadRedaction.split(delivery.payload).first
35
39
  end
36
40
 
@@ -27,6 +27,28 @@ module Spree
27
27
  end
28
28
  end
29
29
 
30
+ # Declares the wire form of an `acted_by` association: the actor's
31
+ # prefixed id, the kind of actor it is, and the expansion. Both
32
+ # halves read off the columns, so naming an actor costs no query and
33
+ # the id and the kind always describe the same row (see
34
+ # docs/plans/6.0-action-actors.md).
35
+ #
36
+ # Declare the matching `typelize` entries alongside, as with any
37
+ # other attribute.
38
+ def self.actor_attributes(*names)
39
+ names.each do |name|
40
+ attribute(:"#{name}_id") { |object| object.acted_by_prefixed_id(name) }
41
+
42
+ attribute(:"#{name}_type") do |object|
43
+ Spree::Base.polymorphic_api_type(object.acted_by_type(name))
44
+ end
45
+
46
+ one name,
47
+ resource: proc { Spree.api.admin_actor_serializer },
48
+ if: proc { expand?(name.to_s) }
49
+ end
50
+ end
51
+
30
52
  # Plain decimal notation. BigDecimal renders 0.06 as "0.6e-1", which
31
53
  # is what a client would otherwise print beside a unit.
32
54
  #
@@ -17,8 +17,10 @@ module Spree
17
17
  expired: :boolean,
18
18
  active: :boolean
19
19
 
20
+ # A bearer credential: masked when the order is shown to someone other
21
+ # than its buyer (a company's other members).
20
22
  attribute :code do |gift_card|
21
- gift_card.display_code
23
+ params[:hide_credentials] ? gift_card.masked_code : gift_card.display_code
22
24
  end
23
25
 
24
26
  attribute :status do |gift_card|
@@ -71,7 +71,8 @@ module Spree
71
71
  if: proc { expand?('seller') }
72
72
 
73
73
  many :option_values, resource: proc { Spree.api.option_value_serializer }
74
- many :digital_links, resource: proc { Spree.api.digital_link_serializer }
74
+ # Download links carry a bearer token; only the buyer gets them.
75
+ many :digital_links, resource: proc { Spree.api.digital_link_serializer }, if: proc { !params[:hide_credentials] }
75
76
  # Tax hangs off its adjustable, never off the cart or order: the
76
77
  # exactly-one-adjustable rule makes the nested view complete, and the
77
78
  # owner already carries the tax totals.
@@ -6,11 +6,16 @@ module Spree
6
6
  default_locale: :string,
7
7
  supported_locales: [:string, multi: true],
8
8
  country_codes: [:string, multi: true],
9
+ country_isos: [:string, multi: true],
9
10
  tax_inclusive: :boolean,
10
11
  default: :boolean
11
12
 
12
13
  attributes :name, :currency, :default_locale, :tax_inclusive, :default, :country_codes
13
14
 
15
+ # @deprecated Storefronts shipped against this name; use +country_codes+.
16
+ # Removed in 6.1.
17
+ attribute :country_isos, &:country_codes
18
+
14
19
  attribute :supported_locales do |market|
15
20
  market.supported_locales_list
16
21
  end
@@ -12,6 +12,9 @@ module Spree
12
12
  attribute :filters do |result|
13
13
  result.filters.filter_map do |filter|
14
14
  filter_type = filter[:type]
15
+ # A price range is prices; a gated guest sees none.
16
+ next if filter_type == 'price_range' && params[:hide_prices]
17
+
15
18
  serializer_class = case filter_type
16
19
  when 'price_range'
17
20
  Spree.api.product_filter_price_range_serializer
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # The signed-in person's own account, as `/me` answers it.
6
+ #
7
+ # Extends the team member shape rather than widening it: `selected_locale`
8
+ # is a preference its owner sets, and the team list serializes colleagues
9
+ # with the parent — where publishing each member's chosen language would
10
+ # tell the whole team something none of them asked to share.
11
+ class AccountSerializer < Seller::TeamMemberSerializer
12
+ typelize selected_locale: [:string, nullable: true]
13
+
14
+ attributes :selected_locale
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # The acceptance link of one seller-team invitation, served on its own
6
+ # so the token never travels with the invitation listing.
7
+ class InvitationAcceptanceLinkSerializer < V3::BaseSerializer
8
+ typelize acceptance_url: :string
9
+
10
+ attributes :acceptance_url
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -5,8 +5,7 @@ module Spree
5
5
  class InvitationSerializer < V3::BaseSerializer
6
6
  typelize email: :string, status: [:string, enum: Spree::Invitation.statuses, enum_type_name: 'InvitationStatus'],
7
7
  expires_at: [:string, nullable: true],
8
- accepted_at: [:string, nullable: true],
9
- acceptance_url: :string
8
+ accepted_at: [:string, nullable: true]
10
9
 
11
10
  attributes :email,
12
11
  created_at: :iso8601, expires_at: :iso8601, accepted_at: :iso8601
@@ -14,14 +13,6 @@ module Spree
14
13
  attribute :status do |invitation|
15
14
  invitation.status.to_s
16
15
  end
17
-
18
- attribute :acceptance_url do |invitation|
19
- if Spree::Config[:seller_panel_url].present? || Spree::Config[:dashboard_url].present?
20
- Rails.application.routes.url_helpers.admin_invitation_acceptance_url(invitation)
21
- else
22
- "/accept-invitation/#{invitation.prefixed_id}?token=#{invitation.token}"
23
- end
24
- end
25
16
  end
26
17
  end
27
18
  end
@@ -51,8 +51,11 @@ module Spree
51
51
 
52
52
 
53
53
  def price_filter
54
- # Remove ordering to avoid PostgreSQL DISTINCT + ORDER BY conflicts
55
- prices = Spree::Price.for_products(@scope.reorder(''), @currency)
54
+ # Remove ordering to avoid PostgreSQL DISTINCT + ORDER BY conflicts.
55
+ # Base prices only: a price list's rows are for its own audience
56
+ # (a company's contract, a draft or scheduled list), and the range is
57
+ # shown to everyone.
58
+ prices = Spree::Price.base_prices.for_products(@scope.reorder(''), @currency)
56
59
  min = prices.minimum(:amount)
57
60
  max = prices.maximum(:amount)
58
61
  return nil if min.nil? || max.nil?
data/config/routes.rb CHANGED
@@ -273,6 +273,7 @@ Spree::Core::Engine.add_routes do
273
273
  member do
274
274
  patch :resend
275
275
  end
276
+ resource :acceptance_link, only: [:show], controller: 'invitations/acceptance_links'
276
277
  end
277
278
  resources :api_keys, only: [:index, :show, :create, :update, :destroy] do
278
279
  collection do
@@ -590,6 +591,7 @@ Spree::Core::Engine.add_routes do
590
591
  member do
591
592
  patch :resend
592
593
  end
594
+ resource :acceptance_link, only: [:show], controller: 'sellers/invitations/acceptance_links'
593
595
  end
594
596
 
595
597
  # What this seller submitted about the requirements, and the
@@ -875,6 +877,10 @@ Spree::Core::Engine.add_routes do
875
877
  patch 'auth/password_resets/:id', to: 'password_resets#update'
876
878
 
877
879
  get 'me', to: 'me#show'
880
+ # Self-service edits to the signed-in person's own account — their
881
+ # name, photo and panel language. Distinct from `profile`, which is
882
+ # the seller business they act for.
883
+ patch 'me', to: 'me#update'
878
884
 
879
885
  # Singular: the seller in play is always `current_seller`.
880
886
  resource :profile, only: [:show, :update], controller: 'profile'
@@ -896,6 +902,7 @@ Spree::Core::Engine.add_routes do
896
902
  member do
897
903
  patch :resend
898
904
  end
905
+ resource :acceptance_link, only: [:show], controller: 'invitations/acceptance_links'
899
906
  end
900
907
 
901
908
  resources :products, only: [:index, :show, :create, :update, :destroy] do
@@ -3,25 +3,30 @@ require 'spree/core/preferences/runtime_configuration'
3
3
  module Spree
4
4
  module Api
5
5
  class Configuration < Spree::Preferences::RuntimeConfiguration
6
- preference :jwt_expiration, :integer, default: 3600 # 1 hour in seconds (customer/store JWT default)
7
- preference :admin_jwt_expiration, :integer, default: 300 # 5 minutes — admin tokens have higher blast radius
8
- preference :jwt_secret_key, :string, default: nil
9
- preference :refresh_token_expiry, :integer, default: 2_592_000 # 30 days in seconds
6
+ preference :jwt_expiration, :integer, default: 3600, env: 'SPREE_JWT_EXPIRATION' # 1 hour in seconds (customer/store JWT default)
7
+ preference :admin_jwt_expiration, :integer, default: 300, env: 'SPREE_ADMIN_JWT_EXPIRATION' # 5 minutes — admin tokens have higher blast radius
8
+ # SPREE_JWT_SECRET_KEY resolves inside the preference, so it sits ahead of
9
+ # the Rails credentials fallback in Spree::Api::V3::JwtAuthentication —
10
+ # an operator who sets it means it. The older, unprefixed JWT_SECRET_KEY
11
+ # keeps its place behind credentials so existing deployments are
12
+ # unaffected.
13
+ preference :jwt_secret_key, :string, default: nil, env: 'SPREE_JWT_SECRET_KEY'
14
+ preference :refresh_token_expiry, :integer, default: 2_592_000, env: 'SPREE_REFRESH_TOKEN_EXPIRY' # 30 days in seconds
10
15
 
11
16
  # Rate limiting
12
- preference :rate_limit_per_key, :integer, default: 300 # per publishable API key + client IP (per visitor)
13
- preference :rate_limit_per_secret_key, :integer, default: 600 # per secret API key, across the whole API
14
- preference :rate_limit_window, :integer, default: 60 # window in seconds
15
- preference :rate_limit_login, :integer, default: 5 # per IP
16
- preference :rate_limit_register, :integer, default: 3 # per IP
17
- preference :rate_limit_refresh, :integer, default: 10 # per IP
18
- preference :rate_limit_password_reset, :integer, default: 3 # per IP
17
+ preference :rate_limit_per_key, :integer, default: 300, env: 'SPREE_RATE_LIMIT_PER_KEY' # per publishable API key + client IP (per visitor)
18
+ preference :rate_limit_per_secret_key, :integer, default: 600, env: 'SPREE_RATE_LIMIT_PER_SECRET_KEY' # per secret API key, across the whole API
19
+ preference :rate_limit_window, :integer, default: 60, env: 'SPREE_RATE_LIMIT_WINDOW' # window in seconds
20
+ preference :rate_limit_login, :integer, default: 5, env: 'SPREE_RATE_LIMIT_LOGIN' # per IP
21
+ preference :rate_limit_register, :integer, default: 3, env: 'SPREE_RATE_LIMIT_REGISTER' # per IP
22
+ preference :rate_limit_refresh, :integer, default: 10, env: 'SPREE_RATE_LIMIT_REFRESH' # per IP
23
+ preference :rate_limit_password_reset, :integer, default: 3, env: 'SPREE_RATE_LIMIT_PASSWORD_RESET' # per IP
19
24
 
20
25
  # Request body size limit in bytes
21
- preference :max_request_body_size, :integer, default: 102_400 # 100KB
26
+ preference :max_request_body_size, :integer, default: 102_400, env: 'SPREE_MAX_REQUEST_BODY_SIZE' # 100KB
22
27
 
23
- preference :webhooks_enabled, :boolean, default: true
24
- preference :webhooks_verify_ssl, :boolean, default: !Rails.env.development?
28
+ preference :webhooks_enabled, :boolean, default: true, env: 'SPREE_WEBHOOKS_ENABLED'
29
+ preference :webhooks_verify_ssl, :boolean, default: !Rails.env.development?, env: 'SPREE_WEBHOOKS_VERIFY_SSL'
25
30
  end
26
31
  end
27
32
  end
@@ -181,12 +181,15 @@ module Spree
181
181
  admin_catalog_order_minimum_serializer: 'Spree::Api::V3::Admin::CatalogOrderMinimumSerializer',
182
182
  admin_tax_exemption_certificate_serializer: 'Spree::Api::V3::Admin::TaxExemptionCertificateSerializer',
183
183
  admin_admin_user_serializer: 'Spree::Api::V3::Admin::AdminUserSerializer',
184
+ admin_actor_serializer: 'Spree::Api::V3::Admin::ActorSerializer',
184
185
  admin_seller_team_member_serializer: 'Spree::Api::V3::Admin::SellerTeamMemberSerializer',
185
186
  seller_serializer: 'Spree::Api::V3::SellerSerializer',
186
187
  seller_profile_serializer: 'Spree::Api::V3::Seller::ProfileSerializer',
187
188
  seller_policy_serializer: 'Spree::Api::V3::Seller::PolicySerializer',
188
189
  seller_team_member_serializer: 'Spree::Api::V3::Seller::TeamMemberSerializer',
190
+ seller_account_serializer: 'Spree::Api::V3::Seller::AccountSerializer',
189
191
  seller_invitation_serializer: 'Spree::Api::V3::Seller::InvitationSerializer',
192
+ seller_invitation_acceptance_link_serializer: 'Spree::Api::V3::Seller::InvitationAcceptanceLinkSerializer',
190
193
  seller_product_serializer: 'Spree::Api::V3::Seller::ProductSerializer',
191
194
  seller_product_type_serializer: 'Spree::Api::V3::Seller::ProductTypeSerializer',
192
195
  seller_delivery_profile_serializer: 'Spree::Api::V3::Seller::DeliveryProfileSerializer',
@@ -266,6 +269,7 @@ module Spree
266
269
  admin_webhook_endpoint_serializer: 'Spree::Api::V3::Admin::WebhookEndpointSerializer',
267
270
  admin_webhook_delivery_serializer: 'Spree::Api::V3::Admin::WebhookDeliverySerializer',
268
271
  admin_invitation_serializer: 'Spree::Api::V3::Admin::InvitationSerializer',
272
+ admin_invitation_acceptance_link_serializer: 'Spree::Api::V3::Admin::InvitationAcceptanceLinkSerializer',
269
273
  admin_role_serializer: 'Spree::Api::V3::Admin::RoleSerializer',
270
274
  admin_permission_serializer: 'Spree::Api::V3::Admin::PermissionSerializer',
271
275
  admin_export_serializer: 'Spree::Api::V3::Admin::ExportSerializer',
@@ -24,6 +24,12 @@ module Spree
24
24
  Spree.subscribers << Spree::WebhookEventSubscriber
25
25
  end
26
26
 
27
+ # Runs after initializers so an explicitly assigned preference — which
28
+ # wins over the environment — is never rejected for a stale env var.
29
+ config.after_initialize do
30
+ Spree::Api::Configuration.validate_env!(Spree::Api::Config)
31
+ end
32
+
27
33
  # Warn in production if no dedicated JWT secret key is configured
28
34
  config.after_initialize do
29
35
  next unless Rails.env.production?
@@ -250,8 +250,8 @@ module Spree
250
250
  #
251
251
  # The seller branch has no API-key credential, so its AuthResponse is
252
252
  # neither the store's nor the admin's: signing in returns the JWT, the
253
- # team member who signed in, and the sellers they may act for — the
254
- # panel cannot make another request until it has picked one.
253
+ # person who signed in, and the sellers they may act for — the panel
254
+ # cannot make another request until it has picked one.
255
255
  def seller_schemas
256
256
  schemas = common_schemas
257
257
 
@@ -259,7 +259,10 @@ module Spree
259
259
  type: :object,
260
260
  properties: {
261
261
  token: { type: :string, description: 'JWT access token, `seller_api` audience' },
262
- user: { '$ref' => '#/components/schemas/TeamMember' },
262
+ # `Account`, not `TeamMember`: the panel adopts the signed-in
263
+ # person's saved language from this payload, which is what
264
+ # carries the choice to a second browser.
265
+ user: { '$ref' => '#/components/schemas/Account' },
263
266
  sellers: {
264
267
  type: :array,
265
268
  description: 'The sellers this user may act for. Pick one and send its `id` as `X-Spree-Seller-Id` on every subsequent request.',
@@ -309,7 +312,10 @@ module Spree
309
312
  type: :object,
310
313
  description: 'The signed-in user, the sellers they may act for, and what they may do on the selected one',
311
314
  properties: {
312
- user: { '$ref' => '#/components/schemas/TeamMember' },
315
+ # `Account`, not `TeamMember`: the person reading their own
316
+ # record also sees the panel language they chose, which the
317
+ # team list does not publish about a colleague.
318
+ user: { '$ref' => '#/components/schemas/Account' },
313
319
  sellers: { type: :array, items: { '$ref' => '#/components/schemas/SellerMeSummary' } },
314
320
  permissions: { type: :array, items: { '$ref' => '#/components/schemas/PermissionRule' } },
315
321
  permission_keys: {