spree_api 6.0.0.rc1 → 6.0.0.rc3
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 +0 -17
- data/app/controllers/concerns/spree/api/v3/admin/product_membership.rb +10 -0
- data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +26 -4
- data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +14 -28
- data/app/controllers/concerns/spree/api/v3/admin/validation_details.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +3 -2
- data/app/controllers/concerns/spree/api/v3/channel_resolution.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/company_address_writes.rb +3 -1
- data/app/controllers/concerns/spree/api/v3/error_handler.rb +48 -2
- data/app/controllers/concerns/spree/api/v3/file_uploads.rb +35 -0
- data/app/controllers/concerns/spree/api/v3/money_params.rb +52 -0
- data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +1 -5
- data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +6 -6
- data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +1 -4
- data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +1 -5
- data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +1 -4
- data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +5 -21
- data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +5 -0
- data/app/controllers/concerns/spree/api/v3/purchase_serialization.rb +26 -0
- data/app/controllers/concerns/spree/api/v3/request_params.rb +65 -0
- data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +8 -3
- data/app/controllers/concerns/spree/api/v3/strict_money_params.rb +94 -0
- data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +10 -1
- data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +8 -1
- data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +15 -7
- data/app/controllers/spree/api/v3/admin/base_controller.rb +1 -0
- data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +3 -1
- data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +7 -5
- data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +60 -33
- data/app/controllers/spree/api/v3/admin/categories/products_controller.rb +4 -1
- data/app/controllers/spree/api/v3/admin/categories_controller.rb +40 -20
- data/app/controllers/spree/api/v3/admin/channels_controller.rb +39 -6
- data/app/controllers/spree/api/v3/admin/claim_reasons_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +4 -1
- data/app/controllers/spree/api/v3/admin/collections_controller.rb +44 -15
- data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +60 -12
- data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +11 -0
- data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +9 -1
- data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +19 -18
- data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +6 -1
- data/app/controllers/spree/api/v3/admin/companies_controller.rb +17 -3
- data/app/controllers/spree/api/v3/admin/countries_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +21 -11
- data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +12 -5
- data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +9 -1
- data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +12 -7
- data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +11 -9
- data/app/controllers/spree/api/v3/admin/customers/tax_identifiers_controller.rb +6 -1
- data/app/controllers/spree/api/v3/admin/customers_controller.rb +35 -7
- data/app/controllers/spree/api/v3/admin/data_requests_controller.rb +8 -0
- data/app/controllers/spree/api/v3/admin/delivery_method_rules_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +15 -7
- data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +92 -57
- data/app/controllers/spree/api/v3/admin/delivery_profiles/origin_groups_controller.rb +8 -1
- data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +13 -1
- data/app/controllers/spree/api/v3/admin/delivery_zones_controller.rb +21 -5
- data/app/controllers/spree/api/v3/admin/email_templates/drafts_controller.rb +14 -1
- data/app/controllers/spree/api/v3/admin/email_templates/previews_controller.rb +4 -0
- data/app/controllers/spree/api/v3/admin/email_templates/publications_controller.rb +7 -0
- data/app/controllers/spree/api/v3/admin/email_templates/restorations_controller.rb +8 -0
- data/app/controllers/spree/api/v3/admin/email_templates/test_emails_controller.rb +4 -0
- data/app/controllers/spree/api/v3/admin/exports_controller.rb +23 -6
- data/app/controllers/spree/api/v3/admin/files_controller.rb +29 -0
- data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +20 -1
- data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +19 -1
- data/app/controllers/spree/api/v3/admin/imports_controller.rb +36 -9
- data/app/controllers/spree/api/v3/admin/integrations_controller.rb +13 -1
- data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +9 -2
- data/app/controllers/spree/api/v3/admin/invitations_controller.rb +8 -1
- data/app/controllers/spree/api/v3/admin/locales_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/markets_controller.rb +30 -9
- data/app/controllers/spree/api/v3/admin/me_controller.rb +12 -3
- data/app/controllers/spree/api/v3/admin/media_controller.rb +22 -9
- data/app/controllers/spree/api/v3/admin/media_library_controller.rb +4 -0
- data/app/controllers/spree/api/v3/admin/option_types_controller.rb +24 -7
- data/app/controllers/spree/api/v3/admin/order_cancellation_reasons_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +13 -1
- data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +39 -1
- data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +19 -1
- data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +29 -5
- data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +36 -1
- data/app/controllers/spree/api/v3/admin/orders/fees_controller.rb +22 -1
- data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +66 -7
- data/app/controllers/spree/api/v3/admin/orders/gift_cards_controller.rb +6 -2
- data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +11 -1
- data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +35 -2
- data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +16 -5
- data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +6 -0
- data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +37 -1
- data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +6 -3
- data/app/controllers/spree/api/v3/admin/orders_controller.rb +74 -60
- data/app/controllers/spree/api/v3/admin/package_types_controller.rb +30 -5
- data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +17 -0
- data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +38 -22
- data/app/controllers/spree/api/v3/admin/policies_controller.rb +8 -4
- data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +27 -15
- data/app/controllers/spree/api/v3/admin/prices_controller.rb +51 -4
- data/app/controllers/spree/api/v3/admin/product_types_controller.rb +25 -8
- data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +27 -10
- data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +9 -14
- data/app/controllers/spree/api/v3/admin/products_controller.rb +121 -70
- data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +11 -2
- data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +10 -1
- data/app/controllers/spree/api/v3/admin/promotions_controller.rb +50 -14
- data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +54 -7
- data/app/controllers/spree/api/v3/admin/refund_reasons_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/reporting/saved_reports_controller.rb +9 -1
- data/app/controllers/spree/api/v3/admin/reporting_controller.rb +34 -0
- data/app/controllers/spree/api/v3/admin/resource_controller.rb +1 -0
- data/app/controllers/spree/api/v3/admin/return_reasons_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/roles_controller.rb +13 -1
- data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +6 -0
- data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +15 -0
- data/app/controllers/spree/api/v3/admin/seller_requirements_controller.rb +32 -6
- data/app/controllers/spree/api/v3/admin/sellers_controller.rb +75 -22
- data/app/controllers/spree/api/v3/admin/setup_controller.rb +54 -15
- data/app/controllers/spree/api/v3/admin/stock_levels_controller.rb +38 -9
- data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +41 -9
- data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +48 -7
- data/app/controllers/spree/api/v3/admin/store_controller.rb +122 -53
- data/app/controllers/spree/api/v3/admin/store_credits_controller.rb +1 -7
- data/app/controllers/spree/api/v3/admin/suppliers_controller.rb +16 -6
- data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +7 -4
- data/app/controllers/spree/api/v3/admin/tax_rates_controller.rb +21 -3
- data/app/controllers/spree/api/v3/admin/tracking_carriers_controller.rb +4 -0
- data/app/controllers/spree/api/v3/admin/translations/batches_controller.rb +17 -9
- data/app/controllers/spree/api/v3/admin/translations_controller.rb +4 -0
- data/app/controllers/spree/api/v3/admin/translations_coverage_controller.rb +5 -0
- data/app/controllers/spree/api/v3/admin/updates_controller.rb +39 -0
- data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +23 -1
- data/app/controllers/spree/api/v3/base_controller.rb +2 -0
- data/app/controllers/spree/api/v3/resource_controller.rb +63 -10
- data/app/controllers/spree/api/v3/seller/auth_controller.rb +8 -0
- data/app/controllers/spree/api/v3/seller/base_controller.rb +1 -0
- data/app/controllers/spree/api/v3/seller/countries_controller.rb +2 -2
- data/app/controllers/spree/api/v3/seller/delivery_methods_controller.rb +49 -60
- data/app/controllers/spree/api/v3/seller/exports_controller.rb +18 -1
- data/app/controllers/spree/api/v3/seller/files_controller.rb +27 -0
- data/app/controllers/spree/api/v3/seller/imports_controller.rb +25 -9
- data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +9 -1
- data/app/controllers/spree/api/v3/seller/me_controller.rb +14 -3
- data/app/controllers/spree/api/v3/seller/onboarding_controller.rb +11 -0
- data/app/controllers/spree/api/v3/seller/orders/claims_controller.rb +35 -0
- data/app/controllers/spree/api/v3/seller/orders/deliveries_controller.rb +12 -0
- data/app/controllers/spree/api/v3/seller/orders/exchanges_controller.rb +33 -0
- data/app/controllers/spree/api/v3/seller/orders/fulfillments_controller.rb +28 -2
- data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +22 -1
- data/app/controllers/spree/api/v3/seller/orders/notes_controller.rb +8 -1
- data/app/controllers/spree/api/v3/seller/orders/returns_controller.rb +32 -0
- data/app/controllers/spree/api/v3/seller/orders_controller.rb +35 -14
- data/app/controllers/spree/api/v3/seller/package_types_controller.rb +21 -9
- data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +10 -0
- data/app/controllers/spree/api/v3/seller/policies_controller.rb +12 -4
- data/app/controllers/spree/api/v3/seller/products_controller.rb +114 -28
- data/app/controllers/spree/api/v3/seller/profile_controller.rb +33 -10
- data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +12 -5
- data/app/controllers/spree/api/v3/seller/resource_controller.rb +12 -0
- data/app/controllers/spree/api/v3/seller/stock_locations_controller.rb +44 -13
- data/app/controllers/spree/api/v3/seller/tax_identifiers_controller.rb +10 -1
- data/app/controllers/spree/api/v3/seller/team_controller.rb +4 -0
- data/app/controllers/spree/api/v3/store/auth_controller.rb +10 -0
- data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +8 -1
- data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +10 -2
- data/app/controllers/spree/api/v3/store/carts/gift_cards_controller.rb +8 -1
- data/app/controllers/spree/api/v3/store/carts/items_controller.rb +17 -5
- data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +20 -6
- data/app/controllers/spree/api/v3/store/carts/payments_controller.rb +11 -0
- data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +24 -26
- data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +19 -1
- data/app/controllers/spree/api/v3/store/carts/tax_identifiers_controller.rb +5 -1
- data/app/controllers/spree/api/v3/store/carts_controller.rb +54 -47
- data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +12 -4
- data/app/controllers/spree/api/v3/store/companies/members_controller.rb +4 -0
- data/app/controllers/spree/api/v3/store/companies_controller.rb +5 -1
- data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +9 -1
- data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +8 -7
- data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +5 -0
- data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +17 -0
- data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +10 -5
- data/app/controllers/spree/api/v3/store/customer/tax_identifiers_controller.rb +5 -1
- data/app/controllers/spree/api/v3/store/customers_controller.rb +28 -2
- data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +22 -0
- data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +11 -2
- data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +10 -1
- data/app/controllers/spree/api/v3/store/orders_controller.rb +47 -10
- data/app/controllers/spree/api/v3/store/products_controller.rb +8 -0
- data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +10 -4
- data/app/controllers/spree/api/v3/store/wishlists_controller.rb +12 -4
- data/app/request_schemas/spree/api/v3/address_request_schema.rb +27 -0
- data/app/request_schemas/spree/api/v3/admin/address_request_schema.rb +13 -0
- data/app/request_schemas/spree/api/v3/admin/bulk_tags_request_schema.rb +17 -0
- data/app/request_schemas/spree/api/v3/admin/catalog_order_minimum_request_schema.rb +17 -0
- data/app/request_schemas/spree/api/v3/admin/email_template_language_request_schema.rb +17 -0
- data/app/request_schemas/spree/api/v3/admin/email_template_preview_request_schema.rb +32 -0
- data/app/request_schemas/spree/api/v3/admin/price_adjustment_tier_request_schema.rb +21 -0
- data/app/request_schemas/spree/api/v3/admin/price_list_price_request_schema.rb +21 -0
- data/app/request_schemas/spree/api/v3/admin/price_list_rule_request_schema.rb +19 -0
- data/app/request_schemas/spree/api/v3/admin/product_membership_reposition_request_schema.rb +17 -0
- data/app/request_schemas/spree/api/v3/admin/promotion_action_calculator_request_schema.rb +18 -0
- data/app/request_schemas/spree/api/v3/admin/promotion_action_line_item_request_schema.rb +15 -0
- data/app/request_schemas/spree/api/v3/admin/promotion_action_request_schema.rb +19 -0
- data/app/request_schemas/spree/api/v3/admin/promotion_rule_request_schema.rb +22 -0
- data/app/request_schemas/spree/api/v3/admin/reason_request_schema.rb +14 -0
- data/app/request_schemas/spree/api/v3/admin/tax_identifier_request_schema.rb +15 -0
- data/app/request_schemas/spree/api/v3/custom_field_value_request_schema.rb +15 -0
- data/app/request_schemas/spree/api/v3/file_upload_request_schema.rb +20 -0
- data/app/request_schemas/spree/api/v3/media_request_schema.rb +27 -0
- data/app/request_schemas/spree/api/v3/price_request_schema.rb +17 -0
- data/app/request_schemas/spree/api/v3/stock_level_request_schema.rb +18 -0
- data/app/request_schemas/spree/api/v3/store/address_request_schema.rb +31 -0
- data/app/request_schemas/spree/api/v3/tax_identifier_request_schema.rb +18 -0
- data/app/request_schemas/spree/api/v3/variant_option_request_schema.rb +13 -0
- data/app/request_schemas/spree/api/v3/variant_request_schema.rb +52 -0
- data/app/serializers/concerns/spree/api/v3/purchase_summary.rb +48 -0
- data/app/serializers/spree/api/v3/address_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/admin/address_serializer.rb +3 -0
- data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/cart_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +3 -2
- data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +3 -4
- data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +4 -3
- data/app/serializers/spree/api/v3/admin/channel_serializer.rb +5 -7
- data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +7 -0
- data/app/serializers/spree/api/v3/admin/claim_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +7 -18
- data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +7 -11
- data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +0 -2
- data/app/serializers/spree/api/v3/admin/country_serializer.rb +4 -0
- data/app/serializers/spree/api/v3/admin/customer_serializer.rb +3 -7
- data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +0 -2
- data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +14 -10
- data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +9 -1
- data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +8 -0
- data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/admin/fee_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/file_upload_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/file_upload_target_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +13 -11
- data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +3 -3
- data/app/serializers/spree/api/v3/admin/import_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/integration_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +12 -12
- data/app/serializers/spree/api/v3/admin/locale_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/admin/market_serializer.rb +3 -0
- data/app/serializers/spree/api/v3/admin/media_serializer.rb +3 -2
- data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +33 -33
- data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +1 -4
- data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -3
- data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +8 -9
- data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +3 -6
- data/app/serializers/spree/api/v3/admin/price_history_serializer.rb +6 -2
- data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +1 -5
- data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/admin/price_serializer.rb +4 -0
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +4 -6
- data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +0 -2
- data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +5 -11
- data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +4 -4
- data/app/serializers/spree/api/v3/admin/refund_serializer.rb +7 -3
- data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +9 -2
- data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +8 -0
- data/app/serializers/spree/api/v3/admin/return_serializer.rb +8 -4
- data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +15 -10
- data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +3 -5
- data/app/serializers/spree/api/v3/admin/seller_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +7 -8
- data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +4 -4
- data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +3 -0
- data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +9 -4
- data/app/serializers/spree/api/v3/admin/store_serializer.rb +17 -98
- data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +2 -12
- data/app/serializers/spree/api/v3/admin/update_status_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/admin/variant_serializer.rb +7 -3
- data/app/serializers/spree/api/v3/base_serializer.rb +112 -7
- data/app/serializers/spree/api/v3/cart_serializer.rb +16 -30
- data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +5 -13
- data/app/serializers/spree/api/v3/claim_serializer.rb +2 -3
- data/app/serializers/spree/api/v3/country_serializer.rb +2 -1
- data/app/serializers/spree/api/v3/currency_serializer.rb +9 -1
- data/app/serializers/spree/api/v3/customer_serializer.rb +3 -2
- data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +8 -12
- data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/discount_serializer.rb +4 -1
- data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +2 -8
- data/app/serializers/spree/api/v3/exchange_serializer.rb +2 -3
- data/app/serializers/spree/api/v3/file_upload_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/file_upload_target_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/gift_card_batch_serializer.rb +2 -4
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +4 -2
- data/app/serializers/spree/api/v3/import_serializer.rb +0 -12
- data/app/serializers/spree/api/v3/line_item_serializer.rb +15 -5
- data/app/serializers/spree/api/v3/locale_serializer.rb +3 -1
- data/app/serializers/spree/api/v3/market_serializer.rb +5 -5
- data/app/serializers/spree/api/v3/media_serializer.rb +7 -2
- data/app/serializers/spree/api/v3/order_group_serializer.rb +12 -4
- data/app/serializers/spree/api/v3/order_serializer.rb +5 -23
- data/app/serializers/spree/api/v3/payment_session_serializer.rb +2 -4
- data/app/serializers/spree/api/v3/price_history_serializer.rb +11 -6
- data/app/serializers/spree/api/v3/price_serializer.rb +17 -10
- data/app/serializers/spree/api/v3/product_filter_price_range_serializer.rb +10 -4
- data/app/serializers/spree/api/v3/product_serializer.rb +3 -3
- data/app/serializers/spree/api/v3/refund_serializer.rb +8 -5
- data/app/serializers/spree/api/v3/return_line_item_serializer.rb +3 -11
- data/app/serializers/spree/api/v3/return_serializer.rb +3 -6
- data/app/serializers/spree/api/v3/seller/address_serializer.rb +12 -0
- data/app/serializers/spree/api/v3/seller/balance_serializer.rb +15 -10
- data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +7 -0
- data/app/serializers/spree/api/v3/seller/claim_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/seller/country_serializer.rb +19 -0
- data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +4 -8
- data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +9 -8
- data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +5 -0
- data/app/serializers/spree/api/v3/seller/file_upload_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/seller/file_upload_target_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/seller/import_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/seller/media_serializer.rb +2 -5
- data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +4 -3
- data/app/serializers/spree/api/v3/seller/order_serializer.rb +16 -16
- data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +8 -9
- data/app/serializers/spree/api/v3/seller/payout_serializer.rb +2 -4
- data/app/serializers/spree/api/v3/seller/price_history_serializer.rb +12 -0
- data/app/serializers/spree/api/v3/seller/price_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/seller/product_serializer.rb +2 -0
- data/app/serializers/spree/api/v3/seller/profile_serializer.rb +7 -7
- data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +8 -0
- data/app/serializers/spree/api/v3/seller/return_serializer.rb +8 -5
- data/app/serializers/spree/api/v3/seller/state_serializer.rb +10 -0
- data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +3 -0
- data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +6 -7
- data/app/serializers/spree/api/v3/seller/variant_serializer.rb +8 -4
- data/app/serializers/spree/api/v3/stock_location_serializer.rb +8 -1
- data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/store_credit_serializer.rb +3 -5
- data/app/serializers/spree/api/v3/tax_line_serializer.rb +2 -4
- data/app/serializers/spree/api/v3/variant_serializer.rb +3 -3
- data/app/services/spree/api/v3/filter_predicates.rb +29 -0
- data/app/services/spree/api/v3/filter_table.rb +337 -0
- data/app/services/spree/api/v3/filters_aggregator.rb +2 -2
- data/app/services/spree/api/v3/request_schema.rb +430 -0
- data/app/services/spree/webhooks/deliver_webhook.rb +7 -3
- data/config/initializers/typelizer.rb +1 -1
- data/config/routes.rb +5 -3
- data/lib/spree/api/configuration.rb +5 -0
- data/lib/spree/api/dependencies.rb +7 -6
- data/lib/spree/api/middleware/request_size_limit.rb +24 -3
- data/lib/spree/api/openapi/filter_documentation.rb +136 -0
- data/lib/spree/api/openapi/schema_helper.rb +126 -80
- data/lib/spree/api/preference_families.rb +46 -0
- data/lib/spree/api/preference_types.rb +138 -0
- data/lib/spree/api/typelizer_generation.rb +4 -0
- data/lib/tasks/filters.rake +12 -0
- data/lib/typelizer/open_enums.rb +10 -0
- metadata +60 -10
- data/app/controllers/concerns/spree/api/v3/address_params.rb +0 -17
- data/app/controllers/concerns/spree/api/v3/direct_uploads.rb +0 -35
- data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +0 -54
- data/app/controllers/spree/api/v3/seller/direct_uploads_controller.rb +0 -21
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
# What one write endpoint accepts, declared once. The controller permits
|
|
5
|
+
# from it, the API reference documents it, and the SDK request types are
|
|
6
|
+
# generated from the reference, so the three cannot disagree.
|
|
7
|
+
#
|
|
8
|
+
# request_params :product do |body|
|
|
9
|
+
# body.attribute :name, :string, required: true, on: :create
|
|
10
|
+
# body.attribute :status, :string, choices: Spree::Product::STATUSES, open: true
|
|
11
|
+
# body.attribute :category_ids, :array, of: :id
|
|
12
|
+
# body.attribute :metadata, :hash
|
|
13
|
+
# body.attribute :prices, :array, of: Spree::Api::V3::PriceRequestSchema
|
|
14
|
+
# body.attribute :options, :array do |option|
|
|
15
|
+
# option.attribute :name, :string, required: true
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# The vocabulary is the `preference` one: a type symbol, `of:` for what
|
|
20
|
+
# an `:array` holds, `choices:` for a closed list (`open: true` when
|
|
21
|
+
# extensions may extend it), `:hash` for any keys. `required: true` is
|
|
22
|
+
# required on both actions; add `on: :create` to require it when
|
|
23
|
+
# creating only. `only: :create` (or `:update`) accepts the field on one
|
|
24
|
+
# action alone. `permit: false` documents a field the controller reads
|
|
25
|
+
# from the raw params itself. `format:` documents a string's format
|
|
26
|
+
# (`email`, `uri`). `deprecated: 'Use country_code. Removed in 6.1.'`
|
|
27
|
+
# keeps a field working while the API reference and the SDK types flag it.
|
|
28
|
+
class RequestSchema
|
|
29
|
+
KINDS = {
|
|
30
|
+
string: { type: :string },
|
|
31
|
+
integer: { type: :integer },
|
|
32
|
+
# Measurements a client sends as JSON numbers (weights, dimensions,
|
|
33
|
+
# coordinates). Money is never a number: use `decimal`.
|
|
34
|
+
number: { type: :number },
|
|
35
|
+
# Amounts, rates and quantities with decimals travel as canonical
|
|
36
|
+
# decimal strings, never JSON numbers (see Spree::Money::Rounding).
|
|
37
|
+
decimal: { type: :string, format: :decimal, pattern: '^-?\d+(\.\d+)?$' },
|
|
38
|
+
boolean: { type: :boolean },
|
|
39
|
+
date: { type: :string, format: :date },
|
|
40
|
+
datetime: { type: :string, format: :'date-time' },
|
|
41
|
+
id: { type: :string },
|
|
42
|
+
any: {},
|
|
43
|
+
# ISO codes, from the closed lists below.
|
|
44
|
+
country: { type: :string },
|
|
45
|
+
currency: { type: :string },
|
|
46
|
+
locale: { type: :string }
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
49
|
+
# The ISO lists a `country` or `currency` field takes, published once
|
|
50
|
+
# per API as a named component — the same `CountryCode` and
|
|
51
|
+
# `CurrencyCode` types the serializers declare, so a value read from
|
|
52
|
+
# a response is the type a request takes.
|
|
53
|
+
CODE_LISTS = {
|
|
54
|
+
country: ['CountryCode', -> { Spree::IsoData.country_codes }],
|
|
55
|
+
currency: ['CurrencyCode', -> { Spree::Money::Rounding::CURRENCY_CODES }],
|
|
56
|
+
locale: ['LocaleCode', -> { Spree::Locales::ALL }]
|
|
57
|
+
}.freeze
|
|
58
|
+
|
|
59
|
+
ACTIONS = %i[create update].freeze
|
|
60
|
+
|
|
61
|
+
OPEN_LIST_NOTE = 'The values listed are the built-in ones; extensions may add more.'.freeze
|
|
62
|
+
|
|
63
|
+
class Field
|
|
64
|
+
attr_reader :name, :kind, :array, :required, :nullable, :description, :example, :enum, :open, :only, :schema,
|
|
65
|
+
:permit, :format, :deprecated
|
|
66
|
+
|
|
67
|
+
def initialize(name, kind, array: false, required: false, nullable: false, description: nil,
|
|
68
|
+
example: nil, enum: nil, open: false, only: nil, schema: nil, permit: true, format: nil,
|
|
69
|
+
deprecated: nil)
|
|
70
|
+
raise ArgumentError, "deprecated: says what to use instead (#{name})" if deprecated == true
|
|
71
|
+
|
|
72
|
+
raise ArgumentError, "open: needs an enum: list of the built-in values (#{name})" if open && enum.nil?
|
|
73
|
+
|
|
74
|
+
unless required.in?([true, false, :create])
|
|
75
|
+
raise ArgumentError, "required: must be true, false or :create (#{name})"
|
|
76
|
+
end
|
|
77
|
+
raise ArgumentError, "only: must be :create or :update (#{name})" if only && !only.in?(ACTIONS)
|
|
78
|
+
|
|
79
|
+
@name = name.to_sym
|
|
80
|
+
@kind = kind
|
|
81
|
+
@array = array
|
|
82
|
+
@required = required
|
|
83
|
+
@nullable = nullable
|
|
84
|
+
@description = description
|
|
85
|
+
@example = example
|
|
86
|
+
@enum = enum&.map(&:to_s)
|
|
87
|
+
@open = open
|
|
88
|
+
@only = only
|
|
89
|
+
@schema = schema
|
|
90
|
+
@permit = permit
|
|
91
|
+
@format = format
|
|
92
|
+
@deprecated = deprecated
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param action [Symbol, nil]
|
|
96
|
+
def accepted_on?(action)
|
|
97
|
+
only.nil? || action.nil? || only == action
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @param action [Symbol, nil]
|
|
101
|
+
def required_on?(action)
|
|
102
|
+
required == true || (required == :create && action == :create)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# This field, required on `on` (`:create`) or always. A field
|
|
106
|
+
# already required always stays required always.
|
|
107
|
+
#
|
|
108
|
+
# @param on [Symbol, nil] `:create`, or nil for every action
|
|
109
|
+
# @return [Field]
|
|
110
|
+
def required_copy(on)
|
|
111
|
+
copy = dup
|
|
112
|
+
copy.instance_variable_set(:@required, required == true ? true : on || true)
|
|
113
|
+
copy
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# A hash of any keys, such as `metadata` or `provider_settings`.
|
|
117
|
+
def free_object?
|
|
118
|
+
kind == :object && schema.nil?
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
attr_reader :name, :fields
|
|
123
|
+
|
|
124
|
+
# The types an attribute takes: the scalars above, plus `:hash` (any
|
|
125
|
+
# keys), `:object` (a block or a `shape:`) and `:array` (`of:` a type
|
|
126
|
+
# or a shape, or a block of fields).
|
|
127
|
+
TYPES = (KINDS.keys + %i[hash object array]).freeze
|
|
128
|
+
|
|
129
|
+
# A shape shared between several endpoints (a price, an address),
|
|
130
|
+
# published as its own component so each SDK has one type for it.
|
|
131
|
+
#
|
|
132
|
+
# @param name [String] the component name, such as `PriceParams`
|
|
133
|
+
# @return [RequestSchema]
|
|
134
|
+
def self.shape(name, &block)
|
|
135
|
+
raise ArgumentError, "a shape's name ends in Params (#{name})" unless name.to_s.end_with?('Params')
|
|
136
|
+
|
|
137
|
+
new(name, &block)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# A shape several endpoints share is a class in app/request_schemas,
|
|
141
|
+
# declared the way a model declares its attributes:
|
|
142
|
+
#
|
|
143
|
+
# class Spree::Api::V3::PriceRequestSchema < Spree::Api::V3::RequestSchema
|
|
144
|
+
# publishes 'PriceParams'
|
|
145
|
+
#
|
|
146
|
+
# attribute :currency, :currency, required: true
|
|
147
|
+
# end
|
|
148
|
+
#
|
|
149
|
+
# A subclass starts from its parent's attributes, so the Admin API's
|
|
150
|
+
# address extends the shared one. Without `publishes` the class is a
|
|
151
|
+
# set of attributes other declarations include rather than a type of
|
|
152
|
+
# its own.
|
|
153
|
+
class << self
|
|
154
|
+
# @param name [String] the component name, ending in `Params`
|
|
155
|
+
def publishes(name)
|
|
156
|
+
raise ArgumentError, "a shape's name ends in Params (#{name})" unless name.to_s.end_with?('Params')
|
|
157
|
+
raise ArgumentError, "#{self.name}: `publishes` goes before the attributes" if @definition
|
|
158
|
+
|
|
159
|
+
@published_name = name.to_s
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# @return [RequestSchema] what the class declares
|
|
163
|
+
def definition
|
|
164
|
+
@definition ||= new(@published_name).tap do |schema|
|
|
165
|
+
schema.include_attributes(superclass) if superclass < RequestSchema
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# @param value [RequestSchema, Class] an instance or a declared class
|
|
170
|
+
# @return [RequestSchema, nil]
|
|
171
|
+
def resolve(value)
|
|
172
|
+
value.is_a?(Class) ? value.definition : value
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
%i[attribute include_attributes require_attributes external_references].each do |method|
|
|
176
|
+
define_method(method) { |*args, **options, &block| definition.public_send(method, *args, **options, &block) }
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# @param name [String, Symbol, nil] the resource, `product` publishing
|
|
181
|
+
# `ProductCreateParams` and `ProductUpdateParams`; or a name ending
|
|
182
|
+
# in `Params`, published as given for every action
|
|
183
|
+
# @yieldparam schema [RequestSchema] the schema, to declare attributes on
|
|
184
|
+
def initialize(name = nil)
|
|
185
|
+
@name = name&.to_s
|
|
186
|
+
@fields = {}
|
|
187
|
+
yield self if block_given?
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Declares one attribute of the body.
|
|
191
|
+
#
|
|
192
|
+
# @param name [Symbol]
|
|
193
|
+
# @param type [Symbol] one of TYPES
|
|
194
|
+
# @param of [Symbol, Class, RequestSchema, nil] what an `:array` holds:
|
|
195
|
+
# a scalar type, or a shared shape
|
|
196
|
+
# @param shape [Class, RequestSchema, nil] what an `:object` holds
|
|
197
|
+
# @param as [String, nil] publishes a block's object (or the objects
|
|
198
|
+
# of an `:array`) as a component of this name
|
|
199
|
+
# @param choices [Array, nil] the values the attribute takes
|
|
200
|
+
# @param required [Boolean]
|
|
201
|
+
# @param on [Symbol, nil] `:create` to require it only when creating
|
|
202
|
+
# @yieldparam schema [RequestSchema] a nested object's attributes
|
|
203
|
+
def attribute(name, type, of: nil, shape: nil, as: nil, choices: nil, required: false, on: nil, **options, &block)
|
|
204
|
+
raise ArgumentError, "#{name}: unknown type #{type.inspect}; use one of #{TYPES.join(', ')}" unless TYPES.include?(type)
|
|
205
|
+
raise ArgumentError, "#{name}: `on:` scopes `required: true` and is `:create`" if on && (!required || on != :create)
|
|
206
|
+
|
|
207
|
+
options = options.merge(required: on || required, enum: choices)
|
|
208
|
+
nested = nested_schema(type, of: of, shape: shape, as: as, &block)
|
|
209
|
+
|
|
210
|
+
case type
|
|
211
|
+
when :array then add_array(name, of, nested, options)
|
|
212
|
+
when :object
|
|
213
|
+
raise ArgumentError, "#{name}: an :object needs a block or `shape:`; use :hash for any keys" unless nested
|
|
214
|
+
|
|
215
|
+
add(Field.new(name, :object, schema: nested, **options))
|
|
216
|
+
when :hash then add(Field.new(name, :object, **options))
|
|
217
|
+
else add(Field.new(name, type, **options))
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# The identities a record has in external systems, which the Admin API
|
|
222
|
+
# reads from the raw params (Admin::Concerns::ExternalReferences).
|
|
223
|
+
def external_references
|
|
224
|
+
attribute :external_references, :hash, permit: false, description: <<~TEXT.squish
|
|
225
|
+
Identities the record has in external systems, keyed by system: the same
|
|
226
|
+
`{ system: external_id }` map the Admin API renders, so what you read can be
|
|
227
|
+
sent straight back. Systems you do not name keep the reference they have.
|
|
228
|
+
A list of `{ system, external_id }` entries is accepted too.
|
|
229
|
+
TEXT
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Adds the attributes of another schema, for endpoints that extend a
|
|
233
|
+
# shared set.
|
|
234
|
+
#
|
|
235
|
+
# @param other [RequestSchema, Class]
|
|
236
|
+
def include_attributes(other)
|
|
237
|
+
RequestSchema.resolve(other).fields.each_value { |field| add(field) }
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Marks attributes this schema took from another as required, for an
|
|
241
|
+
# endpoint whose model needs what the shared set leaves optional.
|
|
242
|
+
#
|
|
243
|
+
# @param names [Array<Symbol>]
|
|
244
|
+
# @param on [Symbol, nil] `:create` to require them only when creating
|
|
245
|
+
# @return [void]
|
|
246
|
+
def require_attributes(*names, on: nil)
|
|
247
|
+
raise ArgumentError, '`on:` is :create' if on && on != :create
|
|
248
|
+
|
|
249
|
+
names.each do |name|
|
|
250
|
+
field = fields.fetch(name) { raise ArgumentError, "#{name} is not an attribute of this schema" }
|
|
251
|
+
fields[name] = field.required_copy(on)
|
|
252
|
+
end
|
|
253
|
+
@permit_lists = nil
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# The `params.permit` list for an action.
|
|
257
|
+
#
|
|
258
|
+
# @param action [Symbol, String, nil] `create` or `update`; nil
|
|
259
|
+
# accepts every field
|
|
260
|
+
# @return [Array<Symbol, Hash>]
|
|
261
|
+
def permit_list(action = nil)
|
|
262
|
+
action = action&.to_sym
|
|
263
|
+
(@permit_lists ||= {})[action] ||= build_permit_list(action).freeze
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# The JSON Schema of the request body for an action.
|
|
267
|
+
#
|
|
268
|
+
# @param action [Symbol, String, nil]
|
|
269
|
+
# @return [Hash]
|
|
270
|
+
def json_schema(action = nil)
|
|
271
|
+
action = action&.to_sym
|
|
272
|
+
fields = fields_for(action)
|
|
273
|
+
required = fields.select { |field| field.required_on?(action) }.map { |field| field.name.to_s }
|
|
274
|
+
|
|
275
|
+
schema = { type: :object, properties: fields.to_h { |field| [field.name, property_schema(field)] } }
|
|
276
|
+
schema[:required] = required if required.any?
|
|
277
|
+
schema
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# The component name published for an action.
|
|
281
|
+
#
|
|
282
|
+
# @param action [Symbol, String]
|
|
283
|
+
# @return [String]
|
|
284
|
+
def component_name(action)
|
|
285
|
+
return name if name.end_with?('Params')
|
|
286
|
+
|
|
287
|
+
"#{name.camelize}#{action.to_s.camelize}Params"
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Every named shape this schema reaches, nested ones included.
|
|
291
|
+
#
|
|
292
|
+
# @return [Array<RequestSchema>]
|
|
293
|
+
def shapes
|
|
294
|
+
fields.each_value.flat_map do |field|
|
|
295
|
+
next [] unless field.schema
|
|
296
|
+
|
|
297
|
+
nested = field.schema.shapes
|
|
298
|
+
shape?(field.schema) ? [field.schema, *nested] : nested
|
|
299
|
+
end.uniq
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# The ISO code lists this schema's fields reach, nested ones included,
|
|
303
|
+
# as the components they publish.
|
|
304
|
+
#
|
|
305
|
+
# @return [Hash{String => Hash}]
|
|
306
|
+
def code_lists
|
|
307
|
+
fields.each_value.each_with_object({}) do |field, lists|
|
|
308
|
+
lists.merge!(field.schema.code_lists) if field.schema
|
|
309
|
+
next unless CODE_LISTS.key?(field.kind)
|
|
310
|
+
|
|
311
|
+
name, values = CODE_LISTS[field.kind]
|
|
312
|
+
lists[name] = { type: :string, enum: values.call }
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def shape?(schema)
|
|
317
|
+
schema.name.present?
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
private
|
|
321
|
+
|
|
322
|
+
def nested_schema(type, of:, shape:, as:, &block)
|
|
323
|
+
return RequestSchema.resolve(shape) if shape
|
|
324
|
+
return RequestSchema.resolve(of) if of.is_a?(Class) || of.is_a?(RequestSchema)
|
|
325
|
+
return unless block
|
|
326
|
+
|
|
327
|
+
as ? RequestSchema.shape(as, &block) : RequestSchema.new(&block)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def add_array(name, of, nested, options)
|
|
331
|
+
return add(Field.new(name, :object, schema: nested, array: true, **options)) if nested
|
|
332
|
+
|
|
333
|
+
unless of.is_a?(Symbol) && KINDS.key?(of)
|
|
334
|
+
raise ArgumentError, "#{name}: an :array needs `of:` a scalar type or a shape, or a block of attributes"
|
|
335
|
+
end
|
|
336
|
+
# Rails permits a list of scalars, never a list of any-key hashes.
|
|
337
|
+
if of == :any && options.fetch(:permit, true)
|
|
338
|
+
raise ArgumentError, "#{name}: a list of :any values cannot be permitted; declare its items or use `permit: false`"
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
add(Field.new(name, of, array: true, **options))
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def add(field)
|
|
345
|
+
raise ArgumentError, "#{field.name} is declared twice" if fields.key?(field.name)
|
|
346
|
+
|
|
347
|
+
@permit_lists = nil
|
|
348
|
+
fields[field.name] = field
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def build_permit_list(action)
|
|
352
|
+
scalars = []
|
|
353
|
+
nested = []
|
|
354
|
+
|
|
355
|
+
fields_for(action).each do |field|
|
|
356
|
+
next unless field.permit
|
|
357
|
+
|
|
358
|
+
if field.schema
|
|
359
|
+
nested << { field.name => field.schema.permit_list }
|
|
360
|
+
elsif field.free_object?
|
|
361
|
+
nested << { field.name => {} }
|
|
362
|
+
elsif field.kind == :any
|
|
363
|
+
# A value of any JSON type: a scalar, a list or a hash.
|
|
364
|
+
scalars << field.name
|
|
365
|
+
nested << { field.name => [] } << { field.name => {} }
|
|
366
|
+
elsif field.array
|
|
367
|
+
nested << { field.name => [] }
|
|
368
|
+
else
|
|
369
|
+
scalars << field.name
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
scalars + nested
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def fields_for(action)
|
|
378
|
+
fields.values.select { |field| field.accepted_on?(action) }
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def property_schema(field)
|
|
382
|
+
item = item_schema(field)
|
|
383
|
+
description = [field.description, (OPEN_LIST_NOTE if field.open), deprecation_note(field)].compact.join(' ').presence
|
|
384
|
+
documentation = { description: description, example: field.example }.compact
|
|
385
|
+
documentation[:deprecated] = true if field.deprecated
|
|
386
|
+
|
|
387
|
+
if field.array
|
|
388
|
+
schema = { type: :array, items: item }.merge(documentation)
|
|
389
|
+
schema[:nullable] = true if field.nullable
|
|
390
|
+
return schema
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# A $ref ignores the keys beside it, so a described or nullable
|
|
394
|
+
# reference wraps it.
|
|
395
|
+
if item.key?(:$ref) && (documentation.any? || field.nullable)
|
|
396
|
+
item = { allOf: [item] }
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
item = item.merge(documentation)
|
|
400
|
+
item[:nullable] = true if field.nullable
|
|
401
|
+
item
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def deprecation_note(field)
|
|
405
|
+
"Deprecated: #{field.deprecated}" if field.deprecated
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def item_schema(field)
|
|
409
|
+
return { '$ref': "#/components/schemas/#{CODE_LISTS[field.kind].first}" } if CODE_LISTS.key?(field.kind)
|
|
410
|
+
|
|
411
|
+
if field.schema
|
|
412
|
+
return { '$ref': "#/components/schemas/#{field.schema.name}" } if shape?(field.schema)
|
|
413
|
+
|
|
414
|
+
return field.schema.json_schema
|
|
415
|
+
end
|
|
416
|
+
return { type: :object, additionalProperties: true } if field.free_object?
|
|
417
|
+
|
|
418
|
+
schema = KINDS.fetch(field.kind).dup
|
|
419
|
+
schema[:format] = field.format if field.format
|
|
420
|
+
return schema unless field.enum
|
|
421
|
+
return schema.merge(enum: field.enum) unless field.open
|
|
422
|
+
|
|
423
|
+
# The same open list the serializers publish (`enum_type_name`):
|
|
424
|
+
# clients autocomplete the built-in values and still accept any other.
|
|
425
|
+
{ anyOf: [schema.merge(enum: field.enum), schema] }
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
end
|
|
@@ -90,10 +90,14 @@ module Spree
|
|
|
90
90
|
http_options = { open_timeout: TIMEOUT, read_timeout: TIMEOUT, verify_mode: ssl_verify_mode }
|
|
91
91
|
|
|
92
92
|
# SSRF protection is disabled in development so webhooks can reach
|
|
93
|
-
# localhost / host.docker.internal (the storefront running on the host)
|
|
94
|
-
|
|
93
|
+
# localhost / host.docker.internal (the storefront running on the host),
|
|
94
|
+
# and for hosts the operator explicitly trusts
|
|
95
|
+
# (Spree::Api::Config.webhooks_allowed_internal_hosts).
|
|
96
|
+
if Rails.env.development? || Spree::WebhookEndpoint.allowed_internal_host?(@delivery.url)
|
|
95
97
|
uri = URI.parse(@delivery.url)
|
|
96
|
-
|
|
98
|
+
# No proxy, as SsrfFilter: an egress proxy from the environment would
|
|
99
|
+
# carry this in-cluster (or localhost) request out of the network.
|
|
100
|
+
http = Net::HTTP.new(uri.hostname, uri.port, nil)
|
|
97
101
|
http.use_ssl = uri.scheme == 'https'
|
|
98
102
|
http_options.each { |k, v| http.send(:"#{k}=", v) }
|
|
99
103
|
|
|
@@ -75,7 +75,7 @@ Rails.application.config.after_initialize do
|
|
|
75
75
|
# serializer this branch inherits references them, so their types still
|
|
76
76
|
# have to exist in the package.
|
|
77
77
|
store_nested_for_seller = %w[
|
|
78
|
-
|
|
78
|
+
Category CustomField OptionType OptionValue Seller
|
|
79
79
|
].to_set
|
|
80
80
|
|
|
81
81
|
config.writer(:seller) do |c|
|
data/config/routes.rb
CHANGED
|
@@ -255,6 +255,8 @@ Spree::Core::Engine.add_routes do
|
|
|
255
255
|
# Self-service profile updates (e.g. the admin's own UI language)
|
|
256
256
|
patch 'me', to: 'me#update'
|
|
257
257
|
|
|
258
|
+
resource :updates, only: :show
|
|
259
|
+
|
|
258
260
|
# Store Settings
|
|
259
261
|
resource :store, only: [:show, :update], controller: 'store' do
|
|
260
262
|
get :data_sources
|
|
@@ -299,8 +301,8 @@ Spree::Core::Engine.add_routes do
|
|
|
299
301
|
resources :roles, only: [:index, :show, :create, :update, :destroy]
|
|
300
302
|
resources :permissions, only: [:index]
|
|
301
303
|
|
|
302
|
-
#
|
|
303
|
-
resources :
|
|
304
|
+
# File uploads — see docs/plans/6.0-uploads-and-file-ownership.md
|
|
305
|
+
resources :files, only: [:create]
|
|
304
306
|
|
|
305
307
|
# CSV Exports — see docs/plans/5.5-admin-spa-csv-export.md
|
|
306
308
|
resources :exports, only: [:index, :show, :create, :destroy] do
|
|
@@ -961,7 +963,7 @@ Spree::Core::Engine.add_routes do
|
|
|
961
963
|
# Registry data — which carriers a tracking number can be pinned to.
|
|
962
964
|
resources :tracking_carriers, only: [:index]
|
|
963
965
|
|
|
964
|
-
resources :
|
|
966
|
+
resources :files, only: [:create]
|
|
965
967
|
|
|
966
968
|
# CSV of what this seller sold, or of their catalogue. Created, polled
|
|
967
969
|
# and downloaded — no index, since a seller has no history page to
|
|
@@ -27,6 +27,11 @@ module Spree
|
|
|
27
27
|
|
|
28
28
|
preference :webhooks_enabled, :boolean, default: true, env: 'SPREE_WEBHOOKS_ENABLED'
|
|
29
29
|
preference :webhooks_verify_ssl, :boolean, default: !Rails.env.development?, env: 'SPREE_WEBHOOKS_VERIFY_SSL'
|
|
30
|
+
# Hosts a webhook may reach even though they resolve to a private
|
|
31
|
+
# address (the SSRF guard otherwise refuses them). "host" matches that
|
|
32
|
+
# host; ".suffix" matches any host under it. See
|
|
33
|
+
# Spree::WebhookEndpoint.allowed_internal_host?.
|
|
34
|
+
preference :webhooks_allowed_internal_hosts, :array, default: [], env: 'SPREE_WEBHOOKS_ALLOWED_INTERNAL_HOSTS'
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
37
|
end
|
|
@@ -18,10 +18,10 @@ module Spree
|
|
|
18
18
|
product_filter_sort_option media_event return return_line_item exchange exchange_line_item claim
|
|
19
19
|
claim_line_item return_reason claim_reason digital_asset export gift_card_batch import import_row
|
|
20
20
|
invitation newsletter_subscriber promotion refund stock_level stock_movement stock_reservation
|
|
21
|
-
stock_transfer company company_membership company_invitation seller].freeze
|
|
21
|
+
stock_transfer company company_membership company_invitation seller file_upload file_upload_target].freeze
|
|
22
22
|
|
|
23
23
|
ADMIN_SERIALIZERS =
|
|
24
|
-
%i[country state applied_promotion discount tax_line cart delivery_zone delivery_profile
|
|
24
|
+
%i[country state locale applied_promotion discount tax_line cart delivery_zone delivery_profile
|
|
25
25
|
delivery_origin_group integration delivery_method_rule delivery_zone_member fee consent_record customer
|
|
26
26
|
data_request newsletter_subscriber order order_group product product_type
|
|
27
27
|
product_type_custom_field_definition variant price price_history custom_field custom_field_definition
|
|
@@ -38,19 +38,20 @@ module Spree
|
|
|
38
38
|
channel order_routing_rule product_publication market delivery_method delivery_method_service
|
|
39
39
|
stock_location stock_reservation delivery_rate freight_summary freight_summary_line payment_method
|
|
40
40
|
credit_card store_credit store_credit_event customer_group payment_source digital_asset digital_link
|
|
41
|
-
store setup_task api_key allowed_origin webhook_endpoint webhook_event webhook_delivery invitation
|
|
41
|
+
store setup_task update_status api_key allowed_origin webhook_endpoint webhook_event webhook_delivery invitation
|
|
42
42
|
invitation_acceptance_link role permission export saved_report import import_row import_mapping promotion
|
|
43
43
|
promotion_action promotion_rule coupon_code price_adjustment_tier price_list price_rule
|
|
44
44
|
resource_translations email_template email_template_draft email_template_revision email_template_preview
|
|
45
|
-
email_template_sample_record].freeze
|
|
45
|
+
email_template_sample_record file_upload file_upload_target].freeze
|
|
46
46
|
|
|
47
47
|
SELLER_SERIALIZERS =
|
|
48
|
-
%i[profile policy team_member account invitation invitation_acceptance_link product product_type
|
|
48
|
+
%i[address country state profile policy team_member account invitation invitation_acceptance_link product product_type
|
|
49
49
|
delivery_profile delivery_method delivery_method_rule delivery_zone variant media stock_level order
|
|
50
50
|
order_line_item fulfillment fulfillment_item delivery delivery_rate shipping_label return
|
|
51
51
|
return_line_item exchange exchange_line_item claim claim_line_item reason package_type stock_location
|
|
52
52
|
requirement_custom_field tax_identifier requirement_status import import_row import_mapping
|
|
53
|
-
requirement_submission export transfer payout balance payment_split
|
|
53
|
+
requirement_submission export transfer payout balance payment_split price price_history file_upload
|
|
54
|
+
file_upload_target].freeze
|
|
54
55
|
|
|
55
56
|
INJECTION_POINTS_WITH_DEFAULTS = {
|
|
56
57
|
**STORE_SERIALIZERS.to_h { |name| [:"#{name}_serializer", "Spree::Api::V3::#{name.to_s.camelize}Serializer"] },
|
|
@@ -2,13 +2,24 @@ module Spree
|
|
|
2
2
|
module Api
|
|
3
3
|
module Middleware
|
|
4
4
|
class RequestSizeLimit
|
|
5
|
+
# `POST /files` takes a file's bytes in the request itself, so it is
|
|
6
|
+
# held to the multipart upload limit instead, plus room for the other
|
|
7
|
+
# form fields.
|
|
8
|
+
FILE_UPLOAD_PATH = %r{\A/api/v3/(admin|seller)/files/?\z}
|
|
9
|
+
MULTIPART_ENVELOPE = 64.kilobytes
|
|
10
|
+
|
|
5
11
|
def initialize(app, limit: nil)
|
|
6
12
|
@app = app
|
|
7
13
|
@limit = limit
|
|
8
14
|
end
|
|
9
15
|
|
|
10
16
|
def call(env)
|
|
11
|
-
if
|
|
17
|
+
if file_upload?(env) && chunked?(env)
|
|
18
|
+
# A chunked body has no length to check here, and these bytes pass
|
|
19
|
+
# through the application.
|
|
20
|
+
body = { error: { code: 'request_too_large', message: 'Send the file with a Content-Length header' } }
|
|
21
|
+
[411, { 'Content-Type' => 'application/json' }, [body.to_json]]
|
|
22
|
+
elsif api_request?(env) && content_length_exceeded?(env)
|
|
12
23
|
body = { error: { code: 'request_too_large', message: 'Request body too large' } }
|
|
13
24
|
[413, { 'Content-Type' => 'application/json' }, [body.to_json]]
|
|
14
25
|
else
|
|
@@ -24,12 +35,22 @@ module Spree
|
|
|
24
35
|
|
|
25
36
|
def content_length_exceeded?(env)
|
|
26
37
|
content_length = env['CONTENT_LENGTH'].to_i
|
|
27
|
-
content_length > max_body_size
|
|
38
|
+
content_length > max_body_size(env)
|
|
28
39
|
end
|
|
29
40
|
|
|
30
|
-
def max_body_size
|
|
41
|
+
def max_body_size(env)
|
|
42
|
+
return Spree::Config[:max_multipart_upload_size] + MULTIPART_ENVELOPE if file_upload?(env)
|
|
43
|
+
|
|
31
44
|
@limit || Spree::Api::Config[:max_request_body_size]
|
|
32
45
|
end
|
|
46
|
+
|
|
47
|
+
def chunked?(env)
|
|
48
|
+
env['CONTENT_LENGTH'].nil? && env['HTTP_TRANSFER_ENCODING'].to_s.include?('chunked')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def file_upload?(env)
|
|
52
|
+
env['REQUEST_METHOD'] == 'POST' && FILE_UPLOAD_PATH.match?(env['PATH_INFO'])
|
|
53
|
+
end
|
|
33
54
|
end
|
|
34
55
|
end
|
|
35
56
|
end
|