spree_api 5.6.1 → 6.0.0.beta1

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 (540) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +28 -0
  3. data/Rakefile +1 -1
  4. data/app/controllers/concerns/spree/api/v3/address_params.rb +17 -0
  5. data/app/controllers/concerns/spree/api/v3/admin/product_listing.rb +46 -0
  6. data/app/controllers/concerns/spree/api/v3/admin/product_membership.rb +110 -0
  7. data/app/controllers/concerns/spree/api/v3/admin/receivable_actions.rb +68 -0
  8. data/app/controllers/concerns/spree/api/v3/admin/reporting_authorization.rb +27 -0
  9. data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +69 -33
  10. data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +86 -0
  11. data/app/controllers/concerns/spree/api/v3/admin/store_context.rb +97 -0
  12. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +12 -6
  13. data/app/controllers/concerns/spree/api/v3/admin/validation_details.rb +91 -0
  14. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +9 -5
  15. data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +41 -5
  16. data/app/controllers/concerns/spree/api/v3/authentication_strategies.rb +48 -0
  17. data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +4 -6
  18. data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +52 -16
  19. data/app/controllers/concerns/spree/api/v3/company_address_writes.rb +37 -0
  20. data/app/controllers/concerns/spree/api/v3/current_password_confirmation.rb +41 -0
  21. data/app/controllers/concerns/spree/api/v3/direct_uploads.rb +35 -0
  22. data/app/controllers/concerns/spree/api/v3/error_handler.rb +53 -11
  23. data/app/controllers/concerns/spree/api/v3/idempotent.rb +10 -4
  24. data/app/controllers/concerns/spree/api/v3/items_payload.rb +54 -0
  25. data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +23 -3
  26. data/app/controllers/concerns/spree/api/v3/key_store_context.rb +31 -0
  27. data/app/controllers/concerns/spree/api/v3/locale_and_currency.rb +3 -3
  28. data/app/controllers/concerns/spree/api/v3/order_lock.rb +22 -3
  29. data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +112 -0
  30. data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +105 -0
  31. data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +117 -0
  32. data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +157 -0
  33. data/app/controllers/concerns/spree/api/v3/orders/post_sale_actions.rb +76 -0
  34. data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +116 -0
  35. data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +128 -0
  36. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +7 -4
  37. data/app/controllers/concerns/spree/api/v3/permission_serialization.rb +42 -0
  38. data/app/controllers/concerns/spree/api/v3/rate_limit_headers.rb +40 -6
  39. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +80 -26
  40. data/app/controllers/concerns/spree/api/v3/seller/auth_cookies.rb +62 -0
  41. data/app/controllers/concerns/spree/api/v3/seller/seller_context.rb +127 -0
  42. data/app/controllers/concerns/spree/api/v3/seller_authentication.rb +40 -0
  43. data/app/controllers/concerns/spree/api/v3/storefront_access.rb +38 -0
  44. data/app/controllers/concerns/spree/api/v3/streams_shipping_label.rb +37 -0
  45. data/app/controllers/concerns/spree/api/v3/tax_identifier_validation.rb +41 -0
  46. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +11 -14
  47. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +1 -1
  48. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +16 -7
  49. data/app/controllers/spree/api/v3/admin/auth_controller.rb +138 -22
  50. data/app/controllers/spree/api/v3/admin/base_controller.rb +2 -0
  51. data/app/controllers/spree/api/v3/admin/catalog_assignments_controller.rb +27 -0
  52. data/app/controllers/spree/api/v3/admin/catalogs/base_controller.rb +29 -0
  53. data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +40 -0
  54. data/app/controllers/spree/api/v3/admin/catalogs/products_controller.rb +107 -0
  55. data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +75 -0
  56. data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +191 -0
  57. data/app/controllers/spree/api/v3/admin/categories/products_controller.rb +28 -41
  58. data/app/controllers/spree/api/v3/admin/categories_controller.rb +16 -7
  59. data/app/controllers/spree/api/v3/admin/channels_controller.rb +50 -2
  60. data/app/controllers/spree/api/v3/admin/claim_reasons_controller.rb +25 -0
  61. data/app/controllers/spree/api/v3/admin/claims_controller.rb +31 -0
  62. data/app/controllers/spree/api/v3/admin/collection_rules_controller.rb +40 -0
  63. data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +101 -0
  64. data/app/controllers/spree/api/v3/admin/collections_controller.rb +56 -0
  65. data/app/controllers/spree/api/v3/admin/commission_lines_controller.rb +39 -0
  66. data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +174 -0
  67. data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +65 -0
  68. data/app/controllers/spree/api/v3/admin/companies/base_controller.rb +29 -0
  69. data/app/controllers/spree/api/v3/admin/companies/invitations_controller.rb +56 -0
  70. data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +66 -0
  71. data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +137 -0
  72. data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +46 -0
  73. data/app/controllers/spree/api/v3/admin/companies_controller.rb +59 -0
  74. data/app/controllers/spree/api/v3/admin/concerns/external_references.rb +166 -0
  75. data/app/controllers/spree/api/v3/admin/consent_records_controller.rb +31 -0
  76. data/app/controllers/spree/api/v3/admin/countries_controller.rb +12 -4
  77. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +19 -4
  78. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +5 -5
  79. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +1 -1
  80. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +4 -4
  81. data/app/controllers/spree/api/v3/admin/customers/base_controller.rb +1 -1
  82. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +2 -3
  83. data/app/controllers/spree/api/v3/admin/customers/tax_identifiers_controller.rb +43 -0
  84. data/app/controllers/spree/api/v3/admin/customers_controller.rb +190 -11
  85. data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +24 -20
  86. data/app/controllers/spree/api/v3/admin/data_requests_controller.rb +60 -0
  87. data/app/controllers/spree/api/v3/admin/delivery_method_rules_controller.rb +54 -0
  88. data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +114 -0
  89. data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +243 -0
  90. data/app/controllers/spree/api/v3/admin/delivery_profiles/origin_groups_controller.rb +80 -0
  91. data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +107 -0
  92. data/app/controllers/spree/api/v3/admin/delivery_zones_controller.rb +116 -0
  93. data/app/controllers/spree/api/v3/admin/digital_links_controller.rb +48 -0
  94. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +17 -3
  95. data/app/controllers/spree/api/v3/admin/exchanges_controller.rb +31 -0
  96. data/app/controllers/spree/api/v3/admin/exports_controller.rb +2 -2
  97. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +1 -1
  98. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +3 -2
  99. data/app/controllers/spree/api/v3/admin/imports_controller.rb +71 -8
  100. data/app/controllers/spree/api/v3/admin/integrations_controller.rb +67 -0
  101. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +5 -5
  102. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +5 -1
  103. data/app/controllers/spree/api/v3/admin/locales_controller.rb +3 -1
  104. data/app/controllers/spree/api/v3/admin/markets_controller.rb +9 -5
  105. data/app/controllers/spree/api/v3/admin/me_controller.rb +4 -30
  106. data/app/controllers/spree/api/v3/admin/media_controller.rb +88 -38
  107. data/app/controllers/spree/api/v3/admin/media_library_controller.rb +156 -0
  108. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +1 -0
  109. data/app/controllers/spree/api/v3/admin/order_cancellation_reasons_controller.rb +25 -0
  110. data/app/controllers/spree/api/v3/admin/order_groups_controller.rb +43 -0
  111. data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +1 -1
  112. data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +56 -0
  113. data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +66 -0
  114. data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +86 -0
  115. data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +99 -0
  116. data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +62 -0
  117. data/app/controllers/spree/api/v3/admin/orders/fees_controller.rb +83 -0
  118. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +45 -67
  119. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +40 -22
  120. data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +75 -0
  121. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +36 -18
  122. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +39 -18
  123. data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +70 -0
  124. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +2 -2
  125. data/app/controllers/spree/api/v3/admin/orders/tax_identifiers_controller.rb +41 -0
  126. data/app/controllers/spree/api/v3/admin/orders/tax_lines_controller.rb +32 -0
  127. data/app/controllers/spree/api/v3/admin/orders_controller.rb +157 -32
  128. data/app/controllers/spree/api/v3/admin/package_types_controller.rb +39 -0
  129. data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +1 -1
  130. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +15 -4
  131. data/app/controllers/spree/api/v3/admin/payout_providers_controller.rb +27 -0
  132. data/app/controllers/spree/api/v3/admin/permissions_controller.rb +30 -0
  133. data/app/controllers/spree/api/v3/admin/policies_controller.rb +42 -0
  134. data/app/controllers/spree/api/v3/admin/price_lists/products_controller.rb +93 -0
  135. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +43 -29
  136. data/app/controllers/spree/api/v3/admin/prices_controller.rb +41 -4
  137. data/app/controllers/spree/api/v3/admin/product_types_controller.rb +93 -0
  138. data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +148 -0
  139. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +24 -3
  140. data/app/controllers/spree/api/v3/admin/products_controller.rb +149 -33
  141. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +6 -2
  142. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +1 -1
  143. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +1 -5
  144. data/app/controllers/spree/api/v3/admin/purchase_orders/stock_receipts_controller.rb +32 -0
  145. data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +161 -0
  146. data/app/controllers/spree/api/v3/admin/refund_reasons_controller.rb +25 -0
  147. data/app/controllers/spree/api/v3/admin/reporting/saved_reports_controller.rb +45 -0
  148. data/app/controllers/spree/api/v3/admin/reporting_controller.rb +95 -0
  149. data/app/controllers/spree/api/v3/admin/resource_controller.rb +27 -10
  150. data/app/controllers/spree/api/v3/admin/return_reasons_controller.rb +25 -0
  151. data/app/controllers/spree/api/v3/admin/returns_controller.rb +31 -0
  152. data/app/controllers/spree/api/v3/admin/roles_controller.rb +50 -6
  153. data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +83 -0
  154. data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +139 -0
  155. data/app/controllers/spree/api/v3/admin/seller_requirements_controller.rb +115 -0
  156. data/app/controllers/spree/api/v3/admin/seller_transfers_controller.rb +36 -0
  157. data/app/controllers/spree/api/v3/admin/sellers/balances_controller.rb +44 -0
  158. data/app/controllers/spree/api/v3/admin/sellers/invitations_controller.rb +77 -0
  159. data/app/controllers/spree/api/v3/admin/sellers/payouts_controller.rb +107 -0
  160. data/app/controllers/spree/api/v3/admin/sellers/team_controller.rb +64 -0
  161. data/app/controllers/spree/api/v3/admin/sellers_controller.rb +197 -0
  162. data/app/controllers/spree/api/v3/admin/setup_controller.rb +231 -0
  163. data/app/controllers/spree/api/v3/admin/stock_levels_controller.rb +172 -0
  164. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +3 -2
  165. data/app/controllers/spree/api/v3/admin/stock_movements_controller.rb +37 -0
  166. data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +1 -1
  167. data/app/controllers/spree/api/v3/admin/stock_transfers/stock_receipts_controller.rb +31 -0
  168. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +134 -38
  169. data/app/controllers/spree/api/v3/admin/store_controller.rb +65 -0
  170. data/app/controllers/spree/api/v3/admin/store_credits/events_controller.rb +47 -0
  171. data/app/controllers/spree/api/v3/admin/store_credits_controller.rb +87 -0
  172. data/app/controllers/spree/api/v3/admin/suppliers_controller.rb +30 -0
  173. data/app/controllers/spree/api/v3/admin/tags_controller.rb +2 -2
  174. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +4 -0
  175. data/app/controllers/spree/api/v3/admin/tax_providers_controller.rb +25 -0
  176. data/app/controllers/spree/api/v3/admin/tax_rates_controller.rb +33 -0
  177. data/app/controllers/spree/api/v3/admin/tracking_carriers_controller.rb +33 -0
  178. data/app/controllers/spree/api/v3/admin/translatable_resources_controller.rb +37 -9
  179. data/app/controllers/spree/api/v3/admin/translations_controller.rb +10 -5
  180. data/app/controllers/spree/api/v3/admin/translations_coverage_controller.rb +150 -0
  181. data/app/controllers/spree/api/v3/admin/variants_controller.rb +11 -4
  182. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +1 -1
  183. data/app/controllers/spree/api/v3/base_controller.rb +59 -16
  184. data/app/controllers/spree/api/v3/resource_controller.rb +154 -38
  185. data/app/controllers/spree/api/v3/seller/auth_controller.rb +169 -0
  186. data/app/controllers/spree/api/v3/seller/balances_controller.rb +35 -0
  187. data/app/controllers/spree/api/v3/seller/base_controller.rb +25 -0
  188. data/app/controllers/spree/api/v3/seller/claim_reasons_controller.rb +20 -0
  189. data/app/controllers/spree/api/v3/seller/countries_controller.rb +38 -0
  190. data/app/controllers/spree/api/v3/seller/delivery_methods_controller.rb +265 -0
  191. data/app/controllers/spree/api/v3/seller/delivery_profiles_controller.rb +65 -0
  192. data/app/controllers/spree/api/v3/seller/delivery_zones_controller.rb +41 -0
  193. data/app/controllers/spree/api/v3/seller/direct_uploads_controller.rb +21 -0
  194. data/app/controllers/spree/api/v3/seller/exports_controller.rb +195 -0
  195. data/app/controllers/spree/api/v3/seller/import_rows_controller.rb +49 -0
  196. data/app/controllers/spree/api/v3/seller/imports_controller.rb +317 -0
  197. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +152 -0
  198. data/app/controllers/spree/api/v3/seller/invitations_controller.rb +71 -0
  199. data/app/controllers/spree/api/v3/seller/me_controller.rb +72 -0
  200. data/app/controllers/spree/api/v3/seller/onboarding_controller.rb +111 -0
  201. data/app/controllers/spree/api/v3/seller/order_cancellation_reasons_controller.rb +25 -0
  202. data/app/controllers/spree/api/v3/seller/orders/base_controller.rb +44 -0
  203. data/app/controllers/spree/api/v3/seller/orders/claims_controller.rb +45 -0
  204. data/app/controllers/spree/api/v3/seller/orders/deliveries_controller.rb +38 -0
  205. data/app/controllers/spree/api/v3/seller/orders/exchanges_controller.rb +50 -0
  206. data/app/controllers/spree/api/v3/seller/orders/fulfillments_controller.rb +79 -0
  207. data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +55 -0
  208. data/app/controllers/spree/api/v3/seller/orders/notes_controller.rb +82 -0
  209. data/app/controllers/spree/api/v3/seller/orders/returns_controller.rb +44 -0
  210. data/app/controllers/spree/api/v3/seller/orders_controller.rb +199 -0
  211. data/app/controllers/spree/api/v3/seller/package_types_controller.rb +100 -0
  212. data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +155 -0
  213. data/app/controllers/spree/api/v3/seller/payouts_controller.rb +47 -0
  214. data/app/controllers/spree/api/v3/seller/policies_controller.rb +57 -0
  215. data/app/controllers/spree/api/v3/seller/product_types_controller.rb +35 -0
  216. data/app/controllers/spree/api/v3/seller/products_controller.rb +394 -0
  217. data/app/controllers/spree/api/v3/seller/profile_controller.rb +137 -0
  218. data/app/controllers/spree/api/v3/seller/reasons_controller.rb +45 -0
  219. data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +95 -0
  220. data/app/controllers/spree/api/v3/seller/resource_controller.rb +75 -0
  221. data/app/controllers/spree/api/v3/seller/return_reasons_controller.rb +20 -0
  222. data/app/controllers/spree/api/v3/seller/stock_locations_controller.rb +56 -0
  223. data/app/controllers/spree/api/v3/seller/tax_identifiers_controller.rb +48 -0
  224. data/app/controllers/spree/api/v3/seller/team_controller.rb +103 -0
  225. data/app/controllers/spree/api/v3/seller/tracking_carriers_controller.rb +35 -0
  226. data/app/controllers/spree/api/v3/seller/transfers_controller.rb +43 -0
  227. data/app/controllers/spree/api/v3/store/account/companies_controller.rb +42 -0
  228. data/app/controllers/spree/api/v3/store/auth_controller.rb +21 -34
  229. data/app/controllers/spree/api/v3/store/base_controller.rb +4 -0
  230. data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +24 -2
  231. data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +41 -15
  232. data/app/controllers/spree/api/v3/store/carts/items_controller.rb +53 -20
  233. data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +36 -20
  234. data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +111 -0
  235. data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +2 -2
  236. data/app/controllers/spree/api/v3/store/carts/tax_identifiers_controller.rb +96 -0
  237. data/app/controllers/spree/api/v3/store/carts_controller.rb +57 -12
  238. data/app/controllers/spree/api/v3/store/categories_controller.rb +6 -3
  239. data/app/controllers/spree/api/v3/store/collections/products_controller.rb +59 -0
  240. data/app/controllers/spree/api/v3/store/collections_controller.rb +36 -0
  241. data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +81 -0
  242. data/app/controllers/spree/api/v3/store/companies/base_controller.rb +24 -0
  243. data/app/controllers/spree/api/v3/store/companies/invitations_controller.rb +50 -0
  244. data/app/controllers/spree/api/v3/store/companies/members_controller.rb +66 -0
  245. data/app/controllers/spree/api/v3/store/companies/orders_controller.rb +28 -0
  246. data/app/controllers/spree/api/v3/store/companies_controller.rb +47 -0
  247. data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +90 -0
  248. data/app/controllers/spree/api/v3/store/countries_controller.rb +8 -6
  249. data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +3 -1
  250. data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +78 -0
  251. data/app/controllers/spree/api/v3/store/customer/digital_links_controller.rb +52 -0
  252. data/app/controllers/spree/api/v3/store/customer/orders_controller.rb +6 -0
  253. data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +7 -3
  254. data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +3 -3
  255. data/app/controllers/spree/api/v3/store/customer/store_credits_controller.rb +0 -3
  256. data/app/controllers/spree/api/v3/store/customer/tax_identifiers_controller.rb +91 -0
  257. data/app/controllers/spree/api/v3/store/customers_controller.rb +26 -31
  258. data/app/controllers/spree/api/v3/store/data_feeds_controller.rb +11 -0
  259. data/app/controllers/spree/api/v3/store/data_request_downloads_controller.rb +58 -0
  260. data/app/controllers/spree/api/v3/store/delivery_methods_controller.rb +108 -0
  261. data/app/controllers/spree/api/v3/store/digital_links_controller.rb +105 -0
  262. data/app/controllers/spree/api/v3/store/markets/countries_controller.rb +5 -9
  263. data/app/controllers/spree/api/v3/store/markets_controller.rb +4 -4
  264. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +8 -9
  265. data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +94 -0
  266. data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +116 -0
  267. data/app/controllers/spree/api/v3/store/orders/tax_identifiers_controller.rb +46 -0
  268. data/app/controllers/spree/api/v3/store/orders_controller.rb +12 -15
  269. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +10 -3
  270. data/app/controllers/spree/api/v3/store/products_controller.rb +25 -6
  271. data/app/controllers/spree/api/v3/store/resource_controller.rb +2 -0
  272. data/app/controllers/spree/api/v3/store/sellers_controller.rb +43 -0
  273. data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +9 -6
  274. data/app/controllers/spree/api/v3/store/wishlists_controller.rb +3 -3
  275. data/app/controllers/spree/api/v3/webhooks/fulfillments_controller.rb +88 -0
  276. data/app/controllers/spree/api/v3/webhooks/payments_controller.rb +5 -2
  277. data/app/controllers/spree/api/v3/webhooks/payouts_controller.rb +61 -0
  278. data/app/models/spree/api/data_request_urls.rb +25 -0
  279. data/app/models/spree/api/digital_link_urls.rb +26 -0
  280. data/app/serializers/spree/api/v3/address_serializer.rb +17 -5
  281. data/app/serializers/spree/api/v3/admin/address_serializer.rb +27 -4
  282. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +13 -10
  283. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +1 -1
  284. data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +15 -0
  285. data/app/serializers/spree/api/v3/admin/cart_serializer.rb +34 -0
  286. data/app/serializers/spree/api/v3/admin/catalog_assignment_serializer.rb +32 -0
  287. data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +23 -0
  288. data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +48 -0
  289. data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +23 -0
  290. data/app/serializers/spree/api/v3/admin/catalog_product_serializer.rb +57 -0
  291. data/app/serializers/spree/api/v3/admin/catalog_product_term_serializer.rb +38 -0
  292. data/app/serializers/spree/api/v3/admin/catalog_quantity_rule_serializer.rb +37 -0
  293. data/app/serializers/spree/api/v3/admin/catalog_serializer.rb +46 -0
  294. data/app/serializers/spree/api/v3/admin/category_serializer.rb +3 -2
  295. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -1
  296. data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +16 -0
  297. data/app/serializers/spree/api/v3/admin/claim_reason_serializer.rb +21 -0
  298. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +29 -0
  299. data/app/serializers/spree/api/v3/admin/collection_rule_serializer.rb +22 -0
  300. data/app/serializers/spree/api/v3/admin/collection_serializer.rb +29 -0
  301. data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +67 -0
  302. data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +69 -0
  303. data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +61 -0
  304. data/app/serializers/spree/api/v3/admin/company_invitation_serializer.rb +15 -0
  305. data/app/serializers/spree/api/v3/admin/company_membership_serializer.rb +11 -0
  306. data/app/serializers/spree/api/v3/admin/company_serializer.rb +37 -0
  307. data/app/serializers/spree/api/v3/admin/concerns/external_references_attribute.rb +33 -0
  308. data/app/serializers/spree/api/v3/admin/consent_record_serializer.rb +28 -0
  309. data/app/serializers/spree/api/v3/admin/country_serializer.rb +2 -2
  310. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +1 -1
  311. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +2 -2
  312. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +2 -2
  313. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +23 -22
  314. data/app/serializers/spree/api/v3/admin/dashboard_counter_serializer.rb +24 -0
  315. data/app/serializers/spree/api/v3/admin/data_request_serializer.rb +36 -0
  316. data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +32 -0
  317. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +66 -1
  318. data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +15 -0
  319. data/app/serializers/spree/api/v3/admin/delivery_origin_group_serializer.rb +34 -0
  320. data/app/serializers/spree/api/v3/admin/delivery_profile_serializer.rb +65 -0
  321. data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +10 -1
  322. data/app/serializers/spree/api/v3/admin/delivery_serializer.rb +20 -0
  323. data/app/serializers/spree/api/v3/admin/delivery_zone_member_serializer.rb +11 -0
  324. data/app/serializers/spree/api/v3/admin/delivery_zone_serializer.rb +29 -0
  325. data/app/serializers/spree/api/v3/admin/digital_asset_serializer.rb +59 -0
  326. data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -4
  327. data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +16 -0
  328. data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +35 -0
  329. data/app/serializers/spree/api/v3/admin/export_serializer.rb +20 -1
  330. data/app/serializers/spree/api/v3/admin/fee_serializer.rb +14 -0
  331. data/app/serializers/spree/api/v3/admin/freight_summary_line_serializer.rb +46 -0
  332. data/app/serializers/spree/api/v3/admin/freight_summary_serializer.rb +16 -0
  333. data/app/serializers/spree/api/v3/admin/fulfillment_item_serializer.rb +39 -0
  334. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +31 -9
  335. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -3
  336. data/app/serializers/spree/api/v3/admin/import_serializer.rb +15 -2
  337. data/app/serializers/spree/api/v3/admin/integration_serializer.rb +32 -0
  338. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +4 -4
  339. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +19 -5
  340. data/app/serializers/spree/api/v3/admin/market_serializer.rb +5 -1
  341. data/app/serializers/spree/api/v3/admin/media_serializer.rb +50 -2
  342. data/app/serializers/spree/api/v3/admin/membership_product_serializer.rb +29 -0
  343. data/app/serializers/spree/api/v3/admin/order_cancellation_reason_serializer.rb +29 -0
  344. data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +50 -0
  345. data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +2 -6
  346. data/app/serializers/spree/api/v3/admin/order_serializer.rb +131 -19
  347. data/app/serializers/spree/api/v3/admin/package_type_serializer.rb +53 -0
  348. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +8 -2
  349. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -0
  350. data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +41 -0
  351. data/app/serializers/spree/api/v3/admin/permission_serializer.rb +39 -0
  352. data/app/serializers/spree/api/v3/admin/policy_serializer.rb +11 -0
  353. data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +22 -0
  354. data/app/serializers/spree/api/v3/admin/price_list_product_serializer.rb +32 -0
  355. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +20 -8
  356. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +2 -12
  357. data/app/serializers/spree/api/v3/admin/price_serializer.rb +3 -0
  358. data/app/serializers/spree/api/v3/admin/product_serializer.rb +54 -8
  359. data/app/serializers/spree/api/v3/admin/product_submission_serializer.rb +39 -0
  360. data/app/serializers/spree/api/v3/admin/product_type_custom_field_definition_serializer.rb +44 -0
  361. data/app/serializers/spree/api/v3/admin/product_type_serializer.rb +34 -0
  362. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +6 -12
  363. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +17 -15
  364. data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +80 -0
  365. data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +94 -0
  366. data/app/serializers/spree/api/v3/admin/refund_reason_serializer.rb +27 -0
  367. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +0 -5
  368. data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +72 -0
  369. data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +16 -0
  370. data/app/serializers/spree/api/v3/admin/return_reason_serializer.rb +21 -0
  371. data/app/serializers/spree/api/v3/admin/return_serializer.rb +59 -0
  372. data/app/serializers/spree/api/v3/admin/role_serializer.rb +24 -6
  373. data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +33 -0
  374. data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +37 -0
  375. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +46 -0
  376. data/app/serializers/spree/api/v3/admin/seller_requirement_serializer.rb +68 -0
  377. data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +48 -0
  378. data/app/serializers/spree/api/v3/admin/seller_requirement_submission_serializer.rb +57 -0
  379. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +92 -0
  380. data/app/serializers/spree/api/v3/admin/seller_team_member_serializer.rb +29 -0
  381. data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +53 -0
  382. data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +82 -0
  383. data/app/serializers/spree/api/v3/admin/state_serializer.rb +1 -1
  384. data/app/serializers/spree/api/v3/admin/stock_level_serializer.rb +65 -0
  385. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +20 -4
  386. data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +116 -0
  387. data/app/serializers/spree/api/v3/admin/stock_receipt_item_serializer.rb +57 -0
  388. data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +49 -0
  389. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +5 -5
  390. data/app/serializers/spree/api/v3/admin/stock_transfer_item_serializer.rb +57 -0
  391. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +36 -16
  392. data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +32 -0
  393. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +42 -7
  394. data/app/serializers/spree/api/v3/admin/store_serializer.rb +63 -1
  395. data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +39 -0
  396. data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +67 -0
  397. data/app/serializers/spree/api/v3/admin/tax_identifier_serializer.rb +43 -0
  398. data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +21 -0
  399. data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +49 -0
  400. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +49 -8
  401. data/app/serializers/spree/api/v3/applied_promotion_serializer.rb +23 -0
  402. data/app/serializers/spree/api/v3/base_serializer.rb +39 -2
  403. data/app/serializers/spree/api/v3/cart_serializer.rb +90 -12
  404. data/app/serializers/spree/api/v3/category_serializer.rb +3 -3
  405. data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +50 -0
  406. data/app/serializers/spree/api/v3/claim_reason_serializer.rb +20 -0
  407. data/app/serializers/spree/api/v3/claim_serializer.rb +62 -0
  408. data/app/serializers/spree/api/v3/collection_serializer.rb +41 -0
  409. data/app/serializers/spree/api/v3/company_invitation_serializer.rb +28 -0
  410. data/app/serializers/spree/api/v3/company_membership_serializer.rb +28 -0
  411. data/app/serializers/spree/api/v3/company_serializer.rb +33 -0
  412. data/app/serializers/spree/api/v3/custom_field_serializer.rb +2 -2
  413. data/app/serializers/spree/api/v3/customer_serializer.rb +9 -1
  414. data/app/serializers/spree/api/v3/data_request_event_serializer.rb +30 -0
  415. data/app/serializers/spree/api/v3/data_request_serializer.rb +40 -0
  416. data/app/serializers/spree/api/v3/delivery_method_serializer.rb +12 -2
  417. data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +34 -17
  418. data/app/serializers/spree/api/v3/delivery_serializer.rb +29 -0
  419. data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +29 -0
  420. data/app/serializers/spree/api/v3/delivery_zone_serializer.rb +13 -0
  421. data/app/serializers/spree/api/v3/digital_asset_serializer.rb +23 -0
  422. data/app/serializers/spree/api/v3/digital_link_serializer.rb +6 -2
  423. data/app/serializers/spree/api/v3/discount_serializer.rb +21 -7
  424. data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +53 -0
  425. data/app/serializers/spree/api/v3/exchange_serializer.rb +61 -0
  426. data/app/serializers/spree/api/v3/fee_serializer.rb +27 -0
  427. data/app/serializers/spree/api/v3/freight_summary_serializer.rb +38 -0
  428. data/app/serializers/spree/api/v3/fulfillment_serializer.rb +28 -15
  429. data/app/serializers/spree/api/v3/gift_card_serializer.rb +2 -2
  430. data/app/serializers/spree/api/v3/import_row_serializer.rb +1 -1
  431. data/app/serializers/spree/api/v3/import_serializer.rb +18 -4
  432. data/app/serializers/spree/api/v3/invitation_serializer.rb +1 -1
  433. data/app/serializers/spree/api/v3/line_item_serializer.rb +18 -1
  434. data/app/serializers/spree/api/v3/market_serializer.rb +2 -2
  435. data/app/serializers/spree/api/v3/{asset_serializer.rb → media_event_serializer.rb} +4 -4
  436. data/app/serializers/spree/api/v3/media_serializer.rb +48 -7
  437. data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +1 -1
  438. data/app/serializers/spree/api/v3/option_type_serializer.rb +1 -1
  439. data/app/serializers/spree/api/v3/order_group_serializer.rb +60 -0
  440. data/app/serializers/spree/api/v3/order_serializer.rb +58 -6
  441. data/app/serializers/spree/api/v3/payment_method_serializer.rb +1 -1
  442. data/app/serializers/spree/api/v3/payment_serializer.rb +2 -6
  443. data/app/serializers/spree/api/v3/payment_session_serializer.rb +10 -3
  444. data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +1 -1
  445. data/app/serializers/spree/api/v3/policy_serializer.rb +7 -2
  446. data/app/serializers/spree/api/v3/product_filter_option_serializer.rb +1 -1
  447. data/app/serializers/spree/api/v3/product_serializer.rb +42 -10
  448. data/app/serializers/spree/api/v3/product_type_serializer.rb +17 -0
  449. data/app/serializers/spree/api/v3/purchase_order_event_serializer.rb +11 -0
  450. data/app/serializers/spree/api/v3/refund_serializer.rb +9 -3
  451. data/app/serializers/spree/api/v3/return_line_item_serializer.rb +42 -0
  452. data/app/serializers/spree/api/v3/return_reason_serializer.rb +20 -0
  453. data/app/serializers/spree/api/v3/return_serializer.rb +62 -0
  454. data/app/serializers/spree/api/v3/seller/balance_serializer.rb +35 -0
  455. data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +21 -0
  456. data/app/serializers/spree/api/v3/seller/claim_serializer.rb +25 -0
  457. data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +32 -0
  458. data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +59 -0
  459. data/app/serializers/spree/api/v3/seller/delivery_profile_serializer.rb +26 -0
  460. data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +35 -0
  461. data/app/serializers/spree/api/v3/seller/delivery_serializer.rb +17 -0
  462. data/app/serializers/spree/api/v3/seller/delivery_zone_serializer.rb +26 -0
  463. data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +29 -0
  464. data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +30 -0
  465. data/app/serializers/spree/api/v3/seller/export_serializer.rb +44 -0
  466. data/app/serializers/spree/api/v3/seller/fulfillment_item_serializer.rb +43 -0
  467. data/app/serializers/spree/api/v3/seller/fulfillment_serializer.rb +76 -0
  468. data/app/serializers/spree/api/v3/seller/import_mapping_serializer.rb +20 -0
  469. data/app/serializers/spree/api/v3/seller/import_row_serializer.rb +17 -0
  470. data/app/serializers/spree/api/v3/seller/import_serializer.rb +77 -0
  471. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +29 -0
  472. data/app/serializers/spree/api/v3/seller/media_serializer.rb +26 -0
  473. data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +44 -0
  474. data/app/serializers/spree/api/v3/seller/order_serializer.rb +119 -0
  475. data/app/serializers/spree/api/v3/seller/package_type_serializer.rb +52 -0
  476. data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +34 -0
  477. data/app/serializers/spree/api/v3/seller/payout_serializer.rb +36 -0
  478. data/app/serializers/spree/api/v3/seller/policy_serializer.rb +11 -0
  479. data/app/serializers/spree/api/v3/seller/product_serializer.rb +60 -0
  480. data/app/serializers/spree/api/v3/seller/product_submission_serializer.rb +30 -0
  481. data/app/serializers/spree/api/v3/seller/product_type_serializer.rb +29 -0
  482. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +77 -0
  483. data/app/serializers/spree/api/v3/seller/reason_serializer.rb +24 -0
  484. data/app/serializers/spree/api/v3/seller/requirement_custom_field_serializer.rb +36 -0
  485. data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +62 -0
  486. data/app/serializers/spree/api/v3/seller/requirement_submission_serializer.rb +33 -0
  487. data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +24 -0
  488. data/app/serializers/spree/api/v3/seller/return_serializer.rb +51 -0
  489. data/app/serializers/spree/api/v3/seller/shipping_label_serializer.rb +23 -0
  490. data/app/serializers/spree/api/v3/seller/stock_level_serializer.rb +27 -0
  491. data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +17 -0
  492. data/app/serializers/spree/api/v3/seller/tax_identifier_serializer.rb +15 -0
  493. data/app/serializers/spree/api/v3/seller/team_member_serializer.rb +22 -0
  494. data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +49 -0
  495. data/app/serializers/spree/api/v3/seller/variant_serializer.rb +71 -0
  496. data/app/serializers/spree/api/v3/seller_serializer.rb +50 -0
  497. data/app/serializers/spree/api/v3/shipping_label_event_serializer.rb +11 -0
  498. data/app/serializers/spree/api/v3/{stock_item_serializer.rb → stock_level_serializer.rb} +5 -5
  499. data/app/serializers/spree/api/v3/stock_location_serializer.rb +11 -7
  500. data/app/serializers/spree/api/v3/stock_movement_serializer.rb +8 -15
  501. data/app/serializers/spree/api/v3/stock_receipt_event_serializer.rb +11 -0
  502. data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +6 -6
  503. data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +29 -0
  504. data/app/serializers/spree/api/v3/supplier_event_serializer.rb +11 -0
  505. data/app/serializers/spree/api/v3/tax_identifier_serializer.rb +15 -0
  506. data/app/serializers/spree/api/v3/tax_line_serializer.rb +37 -0
  507. data/app/serializers/spree/api/v3/variant_serializer.rb +52 -2
  508. data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +6 -6
  509. data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
  510. data/app/services/spree/api/v3/filters_aggregator.rb +14 -12
  511. data/app/services/spree/webhooks/deliver_webhook.rb +62 -26
  512. data/app/subscribers/spree/webhook_event_subscriber.rb +9 -5
  513. data/config/brakeman.ignore +1 -1
  514. data/config/initializers/typelizer.rb +51 -4
  515. data/config/locales/en.yml +5 -0
  516. data/config/routes.rb +730 -22
  517. data/lib/spree/api/configuration.rb +2 -7
  518. data/lib/spree/api/dependencies.rb +173 -227
  519. data/lib/spree/api/openapi/schema_helper.rb +179 -13
  520. data/lib/spree/api/testing_support/v3/base.rb +45 -15
  521. data/lib/spree/api.rb +10 -4
  522. data/lib/typelizer/open_enums.rb +35 -0
  523. metadata +341 -27
  524. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +0 -25
  525. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +0 -42
  526. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +0 -21
  527. data/app/controllers/spree/api/v3/store/digitals_controller.rb +0 -38
  528. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +0 -24
  529. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +0 -143
  530. data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +0 -15
  531. data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +0 -19
  532. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +0 -34
  533. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +0 -19
  534. data/app/serializers/spree/api/v3/customer_return_serializer.rb +0 -17
  535. data/app/serializers/spree/api/v3/digital_serializer.rb +0 -17
  536. data/app/serializers/spree/api/v3/reimbursement_serializer.rb +0 -27
  537. data/app/serializers/spree/api/v3/report_serializer.rb +0 -34
  538. data/app/serializers/spree/api/v3/return_authorization_serializer.rb +0 -31
  539. data/app/serializers/spree/api/v3/return_item_serializer.rb +0 -53
  540. data/app/serializers/spree/api/v3/shipping_category_serializer.rb +0 -11
@@ -76,16 +76,16 @@ module Spree
76
76
 
77
77
  private
78
78
 
79
- # Per-subclass permitted params. Calls `permitted_params` (the base
80
- # allowlist with `type` + `preferences`) and merges in extras the
81
- # subclass has declared via `additional_permitted_attributes`.
82
- # Controllers can override this hook directly if their subclasses
83
- # expose extras through a different mechanism.
79
+ # Per-subclass permitted params: the controller's own allowlist plus
80
+ # whatever the concrete subclass declares through
81
+ # `additional_permitted_attributes`. Controllers can override this
82
+ # hook directly if their subclasses expose extras through a different
83
+ # mechanism.
84
84
  def permitted_params_for(klass)
85
85
  extras = klass.respond_to?(:additional_permitted_attributes) ? klass.additional_permitted_attributes : []
86
86
  return permitted_params if extras.blank?
87
87
 
88
- params.permit(:type, { preferences: {} }, *extras)
88
+ permitted_params.merge(params.permit(:type, *extras, preferences: {}))
89
89
  end
90
90
 
91
91
  # Default build: top-level resource. Nested controllers (actions,
@@ -115,6 +115,12 @@ module Spree
115
115
  preferences.each do |key, value|
116
116
  pref_name = key.to_sym
117
117
  next unless resource.has_preference?(pref_name)
118
+ # Internal preferences are Spree's to write — a secret a
119
+ # provider issued, an id it gave back. They are absent from the
120
+ # schema, so no form offers them; ignoring them here is what
121
+ # stops a client writing one anyway and breaking the signature
122
+ # check that depends on it.
123
+ next if resource.preference_internal(pref_name)
118
124
  # Round-trip guard: clients fetching a record see masked
119
125
  # `:password` values. Submitting the mask back unchanged
120
126
  # must NOT overwrite the real secret with `••••cret`.
@@ -0,0 +1,91 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Richer validation details for the Admin API.
6
+ #
7
+ # The dashboard renders its own copy from its own locale files, so an
8
+ # admin working in one language never reads a message resolved in the
9
+ # store's. To let it do that, every entry carries the Rails error
10
+ # `code` and the interpolation values that go with it; `message` stays
11
+ # beside it as the fallback for clients without their own translation
12
+ # (integrations, scripts, and the dashboard's own last resort).
13
+ #
14
+ # Store API responses keep the flat `{ attribute => [message] }` shape
15
+ # — this override is deliberately not in the shared error handler.
16
+ module ValidationDetails
17
+ private
18
+
19
+ # @param errors [ActiveModel::Errors]
20
+ # @return [Hash{Symbol => Array<Hash>}] per-attribute error entries
21
+ def format_validation_details(errors)
22
+ errors.messages.each_with_object({}) do |(attribute, messages), result|
23
+ # `details` and `messages` are populated in lockstep by
24
+ # ActiveModel, so the nth message describes the nth detail. A
25
+ # message added as a bare string has no symbol and reports a
26
+ # nil code, which the dashboard reads as "render the message".
27
+ details = errors.details[attribute] || []
28
+
29
+ result[attribute] = messages.each_with_index.map do |message, index|
30
+ detail = details[index] || {}
31
+ code = detail[:error].is_a?(Symbol) ? detail[:error] : nil
32
+
33
+ # Interpolation values first, so the keys below are the ones
34
+ # this formatter computed: a validation may itself carry a
35
+ # `code:` option, and it must not displace the Rails error.
36
+ detail.except(:error).merge(
37
+ code: code,
38
+ message: message,
39
+ specific: code.present? &&
40
+ specific_message?(errors, attribute, code, message, detail.except(:error))
41
+ )
42
+ end
43
+ end
44
+ end
45
+
46
+ # Whether `message` says more than its `code` alone would.
47
+ #
48
+ # A code like `:invalid` is generic, and a client holding its own
49
+ # translation of that code should prefer it. But a model may override
50
+ # the message for the same code with something far more useful — the
51
+ # webhook URL validation reports `:invalid` and answers "must be a
52
+ # valid http or https URL". Replacing that with a translated "is
53
+ # invalid" loses what the merchant needs.
54
+ #
55
+ # Only the server can tell the two apart: the comparison is against
56
+ # the code's default *in the request's locale*, so it holds for a
57
+ # store trading in any language. A client cannot do it — it would
58
+ # have to recognise the default wording in every locale it supports.
59
+ #
60
+ # `raise: true` matters. Without it a code Rails has no default for
61
+ # — every Spree code, whose copy lives under `spree.errors.messages`
62
+ # — comes back as a "Translation missing" string, which differs from
63
+ # the message and would mark every one of them as an override.
64
+ #
65
+ # The validation's own options come along: rebuilding the default for
66
+ # `greater_than` without its `count` raises on the missing value.
67
+ #
68
+ # @return [Boolean] true when the model supplied its own wording
69
+ def specific_message?(errors, attribute, code, message, options = {})
70
+ message != errors.generate_message(attribute, code, **options.symbolize_keys, raise: true)
71
+ rescue StandardError
72
+ # Rebuilding the default can fail in several ordinary ways, and none
73
+ # of them should turn a 422 into a 500:
74
+ #
75
+ # - `I18n::MissingTranslationData` — no Rails default at all, which
76
+ # is every Spree code.
77
+ # - `I18n::MissingInterpolationArgument` — the default interpolates
78
+ # (`greater_than` wants `count`) but the call site passed only a
79
+ # `message:`, so the value was never recorded.
80
+ # - `NoMethodError` — a nested attribute (`option_values.name`)
81
+ # names no method to read.
82
+ #
83
+ # In each case there is no default to compare against, so report no
84
+ # override and let the client translate the code.
85
+ false
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -30,9 +30,9 @@ module Spree
30
30
  # Secret keys are checked first (server-to-server integrations),
31
31
  # then JWT tokens (admin SPA sessions).
32
32
  def authenticate_admin!
33
- # Try secret API key first
34
- @current_api_key = Spree::ApiKey.find_by_secret_token(extract_api_key)
35
- @current_api_key = nil if @current_api_key && @current_api_key.store_id != current_store.id
33
+ # Try secret API key first — the key selects the request's store
34
+ # (Admin::StoreContext), so there is no store check to make here.
35
+ @current_api_key = secret_api_key
36
36
 
37
37
  if @current_api_key
38
38
  touch_api_key_if_needed(@current_api_key)
@@ -61,10 +61,14 @@ module Spree
61
61
  false
62
62
  end
63
63
 
64
+ # Membership is holding a role the store itself owns, mirroring
65
+ # Spree::Ability#staff_roles. A role belonging to another resource — a
66
+ # marketplace seller, say — is that panel's business and never admits
67
+ # its holder here.
64
68
  def current_user_member_of_store?
65
- return false unless current_user.respond_to?(:role_users)
69
+ return false unless current_user.respond_to?(:spree_roles)
66
70
 
67
- current_user.role_users.exists?(store: current_store)
71
+ current_user.spree_roles.for_resource(current_store).exists?
68
72
  end
69
73
 
70
74
  def set_no_store_cache
@@ -12,11 +12,13 @@ module Spree
12
12
  end
13
13
 
14
14
  # Authenticates a publishable API key (pk_*) for Store API requests.
15
- # Looks up the key by plaintext token scoped to the current store.
15
+ # The key SELECTS the store lookup is global by token and
16
+ # +current_store+ derives from the key (see KeyStoreContext); the key
17
+ # is never validated against a host-resolved store.
16
18
  #
17
19
  # @return [Boolean] true if authentication succeeded, false otherwise
18
20
  def authenticate_api_key!
19
- @current_api_key = current_store.api_keys.active.publishable.find_by(token: extract_api_key)
21
+ @current_api_key = publishable_api_key
20
22
 
21
23
  unless @current_api_key
22
24
  render_error(
@@ -33,12 +35,12 @@ module Spree
33
35
 
34
36
  # Authenticates a secret API key (sk_*) for Admin API requests.
35
37
  # Computes the HMAC-SHA256 digest of the provided token and looks up
36
- # by +token_digest+, then verifies it belongs to the current store.
38
+ # by +token_digest+. The key is store-bound and selects the request's
39
+ # store (see Admin::StoreContext).
37
40
  #
38
41
  # @return [Boolean] true if authentication succeeded, false otherwise
39
42
  def authenticate_secret_key!
40
- @current_api_key = Spree::ApiKey.find_by_secret_token(extract_api_key)
41
- @current_api_key = nil if @current_api_key && @current_api_key.store_id != current_store.id
43
+ @current_api_key = secret_api_key
42
44
 
43
45
  unless @current_api_key
44
46
  render_error(
@@ -55,6 +57,31 @@ module Spree
55
57
 
56
58
  private
57
59
 
60
+ # Memoized global publishable-key lookup. Deliberately NOT scoped to
61
+ # +current_store+ — the store derives from the key, not the other way
62
+ # around. Memoizes misses too, so pre-authentication callers (store
63
+ # resolution) don't re-query.
64
+ #
65
+ # @return [Spree::ApiKey, nil]
66
+ def publishable_api_key
67
+ return @publishable_api_key if defined?(@publishable_api_key)
68
+
69
+ @publishable_api_key = Spree::StoreScopeGuard.skip do
70
+ extract_api_key ? Spree::ApiKey.active.publishable.find_by(token: extract_api_key) : nil
71
+ end
72
+ end
73
+
74
+ # Memoized global secret-key lookup (digest-based, active keys only).
75
+ #
76
+ # @return [Spree::ApiKey, nil]
77
+ def secret_api_key
78
+ return @secret_api_key if defined?(@secret_api_key)
79
+
80
+ @secret_api_key = Spree::StoreScopeGuard.skip do
81
+ Spree::ApiKey.find_by_secret_token(extract_api_key)
82
+ end
83
+ end
84
+
58
85
  # Marks the API key as used at most once per hour
59
86
  # to avoid unnecessary DB writes and job queue pressure on every request.
60
87
  # This follows the same approach as GitHub's personal access tokens.
@@ -70,6 +97,15 @@ module Spree
70
97
  def extract_api_key
71
98
  request.headers['X-Spree-Api-Key'].presence
72
99
  end
100
+
101
+ # True when the request presents a secret API key token (`sk_` prefix),
102
+ # regardless of whether authentication has resolved it into
103
+ # `current_api_key` yet. The token is unverified until
104
+ # `authenticate_secret_key!` resolves it, so consumers (the scope
105
+ # guard, rate limiting) must stay fail-closed on this signal alone.
106
+ def secret_key_request?
107
+ extract_api_key.to_s.start_with?(Spree::ApiKey::PREFIXES['secret'])
108
+ end
73
109
  end
74
110
  end
75
111
  end
@@ -0,0 +1,48 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Resolves the authentication strategy a login request asked for, shared by
5
+ # the Store and Admin auth controllers so the unsupported-provider contract
6
+ # (error code, status, message) has exactly one definition.
7
+ #
8
+ # Including controllers supply the registry and user class.
9
+ module AuthenticationStrategies
10
+ extend ActiveSupport::Concern
11
+
12
+ private
13
+
14
+ # @param provider [String, nil] defaults to the +provider+ param, then :email
15
+ # @return [Object, nil] a strategy instance, or nil after rendering an error
16
+ def authentication_strategy(provider = nil)
17
+ provider ||= params[:provider].presence || 'email'
18
+
19
+ strategy = authentication_strategies.build(
20
+ provider,
21
+ params: params,
22
+ request_env: request.headers.env,
23
+ user_class: authentication_user_class
24
+ )
25
+
26
+ return strategy if strategy
27
+
28
+ render_error(
29
+ code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:invalid_provider],
30
+ message: "Unsupported authentication provider: #{provider}",
31
+ status: :bad_request
32
+ )
33
+ nil
34
+ end
35
+
36
+ # @return [Spree::Authentication::StrategyRegistry]
37
+ def authentication_strategies
38
+ raise NotImplementedError, "#{self.class} must implement #authentication_strategies"
39
+ end
40
+
41
+ # @return [Class]
42
+ def authentication_user_class
43
+ raise NotImplementedError, "#{self.class} must implement #authentication_user_class"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,11 +1,9 @@
1
1
  module Spree
2
2
  module Api
3
3
  module V3
4
- # API-side counterpart to `Spree::Admin::BulkOperationsConcern`. Provides
5
- # the shared tag bulk actions, the `bulk_collection` relation, and the
6
- # `after_bulk_tags_change` hook controllers override (e.g. to reindex
7
- # search + match automatic taxons). Shape mirrors the legacy concern so
8
- # the two stay easy to keep in sync.
4
+ # Provides the shared tag bulk actions, the `bulk_collection` relation,
5
+ # and the `after_bulk_tags_change` hook controllers override (e.g. to
6
+ # reindex search + match automatic taxons).
9
7
  module BulkOperations
10
8
  extend ActiveSupport::Concern
11
9
 
@@ -56,7 +54,7 @@ module Spree
56
54
 
57
55
  # Hook for controllers to perform additional work after bulk tag
58
56
  # mutations — e.g. enqueueing search reindex jobs, re-matching
59
- # automatic taxons. Mirrors `Spree::Admin::BulkOperationsConcern`.
57
+ # automatic taxons.
60
58
  def after_bulk_tags_change
61
59
  end
62
60
 
@@ -6,33 +6,69 @@ module Spree
6
6
 
7
7
  protected
8
8
 
9
- # Find cart by prefixed ID and authorize access via CanCanCan.
10
- # @return [Spree::Order]
11
- def find_cart
12
- cart_id = params[:cart_id] || params[:id]
13
- @cart = current_store.carts.find_by_prefix_id!(cart_id)
14
- authorize!(:show, @cart, cart_token)
9
+ # Find cart by prefixed ID and authorize read access (owner or guest
10
+ # token). Completed carts are not carts anymore — they 404 unless the
11
+ # caller opts in (idempotent completion, payment-session confirm races).
12
+ # @return [Spree::Cart]
13
+ def find_cart(include_completed: false)
14
+ @cart = resolve_cart(include_completed: include_completed)
15
+ authorize_storefront_read!(@cart, token: cart_token)
15
16
  @cart
16
17
  end
17
18
 
18
- # Find the cart and authorize it for update.
19
- # @return [Spree::Order]
20
- def find_cart!
21
- cart_id = params[:cart_id] || params[:id]
22
- @cart = current_store.carts.find_by_prefix_id!(cart_id)
23
- authorize!(:update, @cart, cart_token)
19
+ # Find the cart and authorize it for mutation. A completed cart
20
+ # resolves only for opted-in flows, where mutation is impossible — a
21
+ # read check is the right bar there.
22
+ # @return [Spree::Cart]
23
+ def find_cart!(include_completed: false)
24
+ @cart = resolve_cart(include_completed: include_completed)
25
+
26
+ if @cart.completed?
27
+ authorize_storefront_read!(@cart, token: cart_token)
28
+ else
29
+ authorize_storefront_write!(@cart, token: cart_token)
30
+ end
31
+
24
32
  @cart
25
33
  end
26
34
 
27
- # Render the cart as JSON using the cart serializer.
35
+ def resolve_cart(include_completed:)
36
+ cart_id = params[:cart_id] || params[:id]
37
+ scope = current_store.carts
38
+ scope = scope.incomplete unless include_completed
39
+ scope.find_by_prefix_id!(cart_id)
40
+ end
41
+
42
+ # Render the cart as JSON using the cart serializer. Rendering never
43
+ # mutates: an action that wants unbuyable lines swept calls
44
+ # +sweep_unbuyable_lines!+ itself first.
28
45
  def render_cart(status: :ok)
29
- @cart = @cart.remove_out_of_stock_items!
30
46
  render json: Spree.api.cart_serializer.new(@cart, params: serializer_params).to_h, status: status
31
47
  end
32
48
 
33
- # Render the order as JSON using the order serializer (for complete action).
49
+ # Drops lines the customer can no longer buy a discontinued product,
50
+ # or stock that ran out while the cart sat idle. For reads of a cart
51
+ # the customer is returning to, never for the write that just
52
+ # happened: an add a stock check already approved must not be
53
+ # second-guessed in the same request, and an external inventory
54
+ # provider makes that contradiction routine, since the provider
55
+ # answers the write while the sweep reads Spree's own rows.
56
+ def sweep_unbuyable_lines!
57
+ @cart = @cart.remove_out_of_stock_items!
58
+ end
59
+
60
+ # Render what the checkout produced (for the complete action).
61
+ #
62
+ # A checkout spanning several sellers produced a group of orders rather
63
+ # than one order, and the group is what the customer bought — so it is
64
+ # what comes back, with the per-seller orders nested inside it. A
65
+ # storefront that knows nothing about groups still finds every order it
66
+ # needs there.
34
67
  def render_order(status: :ok)
35
- render json: Spree.api.order_serializer.new(@cart.reload, params: serializer_params).to_h, status: status
68
+ record = @cart.reload
69
+ serializer = record.is_a?(Spree::OrderGroup) ? Spree.api.order_group_serializer : Spree.api.order_serializer
70
+
71
+ render json: serializer.new(record, params: serializer_params).to_h, status: status
36
72
  end
37
73
 
38
74
  # Return the cart token from the request headers.
@@ -0,0 +1,37 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Writing an entry in a company node's address book, on either API.
5
+ #
6
+ # An entry is an ordinary address the node owns, so the payload is
7
+ # address attributes plus the label it is filed under. The two defaults
8
+ # are not columns on the row — they are pointers on the node — so they
9
+ # travel to the address services as flags, which apply them once the
10
+ # address itself is written.
11
+ module CompanyAddressWrites
12
+ extend ActiveSupport::Concern
13
+
14
+ protected
15
+
16
+ def permitted_params
17
+ params.permit(:label, *Spree::Api::V3::AddressParams::ADDRESS_KEYS)
18
+ end
19
+
20
+ # @return [Hash] default keywords for Spree::Addresses::Create / Update
21
+ def default_flags
22
+ { default_billing: flag_param(:default_billing), default_shipping: flag_param(:default_shipping) }
23
+ end
24
+
25
+ # Each flag has three meanings and they are all different: true claims
26
+ # the slot, false gives it up, and saying nothing leaves it alone.
27
+ #
28
+ # @return [Boolean, nil] nil when the client said nothing about it
29
+ def flag_param(name)
30
+ return nil unless params.key?(name)
31
+
32
+ ActiveModel::Type::Boolean.new.cast(params[name])
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,41 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Re-asks for the account password before something irreversible.
5
+ #
6
+ # Shared because the check must not drift: a customer class may
7
+ # authenticate through `valid_password?` or `authenticate` depending on
8
+ # what the host app swapped in, and a second copy of that ladder is a
9
+ # second thing to remember when it changes. One of the two call sites
10
+ # gates permanent erasure.
11
+ module CurrentPasswordConfirmation
12
+ extend ActiveSupport::Concern
13
+
14
+ private
15
+
16
+ # @return [Boolean] whether `current_password` matches the signed-in
17
+ # account. False when the parameter is missing — an absent password
18
+ # is not a correct one.
19
+ def valid_current_password?
20
+ return false if params[:current_password].blank?
21
+
22
+ if current_user.respond_to?(:valid_password?)
23
+ current_user.valid_password?(params[:current_password])
24
+ elsif current_user.respond_to?(:authenticate)
25
+ current_user.authenticate(params[:current_password]).present?
26
+ else
27
+ false
28
+ end
29
+ end
30
+
31
+ def render_current_password_invalid
32
+ render_error(
33
+ code: ErrorHandler::ERROR_CODES[:current_password_invalid],
34
+ message: Spree.t(:current_password_invalid, scope: :api),
35
+ status: :unprocessable_content
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,35 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Presigning for direct-to-storage uploads: a caller exchanges blob
5
+ # metadata for an upload URL and gets back a signed id to reference when
6
+ # it creates or updates a resource.
7
+ #
8
+ # Shared by the admin and seller branches because the exchange itself is
9
+ # audience-neutral — a blob created here is attached to nothing. What
10
+ # differs is the gate each branch puts in front of it, which stays on the
11
+ # including controller as its `scoped_resource`.
12
+ module DirectUploads
13
+ extend ActiveSupport::Concern
14
+
15
+ def create
16
+ blob = ActiveStorage::Blob.create_before_direct_upload!(**blob_params)
17
+
18
+ render json: {
19
+ direct_upload: {
20
+ url: blob.service_url_for_direct_upload,
21
+ headers: blob.service_headers_for_direct_upload
22
+ },
23
+ signed_id: blob.signed_id
24
+ }, status: :created
25
+ end
26
+
27
+ private
28
+
29
+ def blob_params
30
+ params.require(:blob).permit(:filename, :byte_size, :checksum, :content_type).to_h.symbolize_keys
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -13,6 +13,10 @@ module Spree
13
13
  invalid_token: 'invalid_token',
14
14
  invalid_provider: 'invalid_provider',
15
15
  invalid_refresh_token: 'invalid_refresh_token',
16
+ # Distinct from authentication_failed: the person proved who they are to
17
+ # the identity provider, but no account here is authorized for them.
18
+ account_not_provisioned: 'account_not_provisioned',
19
+ invalid_oauth_state: 'invalid_oauth_state',
16
20
  current_password_invalid: 'current_password_invalid',
17
21
  password_reset_token_invalid: 'password_reset_token_invalid',
18
22
  redirect_url_not_allowed: 'redirect_url_not_allowed',
@@ -36,12 +40,15 @@ module Spree
36
40
  # Order errors
37
41
  order_not_found: 'order_not_found',
38
42
  order_cannot_complete: 'order_cannot_complete',
43
+ discount_not_editable: 'discount_not_editable',
39
44
 
40
45
  # Line item errors
41
46
  line_item_not_found: 'line_item_not_found',
42
47
  variant_not_found: 'variant_not_found',
43
48
  insufficient_stock: 'insufficient_stock',
44
49
  invalid_quantity: 'invalid_quantity',
50
+ invalid_price: 'invalid_price',
51
+ price_override_not_allowed: 'price_override_not_allowed',
45
52
 
46
53
  # Validation errors
47
54
  validation_error: 'validation_error',
@@ -85,12 +92,12 @@ module Spree
85
92
  # Override base controller error handlers
86
93
  rescue_from ActiveRecord::RecordNotFound, with: :handle_record_not_found
87
94
  rescue_from CanCan::AccessDenied, with: :handle_access_denied
95
+ rescue_from Spree::Storefront::AccessDenied, with: :handle_access_denied
88
96
  rescue_from Spree::Core::GatewayError, with: :handle_gateway_error
89
97
  rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing
90
98
  rescue_from ActiveRecord::RecordInvalid, with: :handle_record_invalid
91
99
  rescue_from ArgumentError, with: :handle_argument_error
92
100
  rescue_from ActionDispatch::Http::Parameters::ParseError, with: :handle_parse_error
93
- rescue_from StateMachines::InvalidTransition, with: :handle_invalid_transition
94
101
  end
95
102
 
96
103
  protected
@@ -122,12 +129,33 @@ module Spree
122
129
  )
123
130
  end
124
131
 
132
+ # Maps symbolic line-item rejections onto the API error-code vocabulary.
133
+ #
134
+ # @param errors [ActiveModel::Errors, Object] structured rejection from a workflow
135
+ # @param default [String] fallback when no recognized symbol is present
136
+ # @return [String] a value from {ERROR_CODES}
137
+ def infer_line_item_error_code(errors, default:)
138
+ return default unless errors.is_a?(ActiveModel::Errors)
139
+
140
+ base_symbols = (errors.details[:base] || []).pluck(:error)
141
+ return ERROR_CODES[:price_override_not_allowed] if base_symbols.include?(:price_override_not_allowed)
142
+ return ERROR_CODES[:invalid_price] if base_symbols.include?(:invalid_price)
143
+ return ERROR_CODES[:invalid_quantity] if base_symbols.include?(:quantity_rule_violated)
144
+
145
+ default
146
+ end
147
+
125
148
  # Convenience method for service result errors
126
149
  def render_service_error(error, code: ERROR_CODES[:processing_error], status: :unprocessable_content)
127
150
  if error.is_a?(ActiveModel::Errors)
128
151
  render_validation_error(error, code: code)
129
152
  elsif error.is_a?(String)
130
153
  render_error(code: code, message: error, status: status)
154
+ elsif error.is_a?(Symbol)
155
+ # Workflows reject with a symbol naming the reason. Translate it,
156
+ # falling back to the symbol so a missing key is visible rather
157
+ # than silently blank.
158
+ render_error(code: code, message: Spree.t(error, default: error.to_s.humanize), status: status)
131
159
  else
132
160
  render_error(code: code, message: error.to_s, status: status)
133
161
  end
@@ -161,10 +189,33 @@ module Spree
161
189
  render_error(
162
190
  code: ERROR_CODES[:access_denied],
163
191
  message: exception.message,
164
- status: :forbidden
192
+ status: :forbidden,
193
+ details: access_denied_details
165
194
  )
166
195
  end
167
196
 
197
+ # Names the catalog permission the failed request needed, derived from
198
+ # the controller's `scoped_resource` declaration — the JWT twin of the
199
+ # scope check's `required_scope` (docs/plans/6.0-admin-rbac.md). Only
200
+ # reported when the caller genuinely lacks the key: a denial the caller
201
+ # is capability-authorized for is a record- or store-level condition,
202
+ # and naming a permission they already hold would mislead.
203
+ def access_denied_details
204
+ return unless respond_to?(:scoped_resource_name, true)
205
+
206
+ resource = scoped_resource_name
207
+ return unless resource
208
+
209
+ required = "#{action_kind}_#{resource}"
210
+ return unless Spree.permissions.key?(required)
211
+
212
+ ability = current_ability
213
+ return unless ability.respond_to?(:permission_keys)
214
+ return if ability.permission_keys.include?(required)
215
+
216
+ { required_permission: required }
217
+ end
218
+
168
219
  def handle_gateway_error(exception)
169
220
  Rails.error.report(exception, context: error_context, source: 'spree.api.v3')
170
221
  render_error(
@@ -207,15 +258,6 @@ module Spree
207
258
  )
208
259
  end
209
260
 
210
- def handle_invalid_transition(exception)
211
- Rails.error.report(exception, context: error_context, source: 'spree.api.v3')
212
- render_error(
213
- code: ERROR_CODES[:cart_cannot_transition],
214
- message: exception.message,
215
- status: :unprocessable_content
216
- )
217
- end
218
-
219
261
 
220
262
  private
221
263
 
@@ -67,10 +67,16 @@ module Spree
67
67
  end
68
68
 
69
69
  def idempotency_cache_key(key)
70
- owner_id = request.headers['X-Spree-Api-Key'].presence ||
71
- spree_current_user&.id ||
72
- request.remote_ip
73
- "spree:idempotency:#{Digest::SHA256.hexdigest(owner_id.to_s)}:#{Digest::SHA256.hexdigest(key)}"
70
+ credential = request.headers['X-Spree-Api-Key'].presence ||
71
+ spree_current_user&.id ||
72
+ request.remote_ip
73
+ # The resolved store partitions the namespace: a staff JWT spans
74
+ # stores, and replaying one store's cached response for a request
75
+ # aimed at another would cross store boundaries. The resolved
76
+ # store — not the raw header — so a header naming the default store
77
+ # and no header at all land in the same partition, as they resolve
78
+ # to the same store.
79
+ "spree:idempotency:#{Digest::SHA256.hexdigest("#{credential}\0#{current_store&.id}\0#{key}")}"
74
80
  end
75
81
 
76
82
  def request_fingerprint