spree_api 6.0.0.beta4 → 6.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +4 -31
- data/app/controllers/concerns/spree/api/v3/admin/email_template_lookup.rb +139 -0
- data/app/controllers/concerns/spree/api/v3/admin/store_context.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +7 -0
- data/app/controllers/concerns/spree/api/v3/channel_resolution.rb +2 -2
- data/app/controllers/concerns/spree/api/v3/current_password_confirmation.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/error_handler.rb +7 -2
- data/app/controllers/concerns/spree/api/v3/http_caching.rb +44 -11
- data/app/controllers/concerns/spree/api/v3/idempotent.rb +20 -5
- data/app/controllers/concerns/spree/api/v3/items_payload.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/order_lock.rb +2 -2
- data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +1 -5
- data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +2 -10
- data/app/controllers/concerns/spree/api/v3/orders/post_sale_actions.rb +2 -10
- data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +4 -8
- data/app/controllers/concerns/spree/api/v3/permission_serialization.rb +9 -1
- data/app/controllers/concerns/spree/api/v3/seller/seller_context.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/store/storefront_products.rb +5 -4
- data/app/controllers/concerns/spree/api/v3/storefront_gating.rb +11 -5
- data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +0 -5
- data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +0 -6
- data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/channels_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +1 -2
- data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +2 -2
- data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/companies/invitations_controller.rb +1 -5
- data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +1 -9
- data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/companies_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/countries_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/coupon_codes_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +9 -1
- data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/customers/credit_cards_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/customers_controller.rb +2 -2
- data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +3 -5
- data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +1 -6
- data/app/controllers/spree/api/v3/admin/email_templates/drafts_controller.rb +40 -0
- data/app/controllers/spree/api/v3/admin/email_templates/previews_controller.rb +30 -0
- data/app/controllers/spree/api/v3/admin/email_templates/publications_controller.rb +30 -0
- data/app/controllers/spree/api/v3/admin/email_templates/restorations_controller.rb +34 -0
- data/app/controllers/spree/api/v3/admin/email_templates/revisions_controller.rb +35 -0
- data/app/controllers/spree/api/v3/admin/email_templates/sample_records_controller.rb +33 -0
- data/app/controllers/spree/api/v3/admin/email_templates/test_emails_controller.rb +40 -0
- data/app/controllers/spree/api/v3/admin/email_templates_controller.rb +46 -0
- data/app/controllers/spree/api/v3/admin/imports_controller.rb +1 -2
- data/app/controllers/spree/api/v3/admin/invitations_controller.rb +0 -7
- data/app/controllers/spree/api/v3/admin/me_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/media_library_controller.rb +5 -5
- data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +1 -5
- data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +18 -16
- data/app/controllers/spree/api/v3/admin/orders/gift_cards_controller.rb +3 -3
- data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +2 -10
- data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +2 -14
- data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +1 -5
- data/app/controllers/spree/api/v3/admin/orders_controller.rb +3 -3
- data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +9 -7
- data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +6 -53
- data/app/controllers/spree/api/v3/admin/prices_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +2 -6
- data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/products_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/resource_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +1 -9
- data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +2 -10
- data/app/controllers/spree/api/v3/admin/seller_transfers_controller.rb +0 -4
- data/app/controllers/spree/api/v3/admin/sellers/invitations_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/sellers/payouts_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/sellers_controller.rb +2 -10
- data/app/controllers/spree/api/v3/admin/setup_controller.rb +3 -11
- data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/store_controller.rb +6 -1
- data/app/controllers/spree/api/v3/admin/tags_controller.rb +8 -5
- data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +17 -12
- data/app/controllers/spree/api/v3/admin/webhook_events_controller.rb +25 -0
- data/app/controllers/spree/api/v3/base_controller.rb +10 -0
- data/app/controllers/spree/api/v3/resource_controller.rb +44 -1
- data/app/controllers/spree/api/v3/seller/auth_controller.rb +2 -2
- data/app/controllers/spree/api/v3/seller/countries_controller.rb +1 -1
- data/app/controllers/spree/api/v3/seller/exports_controller.rb +3 -3
- data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +3 -3
- data/app/controllers/spree/api/v3/seller/invitations_controller.rb +1 -1
- data/app/controllers/spree/api/v3/seller/me_controller.rb +1 -1
- data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +1 -1
- data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +10 -11
- data/app/controllers/spree/api/v3/seller/products_controller.rb +2 -1
- data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +1 -1
- data/app/controllers/spree/api/v3/seller/team_controller.rb +1 -1
- data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +1 -1
- data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +3 -11
- data/app/controllers/spree/api/v3/store/carts/gift_cards_controller.rb +5 -3
- data/app/controllers/spree/api/v3/store/carts/items_controller.rb +6 -2
- data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +1 -1
- data/app/controllers/spree/api/v3/store/carts/payments_controller.rb +5 -3
- data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +2 -2
- data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +2 -0
- data/app/controllers/spree/api/v3/store/carts_controller.rb +9 -6
- data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/companies/invitations_controller.rb +1 -5
- data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +1 -1
- data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/customer/credit_cards_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +0 -5
- data/app/controllers/spree/api/v3/store/customer/digital_links_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/customer/gift_cards_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/customer/orders_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +8 -6
- data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +0 -4
- data/app/controllers/spree/api/v3/store/customer/store_credits_controller.rb +0 -5
- data/app/controllers/spree/api/v3/store/data_request_downloads_controller.rb +1 -1
- data/app/controllers/spree/api/v3/store/delivery_methods_controller.rb +1 -1
- data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +5 -14
- data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +1 -5
- data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +1 -5
- data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +0 -4
- data/app/serializers/spree/api/v3/admin/address_serializer.rb +5 -7
- data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/admin/catalog_assignment_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/catalog_product_term_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/catalog_quantity_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/channel_serializer.rb +5 -6
- data/app/serializers/spree/api/v3/admin/claim_reason_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/coupon_code_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +6 -2
- data/app/serializers/spree/api/v3/admin/customer_serializer.rb +2 -10
- data/app/serializers/spree/api/v3/admin/data_request_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +8 -22
- data/app/serializers/spree/api/v3/admin/delivery_origin_group_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/delivery_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/delivery_zone_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/digital_asset_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/admin/email_template_draft_serializer.rb +19 -0
- data/app/serializers/spree/api/v3/admin/email_template_preview_serializer.rb +38 -0
- data/app/serializers/spree/api/v3/admin/email_template_revision_serializer.rb +18 -0
- data/app/serializers/spree/api/v3/admin/email_template_sample_record_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/admin/email_template_serializer.rb +61 -0
- data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/export_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/fulfillment_item_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/admin/market_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/admin/media_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/order_cancellation_reason_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +3 -9
- data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +5 -15
- data/app/serializers/spree/api/v3/admin/package_type_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +7 -1
- data/app/serializers/spree/api/v3/admin/payment_serializer.rb +2 -7
- data/app/serializers/spree/api/v3/admin/permission_serializer.rb +4 -4
- data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +2 -10
- data/app/serializers/spree/api/v3/admin/product_submission_serializer.rb +2 -10
- data/app/serializers/spree/api/v3/admin/product_type_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +2 -15
- data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +2 -15
- data/app/serializers/spree/api/v3/admin/refund_reason_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/refund_serializer.rb +4 -1
- data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +1 -0
- data/app/serializers/spree/api/v3/admin/return_reason_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/return_serializer.rb +3 -11
- data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/admin/seller_requirement_submission_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/seller_serializer.rb +5 -15
- data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +6 -19
- data/app/serializers/spree/api/v3/admin/stock_level_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/stock_receipt_item_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/stock_transfer_item_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +4 -18
- data/app/serializers/spree/api/v3/admin/store_serializer.rb +24 -6
- data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +3 -9
- data/app/serializers/spree/api/v3/admin/tax_identifier_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +5 -1
- data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/admin/variant_serializer.rb +6 -7
- data/app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/webhook_event_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/applied_promotion_serializer.rb +2 -4
- data/app/serializers/spree/api/v3/base_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/cart_serializer.rb +17 -45
- data/app/serializers/spree/api/v3/category_serializer.rb +5 -15
- data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +11 -26
- data/app/serializers/spree/api/v3/claim_serializer.rb +2 -15
- data/app/serializers/spree/api/v3/collection_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/company_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/custom_field_serializer.rb +1 -2
- data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +3 -23
- data/app/serializers/spree/api/v3/digital_asset_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/digital_link_serializer.rb +3 -9
- data/app/serializers/spree/api/v3/discount_serializer.rb +1 -12
- data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +9 -27
- data/app/serializers/spree/api/v3/exchange_serializer.rb +2 -15
- data/app/serializers/spree/api/v3/export_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/fee_serializer.rb +2 -10
- data/app/serializers/spree/api/v3/fulfillment_serializer.rb +4 -11
- data/app/serializers/spree/api/v3/gift_card_batch_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +5 -17
- data/app/serializers/spree/api/v3/import_row_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/import_serializer.rb +3 -14
- data/app/serializers/spree/api/v3/invitation_serializer.rb +2 -19
- data/app/serializers/spree/api/v3/line_item_serializer.rb +6 -20
- data/app/serializers/spree/api/v3/media_event_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/media_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/newsletter_subscriber_request_event_serializer.rb +35 -0
- data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/option_value_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/order_group_serializer.rb +2 -23
- data/app/serializers/spree/api/v3/order_serializer.rb +12 -38
- data/app/serializers/spree/api/v3/password_reset_requested_event_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/payment_method_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/payment_serializer.rb +5 -10
- data/app/serializers/spree/api/v3/payment_session_serializer.rb +3 -9
- data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +3 -11
- data/app/serializers/spree/api/v3/policy_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/price_history_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/price_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/product_publication_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/product_serializer.rb +7 -21
- data/app/serializers/spree/api/v3/product_submission_serializer.rb +26 -0
- data/app/serializers/spree/api/v3/purchase_order_event_serializer.rb +23 -4
- data/app/serializers/spree/api/v3/refund_serializer.rb +3 -11
- data/app/serializers/spree/api/v3/return_line_item_serializer.rb +12 -19
- data/app/serializers/spree/api/v3/return_serializer.rb +6 -15
- data/app/serializers/spree/api/v3/saved_report_event_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/seller/delivery_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/seller/delivery_zone_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/seller/fulfillment_item_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/seller/fulfillment_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +7 -13
- data/app/serializers/spree/api/v3/seller/order_serializer.rb +4 -25
- data/app/serializers/spree/api/v3/seller/payout_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/seller/product_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/seller/product_submission_serializer.rb +1 -21
- data/app/serializers/spree/api/v3/seller/profile_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +3 -9
- data/app/serializers/spree/api/v3/seller/return_serializer.rb +3 -15
- data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/seller_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/shipping_label_event_serializer.rb +22 -4
- data/app/serializers/spree/api/v3/stock_level_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/stock_movement_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/stock_receipt_event_serializer.rb +20 -4
- data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +1 -7
- data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +2 -11
- data/app/serializers/spree/api/v3/store_credit_serializer.rb +2 -24
- data/app/serializers/spree/api/v3/supplier_event_serializer.rb +6 -4
- data/app/serializers/spree/api/v3/tax_line_serializer.rb +10 -20
- data/app/serializers/spree/api/v3/variant_serializer.rb +7 -21
- data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +1 -11
- data/app/serializers/spree/api/v3/wishlist_serializer.rb +2 -6
- data/app/subscribers/spree/webhook_event_subscriber.rb +3 -10
- data/config/initializers/pagy.rb +1 -1
- data/config/initializers/typelizer.rb +6 -8
- data/config/locales/ar.yml +15 -0
- data/config/locales/be.yml +15 -0
- data/config/locales/bg.yml +15 -0
- data/config/locales/ca.yml +15 -0
- data/config/locales/cs.yml +15 -0
- data/config/locales/da.yml +15 -0
- data/config/locales/de-CH.yml +11 -0
- data/config/locales/de.yml +15 -0
- data/config/locales/el.yml +15 -0
- data/config/locales/en.yml +5 -40
- data/config/locales/es-CL.yml +10 -0
- data/config/locales/es-EC.yml +11 -0
- data/config/locales/es-MX.yml +12 -0
- data/config/locales/es.yml +15 -0
- data/config/locales/et.yml +15 -0
- data/config/locales/fa.yml +15 -0
- data/config/locales/fi.yml +15 -0
- data/config/locales/fr.yml +15 -0
- data/config/locales/hu.yml +15 -0
- data/config/locales/id.yml +15 -0
- data/config/locales/it.yml +15 -0
- data/config/locales/ja.yml +15 -0
- data/config/locales/km.yml +15 -0
- data/config/locales/ko.yml +15 -0
- data/config/locales/ku.yml +15 -0
- data/config/locales/lt.yml +15 -0
- data/config/locales/lv.yml +15 -0
- data/config/locales/nb.yml +15 -0
- data/config/locales/ne.yml +15 -0
- data/config/locales/nl.yml +15 -0
- data/config/locales/pl.yml +15 -0
- data/config/locales/pt-BR.yml +13 -0
- data/config/locales/pt.yml +15 -0
- data/config/locales/ro.yml +15 -0
- data/config/locales/ru.yml +15 -0
- data/config/locales/sk.yml +15 -0
- data/config/locales/sl-SI.yml +15 -0
- data/config/locales/sv.yml +15 -0
- data/config/locales/th.yml +15 -0
- data/config/locales/tr.yml +15 -0
- data/config/locales/uk.yml +15 -0
- data/config/locales/vi.yml +15 -0
- data/config/locales/zh-CN.yml +15 -0
- data/config/locales/zh-TW.yml +15 -0
- data/config/routes.rb +49 -99
- data/lib/spree/api/dependencies.rb +53 -274
- data/lib/spree/api/openapi/schema_helper.rb +1 -1
- data/lib/spree/api/typelizer_generation.rb +35 -0
- data/lib/spree/api/webhook_event_types.rb +140 -0
- data/lib/spree/api.rb +0 -2
- metadata +71 -36
- data/config/i18n-tasks.yml +0 -40
- data/config/initializers/alba.rb +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3816f80ebaf4e6b8bc42854938340dce8bc17f6190d55337a7e08950fedf7fb1
|
|
4
|
+
data.tar.gz: 42034e2f05201a30da2d13345b761e1376523ecf98f64668de3538de772a19f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f315aff41e1e8731961bfa6cf18bba36428e222aa11ed341b66c9b74bee863eb53b5cece23b361a73a036f5d744e25037e25ec1a49004653a8a7f0448f29a10c
|
|
7
|
+
data.tar.gz: 34d2faa68118ec0bba15cf75b5711ade7aa0b1d817606180a3e7fb2a57bfdb816799f2911b83b41833f07251f0781d9d5e9046251eb6068356956839b38fc59e
|
data/Rakefile
CHANGED
|
@@ -67,39 +67,12 @@ namespace :rswag do
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
namespace :typelizer do
|
|
70
|
-
desc 'Generate TypeScript types for
|
|
70
|
+
desc 'Generate TypeScript types for every SDK (runs in spree_emails, where all serializers load)'
|
|
71
71
|
task :generate do
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
require File.expand_path('spec/dummy/config/environment', __dir__)
|
|
76
|
-
|
|
77
|
-
# Eager load serializers so typelizer can find them
|
|
78
|
-
serializers_path = File.expand_path('app/serializers/spree/api/v3', __dir__)
|
|
79
|
-
Rails.autoloaders.main.eager_load_dir(serializers_path)
|
|
80
|
-
|
|
81
|
-
require 'typelizer/generator'
|
|
82
|
-
|
|
83
|
-
# Writer config is in config/initializers/typelizer.rb
|
|
84
|
-
Typelizer::Generator.call(force: true)
|
|
85
|
-
|
|
86
|
-
# Post-process: convert `type Foo = {` to `interface Foo {` for declaration merging support.
|
|
87
|
-
# This lets SDK consumers extend generated types via `declare module '@spree/sdk' { interface Product { ... } }`.
|
|
88
|
-
api_root = Spree::Api::Engine.root
|
|
89
|
-
[
|
|
90
|
-
api_root.join('../../packages/sdk/src/types/generated'),
|
|
91
|
-
api_root.join('../../packages/admin-sdk/src/types/generated')
|
|
92
|
-
].each do |dir|
|
|
93
|
-
Dir[File.join(dir, '*.ts')].each do |file|
|
|
94
|
-
next if File.basename(file) == 'index.ts'
|
|
95
|
-
|
|
96
|
-
content = File.read(file)
|
|
97
|
-
updated = content.gsub(/^type (\w+) = \{/, 'interface \1 {')
|
|
98
|
-
File.write(file, updated) if updated != content
|
|
99
|
-
end
|
|
72
|
+
emails_dir = File.expand_path('../emails', __dir__)
|
|
73
|
+
Bundler.with_unbundled_env do
|
|
74
|
+
sh "cd #{emails_dir} && bundle exec rake typelizer:generate"
|
|
100
75
|
end
|
|
101
|
-
|
|
102
|
-
puts "Generated types → packages/sdk/src/types/generated/ & packages/admin-sdk/src/types/generated/"
|
|
103
76
|
end
|
|
104
77
|
|
|
105
78
|
desc 'Clean and regenerate TypeScript types'
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Admin
|
|
5
|
+
# Finds the editable email template a request is about, from its
|
|
6
|
+
# dotted key, for the language the request names.
|
|
7
|
+
module EmailTemplateLookup
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
scoped_resource :email_templates
|
|
12
|
+
|
|
13
|
+
before_action :load_email_template
|
|
14
|
+
|
|
15
|
+
rescue_from Spree::EmailTemplates::NoSampleRecord, with: :render_no_sample
|
|
16
|
+
rescue_from Liquid::Error, MRML::Error, with: :render_render_error
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
attr_reader :email_template
|
|
22
|
+
|
|
23
|
+
def load_email_template
|
|
24
|
+
@email_template = Spree::EmailTemplates::Entry.for_id(
|
|
25
|
+
current_store, params[:email_template_id] || params[:id], locale: language
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# A language code, or "any" for the version every language uses. Named
|
|
30
|
+
# `language` rather than `locale`, which picks the response's language.
|
|
31
|
+
def language
|
|
32
|
+
@language ||= params[:language].to_s.strip.presence || Spree::EmailTemplate::ANY_LOCALE
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def serialize_email_template(reload: false)
|
|
36
|
+
load_email_template if reload
|
|
37
|
+
Spree.api.admin_email_template_serializer.new(email_template, params: serializer_params).to_h
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def serializer_class
|
|
41
|
+
Spree.api.admin_email_template_serializer
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Renders the template as it stands after a workflow ran, or why the
|
|
45
|
+
# workflow refused.
|
|
46
|
+
def render_email_template_result(result, status: :ok)
|
|
47
|
+
return render_stale_draft if result.error&.value == :stale
|
|
48
|
+
return render_template_problems(result.value) if result.error&.value == :invalid_template
|
|
49
|
+
return render_result_error(result) unless result.success?
|
|
50
|
+
|
|
51
|
+
render json: serialize_email_template(reload: true), status: status
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Every published version of the template in the requested language.
|
|
55
|
+
def email_template_revisions
|
|
56
|
+
Spree::EmailTemplateRevision.where(
|
|
57
|
+
email_template: current_store.email_templates.for_key(email_template.key, language)
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# An unsaved subject and body are previewed only when sent, so an
|
|
62
|
+
# empty body still previews as empty. `branding` previews unsaved
|
|
63
|
+
# colors and font.
|
|
64
|
+
def preview_arguments
|
|
65
|
+
arguments = params.permit(:record_id, :subject, :body).to_h.symbolize_keys
|
|
66
|
+
arguments[:locale] = language
|
|
67
|
+
arguments[:email_key] = params[:email_key].to_s.tr('.', '/').presence
|
|
68
|
+
arguments[:branding] = params.fetch(:branding, {}).permit(*Spree::Emails::Branding.attribute_names).to_h
|
|
69
|
+
arguments
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Samples show a real record of the store (the latest order, a
|
|
73
|
+
# company), so previewing one needs permission to read it.
|
|
74
|
+
def authorize_sample_data!
|
|
75
|
+
missing = sample_classes.flat_map { |sample| Array(sample.try(:required_permissions)) }.uniq.
|
|
76
|
+
reject { |key| holds_permission?(key) }
|
|
77
|
+
return if missing.empty?
|
|
78
|
+
|
|
79
|
+
render_error(
|
|
80
|
+
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:access_denied],
|
|
81
|
+
message: I18n.t('spree.email_templates.sample_needs_permission', permissions: missing.to_sentence),
|
|
82
|
+
status: :forbidden,
|
|
83
|
+
details: { required_scope: missing.first }
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# A preview shows one email; publishing the layout or a partial
|
|
88
|
+
# renders every email, so it needs what all of their samples need.
|
|
89
|
+
def sample_classes
|
|
90
|
+
if action_name == 'create' && controller_name == 'publications' && !email_template.definition.email?
|
|
91
|
+
Spree.editable_email_templates.emails.map(&:sample_class)
|
|
92
|
+
else
|
|
93
|
+
[build_preview.email.sample_class]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def build_preview
|
|
98
|
+
Spree::EmailTemplates::Preview.new(store: current_store, key: email_template.key, strict: true, **preview_arguments)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def render_template_problems(problems)
|
|
102
|
+
problems = problems.map { |problem| problem.merge(email: problem[:email].tr('/', '.')) }
|
|
103
|
+
|
|
104
|
+
render_error(
|
|
105
|
+
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:email_template_invalid],
|
|
106
|
+
message: problems.map { |problem| problem[:message] }.uniq.to_sentence,
|
|
107
|
+
status: :unprocessable_content,
|
|
108
|
+
details: { problems: problems }
|
|
109
|
+
)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Attributed to the template being edited, whose lines the editor marks.
|
|
113
|
+
def render_render_error(error)
|
|
114
|
+
render_template_problems([{ email: email_template.id, message: error.message, line: error.try(:line_number) }])
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def render_no_sample(error)
|
|
118
|
+
render_error(
|
|
119
|
+
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:email_template_no_sample],
|
|
120
|
+
message: error.message,
|
|
121
|
+
status: :unprocessable_content
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def render_stale_draft
|
|
126
|
+
saved_by = email_template.draft&.updated_by&.actor_label
|
|
127
|
+
|
|
128
|
+
render_error(
|
|
129
|
+
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:email_template_stale],
|
|
130
|
+
message: I18n.t('spree.email_templates.stale_draft', name: saved_by || I18n.t('spree.email_templates.another_admin')),
|
|
131
|
+
status: :conflict,
|
|
132
|
+
details: { updated_by: saved_by }
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -44,7 +44,7 @@ module Spree
|
|
|
44
44
|
if secret_api_key && store_id_header && secret_api_key.store&.prefixed_id != store_id_header
|
|
45
45
|
render_error(
|
|
46
46
|
code: ErrorHandler::ERROR_CODES[:access_denied],
|
|
47
|
-
message:
|
|
47
|
+
message: I18n.t('spree.api.errors.store_mismatch'),
|
|
48
48
|
status: :forbidden
|
|
49
49
|
)
|
|
50
50
|
return
|
|
@@ -103,7 +103,7 @@ module Spree
|
|
|
103
103
|
def render_unknown_type
|
|
104
104
|
render_error(
|
|
105
105
|
code: self.class.unknown_type_error_code,
|
|
106
|
-
message:
|
|
106
|
+
message: I18n.t("spree.api.#{self.class.unknown_type_error_code}",
|
|
107
107
|
default: 'Unknown type'),
|
|
108
108
|
status: :unprocessable_content
|
|
109
109
|
)
|
|
@@ -57,6 +57,13 @@ module Spree
|
|
|
57
57
|
@cart = @cart.remove_out_of_stock_items!
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# Drops a batch coupon code the cart no longer holds. Unlike the line
|
|
61
|
+
# sweep this runs after writes too, since an API client may rely on
|
|
62
|
+
# write responses alone to learn why its discount went.
|
|
63
|
+
def sweep_unavailable_coupon_code!
|
|
64
|
+
@cart = @cart.remove_unavailable_coupon_code!
|
|
65
|
+
end
|
|
66
|
+
|
|
60
67
|
# Render what the checkout produced (for the complete action).
|
|
61
68
|
#
|
|
62
69
|
# A checkout spanning several sellers produced a group of orders rather
|
|
@@ -59,7 +59,7 @@ module Spree
|
|
|
59
59
|
if header && header.id != bound.id
|
|
60
60
|
render_error(
|
|
61
61
|
code: ErrorHandler::ERROR_CODES[:channel_mismatch],
|
|
62
|
-
message:
|
|
62
|
+
message: I18n.t('spree.api.errors.channel_mismatch'),
|
|
63
63
|
status: :unprocessable_entity
|
|
64
64
|
)
|
|
65
65
|
return
|
|
@@ -68,7 +68,7 @@ module Spree
|
|
|
68
68
|
unless bound.active?
|
|
69
69
|
render_error(
|
|
70
70
|
code: ErrorHandler::ERROR_CODES[:channel_inactive],
|
|
71
|
-
message:
|
|
71
|
+
message: I18n.t('spree.api.errors.channel_inactive'),
|
|
72
72
|
status: :forbidden
|
|
73
73
|
)
|
|
74
74
|
return
|
|
@@ -39,7 +39,7 @@ module Spree
|
|
|
39
39
|
def render_current_password_invalid
|
|
40
40
|
render_error(
|
|
41
41
|
code: ErrorHandler::ERROR_CODES[:current_password_invalid],
|
|
42
|
-
message:
|
|
42
|
+
message: I18n.t('spree.api.current_password_invalid'),
|
|
43
43
|
status: :unprocessable_content
|
|
44
44
|
)
|
|
45
45
|
end
|
|
@@ -74,6 +74,11 @@ module Spree
|
|
|
74
74
|
# Export errors
|
|
75
75
|
export_not_ready: 'export_not_ready',
|
|
76
76
|
|
|
77
|
+
# Email template errors
|
|
78
|
+
email_template_stale: 'email_template_stale',
|
|
79
|
+
email_template_invalid: 'email_template_invalid',
|
|
80
|
+
email_template_no_sample: 'email_template_no_sample',
|
|
81
|
+
|
|
77
82
|
# Rate limiting errors
|
|
78
83
|
rate_limit_exceeded: 'rate_limit_exceeded',
|
|
79
84
|
|
|
@@ -155,7 +160,7 @@ module Spree
|
|
|
155
160
|
# Workflows reject with a symbol naming the reason. Translate it,
|
|
156
161
|
# falling back to the symbol so a missing key is visible rather
|
|
157
162
|
# than silently blank.
|
|
158
|
-
render_error(code: code, message:
|
|
163
|
+
render_error(code: code, message: I18n.t("spree.#{error}", default: error.to_s.humanize), status: status)
|
|
159
164
|
else
|
|
160
165
|
render_error(code: code, message: error.to_s, status: status)
|
|
161
166
|
end
|
|
@@ -311,7 +316,7 @@ module Spree
|
|
|
311
316
|
model_name&.humanize || 'record'
|
|
312
317
|
end
|
|
313
318
|
|
|
314
|
-
|
|
319
|
+
I18n.t('spree.api.record_not_found', model: label)
|
|
315
320
|
end
|
|
316
321
|
|
|
317
322
|
# Extract clean model name from exception
|
|
@@ -11,6 +11,33 @@ module Spree
|
|
|
11
11
|
module HttpCaching
|
|
12
12
|
extend ActiveSupport::Concern
|
|
13
13
|
|
|
14
|
+
# Every request header that changes a publicly cacheable response.
|
|
15
|
+
# A shared cache (CDN, reverse proxy) keys stored responses on these,
|
|
16
|
+
# so a header missing here lets one visitor's response be served to
|
|
17
|
+
# another:
|
|
18
|
+
# - +Accept+ — response format
|
|
19
|
+
# - +X-Spree-Api-Key+ — the publishable key selects the store (and
|
|
20
|
+
# may bind a channel)
|
|
21
|
+
# - +Authorization+ — a customer JWT turns the response private
|
|
22
|
+
# (customer-group prices, gated catalog); without it a guest
|
|
23
|
+
# response could be served to a signed-in customer
|
|
24
|
+
# - +X-Spree-Country+ — selects the market (currency, prices, tax
|
|
25
|
+
# display, availability)
|
|
26
|
+
# - +X-Spree-Currency+ / +X-Spree-Locale+ — currency and language
|
|
27
|
+
# - +X-Spree-Channel+ — price hiding + channel-scoped visibility
|
|
28
|
+
#
|
|
29
|
+
# Query-param equivalents (+?country=+, +?currency=+, +?locale=+)
|
|
30
|
+
# are part of the URL and so already part of every cache key.
|
|
31
|
+
VARY_HEADERS = %w[
|
|
32
|
+
Accept
|
|
33
|
+
X-Spree-Api-Key
|
|
34
|
+
Authorization
|
|
35
|
+
X-Spree-Country
|
|
36
|
+
X-Spree-Currency
|
|
37
|
+
X-Spree-Locale
|
|
38
|
+
X-Spree-Channel
|
|
39
|
+
].freeze
|
|
40
|
+
|
|
14
41
|
included do
|
|
15
42
|
after_action :set_vary_headers
|
|
16
43
|
end
|
|
@@ -22,13 +49,11 @@ module Spree
|
|
|
22
49
|
current_user.nil?
|
|
23
50
|
end
|
|
24
51
|
|
|
25
|
-
# Set Vary
|
|
26
|
-
#
|
|
27
|
-
# serialized body (price hiding + channel-scoped visibility), so a shared
|
|
28
|
-
# cache must not serve one channel's guest response to another channel.
|
|
52
|
+
# Set Vary so a shared cache stores one guest response per
|
|
53
|
+
# store/market/currency/locale/channel combination (see VARY_HEADERS).
|
|
29
54
|
def set_vary_headers
|
|
30
55
|
if guest_user?
|
|
31
|
-
response.headers['Vary'] = '
|
|
56
|
+
response.headers['Vary'] = VARY_HEADERS.join(', ')
|
|
32
57
|
else
|
|
33
58
|
response.headers['Cache-Control'] = 'private, no-store'
|
|
34
59
|
end
|
|
@@ -70,12 +95,12 @@ module Spree
|
|
|
70
95
|
|
|
71
96
|
expires_in expires_in, public: true
|
|
72
97
|
|
|
73
|
-
# Use Rails' stale? which handles ETag and Last-Modified. The
|
|
74
|
-
# is folded into the ETag
|
|
75
|
-
#
|
|
76
|
-
# timestamp as before.
|
|
98
|
+
# Use Rails' stale? which handles ETag and Last-Modified. The request
|
|
99
|
+
# context (currency, locale, market, channel) is folded into the ETag
|
|
100
|
+
# so a revalidation never 304s across contexts; Last-Modified mirrors
|
|
101
|
+
# the resource's own timestamp as before.
|
|
77
102
|
stale?(
|
|
78
|
-
etag: [resource, cache_channel_fragment],
|
|
103
|
+
etag: [resource, current_currency, current_locale, cache_market_fragment, cache_channel_fragment],
|
|
79
104
|
last_modified: resource.try(:updated_at),
|
|
80
105
|
public: true
|
|
81
106
|
)
|
|
@@ -84,7 +109,7 @@ module Spree
|
|
|
84
109
|
private
|
|
85
110
|
|
|
86
111
|
# Build a cache key for a collection
|
|
87
|
-
# Includes: latest updated_at, total count, query params, pagination, expand, currency, locale, channel
|
|
112
|
+
# Includes: latest updated_at, total count, query params, pagination, expand, currency, locale, market, channel
|
|
88
113
|
def collection_cache_key(collection)
|
|
89
114
|
# For ActiveRecord collections use updated_at, for plain arrays use store's updated_at as proxy
|
|
90
115
|
latest_updated_at = if collection.first&.respond_to?(:updated_at)
|
|
@@ -103,12 +128,20 @@ module Spree
|
|
|
103
128
|
params[:limit],
|
|
104
129
|
current_currency,
|
|
105
130
|
current_locale,
|
|
131
|
+
cache_market_fragment,
|
|
106
132
|
cache_channel_fragment
|
|
107
133
|
]
|
|
108
134
|
|
|
109
135
|
parts.compact.join('/')
|
|
110
136
|
end
|
|
111
137
|
|
|
138
|
+
# Identifies the resolved market (from X-Spree-Country / ?country=).
|
|
139
|
+
# The market drives tax display and availability as well as currency,
|
|
140
|
+
# so it is part of the guest cache identity.
|
|
141
|
+
def cache_market_fragment
|
|
142
|
+
Spree::Current.market&.id
|
|
143
|
+
end
|
|
144
|
+
|
|
112
145
|
# Identifies the resolved channel for cache-key purposes. The channel
|
|
113
146
|
# changes the serialized body (price hiding + channel-scoped visibility),
|
|
114
147
|
# so it must be part of the guest cache identity. Uses the same
|
|
@@ -29,6 +29,8 @@ module Spree
|
|
|
29
29
|
return
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
return yield if caller_identity.nil?
|
|
33
|
+
|
|
32
34
|
cache_key = idempotency_cache_key(key)
|
|
33
35
|
cached = Rails.cache.read(cache_key)
|
|
34
36
|
|
|
@@ -36,7 +38,7 @@ module Spree
|
|
|
36
38
|
if cached[:fingerprint] != request_fingerprint
|
|
37
39
|
render_error(
|
|
38
40
|
code: ErrorHandler::ERROR_CODES[:idempotency_key_reused],
|
|
39
|
-
message:
|
|
41
|
+
message: I18n.t('spree.idempotency_key_reused'),
|
|
40
42
|
status: :unprocessable_content
|
|
41
43
|
)
|
|
42
44
|
return
|
|
@@ -66,17 +68,30 @@ module Spree
|
|
|
66
68
|
MUTATING_METHODS.include?(request.method)
|
|
67
69
|
end
|
|
68
70
|
|
|
71
|
+
def caller_identity
|
|
72
|
+
return @caller_identity if defined?(@caller_identity)
|
|
73
|
+
|
|
74
|
+
credentials = []
|
|
75
|
+
|
|
76
|
+
credentials << ['secret_key', Spree::ApiKey.compute_token_digest(extract_api_key)] if secret_key_request?
|
|
77
|
+
|
|
78
|
+
bearer_token = extract_token
|
|
79
|
+
credentials << ['bearer', Digest::SHA256.hexdigest(bearer_token)] if bearer_token.present?
|
|
80
|
+
|
|
81
|
+
credentials << ['order_token', Digest::SHA256.hexdigest(order_token)] if order_token.present?
|
|
82
|
+
|
|
83
|
+
@caller_identity = credentials.presence
|
|
84
|
+
end
|
|
85
|
+
|
|
69
86
|
def idempotency_cache_key(key)
|
|
70
|
-
credential = request.headers['X-Spree-Api-Key'].presence ||
|
|
71
|
-
spree_current_user&.id ||
|
|
72
|
-
request.remote_ip
|
|
73
87
|
# The resolved store partitions the namespace: a staff JWT spans
|
|
74
88
|
# stores, and replaying one store's cached response for a request
|
|
75
89
|
# aimed at another would cross store boundaries. The resolved
|
|
76
90
|
# store — not the raw header — so a header naming the default store
|
|
77
91
|
# and no header at all land in the same partition, as they resolve
|
|
78
92
|
# to the same store.
|
|
79
|
-
|
|
93
|
+
digest = Digest::SHA256.hexdigest([*caller_identity.flatten, current_store&.id, key].join("\0"))
|
|
94
|
+
"spree:idempotency:#{digest}"
|
|
80
95
|
end
|
|
81
96
|
|
|
82
97
|
def request_fingerprint
|
|
@@ -45,7 +45,7 @@ module Spree
|
|
|
45
45
|
# `return_line_items`).
|
|
46
46
|
def render_invalid_items
|
|
47
47
|
errors = ActiveModel::Errors.new(@resource || model_class.new)
|
|
48
|
-
errors.add(:base, :invalid_items, message:
|
|
48
|
+
errors.add(:base, :invalid_items, message: I18n.t('spree.errors.messages.items_not_a_list'))
|
|
49
49
|
render_validation_error(errors)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
@@ -29,7 +29,7 @@ module Spree
|
|
|
29
29
|
if order.is_a?(Spree::Cart) && order.completion_claimed?
|
|
30
30
|
next render_error(
|
|
31
31
|
code: 'completion_in_progress',
|
|
32
|
-
message:
|
|
32
|
+
message: I18n.t('spree.cart_completion_in_progress'),
|
|
33
33
|
status: :conflict
|
|
34
34
|
)
|
|
35
35
|
end
|
|
@@ -51,7 +51,7 @@ module Spree
|
|
|
51
51
|
Rails.error.report(exception, context: { order_id: (@order || @parent || @cart)&.id }, source: 'spree.api.v3')
|
|
52
52
|
render_error(
|
|
53
53
|
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:cart_already_updated],
|
|
54
|
-
message:
|
|
54
|
+
message: I18n.t('spree.cart_already_updated'),
|
|
55
55
|
status: :conflict
|
|
56
56
|
)
|
|
57
57
|
end
|
|
@@ -28,11 +28,7 @@ module Spree
|
|
|
28
28
|
**resource_permitted_attributes.index_with { |key| delivery_params[key] }
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
render json: serialize_resource(result.value), status: :created
|
|
33
|
-
else
|
|
34
|
-
render_result_error(result)
|
|
35
|
-
end
|
|
31
|
+
render_result(result, status: :created)
|
|
36
32
|
end
|
|
37
33
|
end
|
|
38
34
|
|
|
@@ -45,11 +45,7 @@ module Spree
|
|
|
45
45
|
**fulfill_workflow_options
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
render json: serialize_resource(result.value)
|
|
50
|
-
else
|
|
51
|
-
render_result_error(result)
|
|
52
|
-
end
|
|
48
|
+
render_result(result)
|
|
53
49
|
end
|
|
54
50
|
end
|
|
55
51
|
|
|
@@ -60,11 +56,7 @@ module Spree
|
|
|
60
56
|
with_order_lock do
|
|
61
57
|
result = Spree.fulfillment_cancel_workflow.call(fulfillment: @resource)
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
render json: serialize_resource(result.value)
|
|
65
|
-
else
|
|
66
|
-
render_result_error(result)
|
|
67
|
-
end
|
|
59
|
+
render_result(result)
|
|
68
60
|
end
|
|
69
61
|
end
|
|
70
62
|
|
|
@@ -28,11 +28,7 @@ module Spree
|
|
|
28
28
|
def run_workflow(workflow, **arguments)
|
|
29
29
|
result = workflow.call(workflow_record_key => @resource, **arguments)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
render json: serialize_resource(result.value)
|
|
33
|
-
else
|
|
34
|
-
render_result_error(result)
|
|
35
|
-
end
|
|
31
|
+
render_result(result)
|
|
36
32
|
end
|
|
37
33
|
|
|
38
34
|
# @return [Symbol] the keyword this entity's workflows take it under
|
|
@@ -63,11 +59,7 @@ module Spree
|
|
|
63
59
|
**arguments
|
|
64
60
|
)
|
|
65
61
|
|
|
66
|
-
|
|
67
|
-
render json: serialize_resource(result.value), status: :created
|
|
68
|
-
else
|
|
69
|
-
render_result_error(result)
|
|
70
|
-
end
|
|
62
|
+
render_result(result, status: :created)
|
|
71
63
|
end
|
|
72
64
|
end
|
|
73
65
|
end
|
|
@@ -31,7 +31,7 @@ module Spree
|
|
|
31
31
|
stream_shipping_label(@resource) do
|
|
32
32
|
render_error(
|
|
33
33
|
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:validation_error],
|
|
34
|
-
message:
|
|
34
|
+
message: I18n.t('spree.shipping_labels.errors.no_file_url'),
|
|
35
35
|
status: :unprocessable_content
|
|
36
36
|
)
|
|
37
37
|
end
|
|
@@ -45,7 +45,7 @@ module Spree
|
|
|
45
45
|
unless @resource.uploaded?
|
|
46
46
|
return render_error(
|
|
47
47
|
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:validation_error],
|
|
48
|
-
message:
|
|
48
|
+
message: I18n.t('spree.shipping_labels.errors.purchased_not_deletable'),
|
|
49
49
|
status: :unprocessable_content
|
|
50
50
|
)
|
|
51
51
|
end
|
|
@@ -104,11 +104,7 @@ module Spree
|
|
|
104
104
|
**label_permitted_keys.index_with { |key| label_params[key] }
|
|
105
105
|
)
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
render json: serialize_resource(result.value), status: :created
|
|
109
|
-
else
|
|
110
|
-
render_result_error(result)
|
|
111
|
-
end
|
|
107
|
+
render_result(result, status: :created)
|
|
112
108
|
end
|
|
113
109
|
end
|
|
114
110
|
|
|
@@ -117,7 +113,7 @@ module Spree
|
|
|
117
113
|
def render_invalid_signature
|
|
118
114
|
render_error(
|
|
119
115
|
code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:parameter_invalid],
|
|
120
|
-
message:
|
|
116
|
+
message: I18n.t('spree.shipping_labels.errors.file_required'),
|
|
121
117
|
status: :unprocessable_content
|
|
122
118
|
)
|
|
123
119
|
end
|
|
@@ -6,6 +6,7 @@ module Spree
|
|
|
6
6
|
# branches answer different audiences, but the frontend permission model
|
|
7
7
|
# is one implementation, so its input has to be too.
|
|
8
8
|
#
|
|
9
|
+
# - Subjects are short names (`product`), not Ruby class names.
|
|
9
10
|
# - Rule order is preserved so the frontend matcher can apply
|
|
10
11
|
# CanCanCan's "last matching rule wins" semantics.
|
|
11
12
|
# - Per-record conditions are NOT serialized (they often reference
|
|
@@ -23,12 +24,19 @@ module Spree
|
|
|
23
24
|
{
|
|
24
25
|
allow: rule.base_behavior,
|
|
25
26
|
actions: Array(rule.actions).map(&:to_s),
|
|
26
|
-
subjects: Array(rule.subjects).map { |subject| subject
|
|
27
|
+
subjects: Array(rule.subjects).map { |subject| serialize_subject(subject) },
|
|
27
28
|
has_conditions: rule_has_conditions?(rule)
|
|
28
29
|
}
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
|
|
33
|
+
# A model subject travels as its short name (`product`, `customer`),
|
|
34
|
+
# never the Ruby class; `all` and symbol subjects (`dashboard`) pass
|
|
35
|
+
# through as they are.
|
|
36
|
+
def serialize_subject(subject)
|
|
37
|
+
subject.is_a?(Class) ? Spree::Base.polymorphic_api_type(subject.name) : subject.to_s
|
|
38
|
+
end
|
|
39
|
+
|
|
32
40
|
def serialize_permission_keys(ability)
|
|
33
41
|
ability.respond_to?(:permission_keys) ? ability.permission_keys : []
|
|
34
42
|
end
|
|
@@ -5,9 +5,10 @@ module Spree
|
|
|
5
5
|
# The products a storefront buyer may see: available now (or on
|
|
6
6
|
# pre-order) in the current currency, narrowed to the catalogs their
|
|
7
7
|
# company, customer group or channel resolve to. The product listing
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
8
|
+
# and wishlist items read through it, so an id cannot reach what the
|
|
9
|
+
# listing would never show. Carts narrow through
|
|
10
|
+
# {Spree::Cart#orderable_variants} instead, which asks the same
|
|
11
|
+
# catalogs about the cart's own buyer and company.
|
|
11
12
|
module StorefrontProducts
|
|
12
13
|
extend ActiveSupport::Concern
|
|
13
14
|
|
|
@@ -26,7 +27,7 @@ module Spree
|
|
|
26
27
|
|
|
27
28
|
# @return [ActiveRecord::Relation<Spree::Variant>]
|
|
28
29
|
def storefront_variants
|
|
29
|
-
Spree::Variant.
|
|
30
|
+
Spree::Variant.for_products(storefront_products)
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
end
|