spree_api 5.3.3 → 5.4.0.beta
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/README.md +71 -33
- data/Rakefile +25 -0
- data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +51 -0
- data/app/controllers/concerns/spree/api/v3/error_handler.rb +255 -0
- data/app/controllers/concerns/spree/api/v3/http_caching.rb +90 -0
- data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +95 -0
- data/app/controllers/concerns/spree/api/v3/locale_and_currency.rb +73 -0
- data/app/controllers/concerns/spree/api/v3/order_concern.rb +51 -0
- data/app/controllers/concerns/spree/api/v3/resource_serializer.rb +41 -0
- data/app/controllers/spree/api/v3/base_controller.rb +42 -0
- data/app/controllers/spree/api/v3/resource_controller.rb +210 -0
- data/app/controllers/spree/api/v3/store/auth_controller.rb +140 -0
- data/app/controllers/spree/api/v3/store/base_controller.rb +12 -0
- data/app/controllers/spree/api/v3/store/cart_controller.rb +82 -0
- data/app/controllers/spree/api/v3/store/countries_controller.rb +31 -0
- data/app/controllers/spree/api/v3/store/currencies_controller.rb +18 -0
- data/app/controllers/spree/api/v3/store/customer/account_controller.rb +38 -0
- data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +85 -0
- data/app/controllers/spree/api/v3/store/customer/credit_cards_controller.rb +31 -0
- data/app/controllers/spree/api/v3/store/customer/gift_cards_controller.rb +36 -0
- data/app/controllers/spree/api/v3/store/customer/orders_controller.rb +35 -0
- data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +83 -0
- data/app/controllers/spree/api/v3/store/digitals_controller.rb +37 -0
- data/app/controllers/spree/api/v3/store/locales_controller.rb +24 -0
- data/app/controllers/spree/api/v3/store/orders/coupon_codes_controller.rb +68 -0
- data/app/controllers/spree/api/v3/store/orders/line_items_controller.rb +87 -0
- data/app/controllers/spree/api/v3/store/orders/payment_methods_controller.rb +43 -0
- data/app/controllers/spree/api/v3/store/orders/payment_sessions_controller.rb +96 -0
- data/app/controllers/spree/api/v3/store/orders/payments_controller.rb +45 -0
- data/app/controllers/spree/api/v3/store/orders/shipments_controller.rb +53 -0
- data/app/controllers/spree/api/v3/store/orders/store_credits_controller.rb +42 -0
- data/app/controllers/spree/api/v3/store/orders_controller.rb +125 -0
- data/app/controllers/spree/api/v3/store/products/filters_controller.rb +38 -0
- data/app/controllers/spree/api/v3/store/products_controller.rb +74 -0
- data/app/controllers/spree/api/v3/store/resource_controller.rb +12 -0
- data/app/controllers/spree/api/v3/store/stores_controller.rb +26 -0
- data/app/controllers/spree/api/v3/store/taxonomies_controller.rb +19 -0
- data/app/controllers/spree/api/v3/store/taxons/products_controller.rb +37 -0
- data/app/controllers/spree/api/v3/store/taxons_controller.rb +34 -0
- data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +33 -0
- data/app/controllers/spree/api/v3/store/wishlists_controller.rb +41 -0
- data/app/serializers/spree/api/v3/address_serializer.rb +22 -0
- data/app/serializers/spree/api/v3/admin/customer_serializer.rb +43 -0
- data/app/serializers/spree/api/v3/admin/metafield_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +39 -0
- data/app/serializers/spree/api/v3/admin/price_serializer.rb +21 -0
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +47 -0
- data/app/serializers/spree/api/v3/admin/taxon_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/admin/taxonomy_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/variant_serializer.rb +44 -0
- data/app/serializers/spree/api/v3/asset_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/base_serializer.rb +98 -0
- data/app/serializers/spree/api/v3/country_serializer.rb +35 -0
- data/app/serializers/spree/api/v3/credit_card_serializer.rb +12 -0
- data/app/serializers/spree/api/v3/currency_serializer.rb +14 -0
- data/app/serializers/spree/api/v3/customer_return_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/customer_serializer.rb +19 -0
- data/app/serializers/spree/api/v3/digital_link_serializer.rb +30 -0
- data/app/serializers/spree/api/v3/digital_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/export_serializer.rb +19 -0
- data/app/serializers/spree/api/v3/gift_card_batch_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +78 -0
- data/app/serializers/spree/api/v3/image_serializer.rb +43 -0
- data/app/serializers/spree/api/v3/import_row_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/import_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/invitation_serializer.rb +47 -0
- data/app/serializers/spree/api/v3/line_item_serializer.rb +48 -0
- data/app/serializers/spree/api/v3/locale_serializer.rb +14 -0
- data/app/serializers/spree/{v2/storefront → api/v3}/metafield_serializer.rb +5 -3
- data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +27 -0
- data/app/serializers/spree/api/v3/option_type_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/option_value_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/order_promotion_serializer.rb +16 -0
- data/app/serializers/spree/api/v3/order_serializer.rb +39 -0
- data/app/serializers/spree/api/v3/payment_method_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/payment_serializer.rb +54 -0
- data/app/serializers/spree/api/v3/payment_session_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +33 -0
- data/app/serializers/spree/api/v3/payment_source_serializer.rb +18 -0
- data/app/serializers/spree/api/v3/post_category_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/post_serializer.rb +25 -0
- data/app/serializers/spree/api/v3/price_serializer.rb +34 -0
- data/app/serializers/spree/api/v3/product_serializer.rb +108 -0
- data/app/serializers/spree/api/v3/promotion_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/refund_serializer.rb +31 -0
- data/app/serializers/spree/api/v3/reimbursement_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/report_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/return_authorization_serializer.rb +31 -0
- data/app/serializers/spree/api/v3/return_item_serializer.rb +53 -0
- data/app/serializers/spree/api/v3/shipment_serializer.rb +19 -0
- data/app/serializers/spree/api/v3/shipping_method_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/shipping_rate_serializer.rb +26 -0
- data/app/serializers/spree/api/v3/state_serializer.rb +14 -0
- data/app/serializers/spree/api/v3/stock_item_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/stock_location_serializer.rb +18 -0
- data/app/serializers/spree/api/v3/stock_movement_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +25 -0
- data/app/serializers/spree/api/v3/store_credit_serializer.rb +37 -0
- data/app/serializers/spree/api/v3/store_serializer.rb +38 -0
- data/app/serializers/spree/api/v3/taxon_serializer.rb +78 -0
- data/app/serializers/spree/api/v3/taxonomy_serializer.rb +33 -0
- data/app/serializers/spree/api/v3/variant_serializer.rb +86 -0
- data/app/serializers/spree/api/v3/wished_item_serializer.rb +22 -0
- data/app/serializers/spree/api/v3/wishlist_serializer.rb +25 -0
- data/app/services/spree/api/v3/filters_aggregator.rb +156 -0
- data/app/services/spree/api/v3/orders/update.rb +103 -0
- data/config/initializers/alba.rb +5 -0
- data/config/initializers/pagy.rb +10 -0
- data/config/initializers/typelizer.rb +25 -0
- data/config/locales/en.yml +1 -0
- data/config/routes.rb +63 -196
- data/lib/spree/api/dependencies.rb +68 -0
- data/lib/spree/api/engine.rb +0 -5
- data/lib/spree/api/openapi/schema_helper.rb +177 -0
- data/lib/spree/api/testing_support/factories.rb +1 -3
- data/lib/spree/api/testing_support/v3/base.rb +118 -0
- data/lib/spree/api.rb +7 -4
- metadata +131 -264
- data/LICENSE.md +0 -57
- data/app/controllers/concerns/spree/api/v2/caching.rb +0 -40
- data/app/controllers/concerns/spree/api/v2/coupon_codes_helper.rb +0 -29
- data/app/controllers/concerns/spree/api/v2/number_resource.rb +0 -11
- data/app/controllers/concerns/spree/api/v2/platform/nested_set_reposition_concern.rb +0 -37
- data/app/controllers/concerns/spree/api/v2/platform/promotion_calculator_params.rb +0 -17
- data/app/controllers/concerns/spree/api/v2/platform/promotion_rule_params.rb +0 -16
- data/app/controllers/concerns/spree/api/v2/product_list_includes.rb +0 -21
- data/app/controllers/concerns/spree/api/v2/storefront/metadata_controller_concern.rb +0 -18
- data/app/controllers/concerns/spree/api/v2/storefront/order_concern.rb +0 -49
- data/app/controllers/spree/api/v2/base_controller.rb +0 -233
- data/app/controllers/spree/api/v2/data_feeds/google_controller.rb +0 -24
- data/app/controllers/spree/api/v2/platform/addresses_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/adjustments_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/classifications_controller.rb +0 -26
- data/app/controllers/spree/api/v2/platform/countries_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/data_feeds_controller.rb +0 -19
- data/app/controllers/spree/api/v2/platform/digital_links_controller.rb +0 -29
- data/app/controllers/spree/api/v2/platform/digitals_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/gift_cards_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/line_items_controller.rb +0 -63
- data/app/controllers/spree/api/v2/platform/option_types_controller.rb +0 -19
- data/app/controllers/spree/api/v2/platform/option_values_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/orders_controller.rb +0 -167
- data/app/controllers/spree/api/v2/platform/payment_methods_controller.rb +0 -31
- data/app/controllers/spree/api/v2/platform/payments_controller.rb +0 -21
- data/app/controllers/spree/api/v2/platform/products_controller.rb +0 -41
- data/app/controllers/spree/api/v2/platform/promotion_actions_controller.rb +0 -34
- data/app/controllers/spree/api/v2/platform/promotion_categories_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/promotion_rules_controller.rb +0 -29
- data/app/controllers/spree/api/v2/platform/promotions_controller.rb +0 -35
- data/app/controllers/spree/api/v2/platform/resource_controller.rb +0 -154
- data/app/controllers/spree/api/v2/platform/roles_controller.rb +0 -19
- data/app/controllers/spree/api/v2/platform/shipments_controller.rb +0 -147
- data/app/controllers/spree/api/v2/platform/shipping_categories_controller.rb +0 -19
- data/app/controllers/spree/api/v2/platform/shipping_methods_controller.rb +0 -28
- data/app/controllers/spree/api/v2/platform/states_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/stock_items_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/stock_locations_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/store_credit_categories_controller.rb +0 -19
- data/app/controllers/spree/api/v2/platform/store_credit_types_controller.rb +0 -19
- data/app/controllers/spree/api/v2/platform/store_credits_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/tax_categories_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/tax_rates_controller.rb +0 -27
- data/app/controllers/spree/api/v2/platform/taxonomies_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/taxons_controller.rb +0 -59
- data/app/controllers/spree/api/v2/platform/users_controller.rb +0 -37
- data/app/controllers/spree/api/v2/platform/variants_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/wished_items_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/wishlists_controller.rb +0 -23
- data/app/controllers/spree/api/v2/platform/zones_controller.rb +0 -23
- data/app/controllers/spree/api/v2/resource_controller.rb +0 -79
- data/app/controllers/spree/api/v2/storefront/account/addresses_controller.rb +0 -77
- data/app/controllers/spree/api/v2/storefront/account/credit_cards_controller.rb +0 -52
- data/app/controllers/spree/api/v2/storefront/account/orders_controller.rb +0 -50
- data/app/controllers/spree/api/v2/storefront/account_controller.rb +0 -52
- data/app/controllers/spree/api/v2/storefront/cart_controller.rb +0 -246
- data/app/controllers/spree/api/v2/storefront/checkout_controller.rb +0 -183
- data/app/controllers/spree/api/v2/storefront/countries_controller.rb +0 -57
- data/app/controllers/spree/api/v2/storefront/digitals_controller.rb +0 -58
- data/app/controllers/spree/api/v2/storefront/order_status_controller.rb +0 -34
- data/app/controllers/spree/api/v2/storefront/policies_controller.rb +0 -31
- data/app/controllers/spree/api/v2/storefront/post_categories_controller.rb +0 -35
- data/app/controllers/spree/api/v2/storefront/posts_controller.rb +0 -51
- data/app/controllers/spree/api/v2/storefront/products_controller.rb +0 -66
- data/app/controllers/spree/api/v2/storefront/stores_controller.rb +0 -27
- data/app/controllers/spree/api/v2/storefront/taxons_controller.rb +0 -51
- data/app/controllers/spree/api/v2/storefront/variants_controller.rb +0 -41
- data/app/controllers/spree/api/v2/storefront/wishlists_controller.rb +0 -214
- data/app/helpers/spree/api/v2/collection_options_helpers.rb +0 -46
- data/app/helpers/spree/api/v2/display_money_helper.rb +0 -63
- data/app/helpers/spree/api/v2/store_media_serializer_images_concern.rb +0 -30
- data/app/models/concerns/spree/user_api_authentication.rb +0 -19
- data/app/models/concerns/spree/user_api_methods.rb +0 -7
- data/app/models/spree/oauth_access_grant.rb +0 -7
- data/app/models/spree/oauth_access_token.rb +0 -7
- data/app/models/spree/oauth_application.rb +0 -22
- data/app/paginators/spree/api/paginate.rb +0 -68
- data/app/presenters/spree/api/products/filters_presenter.rb +0 -39
- data/app/serializers/concerns/spree/api/v2/image_transformation_concern.rb +0 -15
- data/app/serializers/concerns/spree/api/v2/public_metafields_concern.rb +0 -15
- data/app/serializers/concerns/spree/api/v2/resource_serializer_concern.rb +0 -42
- data/app/serializers/concerns/spree/api/v2/taxon_image_transformation_concern.rb +0 -15
- data/app/serializers/spree/api/v2/base_serializer.rb +0 -43
- data/app/serializers/spree/api/v2/platform/address_serializer.rb +0 -15
- data/app/serializers/spree/api/v2/platform/adjustment_serializer.rb +0 -20
- data/app/serializers/spree/api/v2/platform/admin_user_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/asset_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/base_serializer.rb +0 -10
- data/app/serializers/spree/api/v2/platform/calculator_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/classification_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/country_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/credit_card_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/customer_return_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/data_feed_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/digital_link_serializer.rb +0 -16
- data/app/serializers/spree/api/v2/platform/digital_serializer.rb +0 -29
- data/app/serializers/spree/api/v2/platform/gift_card_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/image_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/inventory_unit_serializer.rb +0 -19
- data/app/serializers/spree/api/v2/platform/line_item_serializer.rb +0 -19
- data/app/serializers/spree/api/v2/platform/log_entry_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/metafield_serializer.rb +0 -21
- data/app/serializers/spree/api/v2/platform/option_type_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/option_value_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/order_promotion_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/order_serializer.rb +0 -31
- data/app/serializers/spree/api/v2/platform/payment_capture_event_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/payment_method_serializer.rb +0 -18
- data/app/serializers/spree/api/v2/platform/payment_serializer.rb +0 -22
- data/app/serializers/spree/api/v2/platform/payment_source_serializer.rb +0 -12
- data/app/serializers/spree/api/v2/platform/price_serializer.rb +0 -19
- data/app/serializers/spree/api/v2/platform/product_property_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/product_serializer.rb +0 -90
- data/app/serializers/spree/api/v2/platform/promotion_action_line_item_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/promotion_action_serializer.rb +0 -19
- data/app/serializers/spree/api/v2/platform/promotion_category_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/promotion_rule_serializer.rb +0 -21
- data/app/serializers/spree/api/v2/platform/promotion_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/property_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/prototype_serializer.rb +0 -15
- data/app/serializers/spree/api/v2/platform/refund_reason_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/refund_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/reimbursement_credit_serializer.rb +0 -10
- data/app/serializers/spree/api/v2/platform/reimbursement_serializer.rb +0 -19
- data/app/serializers/spree/api/v2/platform/reimbursement_type_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/return_authorization_reason_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/return_authorization_serializer.rb +0 -17
- data/app/serializers/spree/api/v2/platform/return_item_serializer.rb +0 -16
- data/app/serializers/spree/api/v2/platform/role_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/shipment_serializer.rb +0 -22
- data/app/serializers/spree/api/v2/platform/shipping_category_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/shipping_method_serializer.rb +0 -16
- data/app/serializers/spree/api/v2/platform/shipping_rate_serializer.rb +0 -15
- data/app/serializers/spree/api/v2/platform/state_change_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/state_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/stock_item_serializer.rb +0 -18
- data/app/serializers/spree/api/v2/platform/stock_location_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/stock_movement_serializer.rb +0 -11
- data/app/serializers/spree/api/v2/platform/stock_transfer_serializer.rb +0 -15
- data/app/serializers/spree/api/v2/platform/store_credit_category_serializer.rb +0 -12
- data/app/serializers/spree/api/v2/platform/store_credit_event_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/store_credit_serializer.rb +0 -18
- data/app/serializers/spree/api/v2/platform/store_credit_type_serializer.rb +0 -12
- data/app/serializers/spree/api/v2/platform/store_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/tax_category_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/tax_rate_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/taxon_image_serializer.rb +0 -15
- data/app/serializers/spree/api/v2/platform/taxon_serializer.rb +0 -47
- data/app/serializers/spree/api/v2/platform/taxonomy_serializer.rb +0 -14
- data/app/serializers/spree/api/v2/platform/user_serializer.rb +0 -37
- data/app/serializers/spree/api/v2/platform/variant_serializer.rb +0 -66
- data/app/serializers/spree/api/v2/platform/wished_item_serializer.rb +0 -29
- data/app/serializers/spree/api/v2/platform/wishlist_serializer.rb +0 -19
- data/app/serializers/spree/api/v2/platform/zone_member_serializer.rb +0 -13
- data/app/serializers/spree/api/v2/platform/zone_serializer.rb +0 -13
- data/app/serializers/spree/v2/storefront/address_serializer.rb +0 -22
- data/app/serializers/spree/v2/storefront/base_serializer.rb +0 -10
- data/app/serializers/spree/v2/storefront/cart_serializer.rb +0 -67
- data/app/serializers/spree/v2/storefront/country_serializer.rb +0 -24
- data/app/serializers/spree/v2/storefront/credit_card_serializer.rb +0 -15
- data/app/serializers/spree/v2/storefront/digital_link_serializer.rb +0 -11
- data/app/serializers/spree/v2/storefront/estimated_shipping_rate_serializer.rb +0 -35
- data/app/serializers/spree/v2/storefront/gift_card_serializer.rb +0 -16
- data/app/serializers/spree/v2/storefront/image_serializer.rb +0 -13
- data/app/serializers/spree/v2/storefront/line_item_serializer.rb +0 -23
- data/app/serializers/spree/v2/storefront/option_type_serializer.rb +0 -15
- data/app/serializers/spree/v2/storefront/option_value_serializer.rb +0 -13
- data/app/serializers/spree/v2/storefront/order_promotion_serializer.rb +0 -14
- data/app/serializers/spree/v2/storefront/order_serializer.rb +0 -11
- data/app/serializers/spree/v2/storefront/payment_method_serializer.rb +0 -17
- data/app/serializers/spree/v2/storefront/payment_serializer.rb +0 -20
- data/app/serializers/spree/v2/storefront/payment_source_serializer.rb +0 -12
- data/app/serializers/spree/v2/storefront/policy_serializer.rb +0 -19
- data/app/serializers/spree/v2/storefront/post_category_serializer.rb +0 -23
- data/app/serializers/spree/v2/storefront/post_serializer.rb +0 -51
- data/app/serializers/spree/v2/storefront/product_property_serializer.rb +0 -19
- data/app/serializers/spree/v2/storefront/product_serializer.rb +0 -92
- data/app/serializers/spree/v2/storefront/shipment_serializer.rb +0 -26
- data/app/serializers/spree/v2/storefront/shipping_category_serializer.rb +0 -10
- data/app/serializers/spree/v2/storefront/shipping_method_serializer.rb +0 -12
- data/app/serializers/spree/v2/storefront/shipping_rate_serializer.rb +0 -26
- data/app/serializers/spree/v2/storefront/state_serializer.rb +0 -11
- data/app/serializers/spree/v2/storefront/stock_location_serializer.rb +0 -11
- data/app/serializers/spree/v2/storefront/store_credit_category_serializer.rb +0 -11
- data/app/serializers/spree/v2/storefront/store_credit_event_serializer.rb +0 -15
- data/app/serializers/spree/v2/storefront/store_credit_serializer.rb +0 -19
- data/app/serializers/spree/v2/storefront/store_credit_type_serializer.rb +0 -11
- data/app/serializers/spree/v2/storefront/store_serializer.rb +0 -18
- data/app/serializers/spree/v2/storefront/taxon_image_serializer.rb +0 -13
- data/app/serializers/spree/v2/storefront/taxon_serializer.rb +0 -55
- data/app/serializers/spree/v2/storefront/taxonomy_serializer.rb +0 -13
- data/app/serializers/spree/v2/storefront/user_serializer.rb +0 -33
- data/app/serializers/spree/v2/storefront/variant_serializer.rb +0 -58
- data/app/serializers/spree/v2/storefront/wished_item_serializer.rb +0 -29
- data/app/serializers/spree/v2/storefront/wishlist_serializer.rb +0 -17
- data/config/initializers/doorkeeper.rb +0 -50
- data/config/initializers/json_api_mime_types.rb +0 -8
- data/config/initializers/user_class_extensions.rb +0 -7
- data/db/migrate/20100107141738_add_api_key_to_spree_users.rb +0 -7
- data/db/migrate/20120411123334_resize_api_key_field.rb +0 -7
- data/db/migrate/20120530054546_rename_api_key_to_spree_api_key.rb +0 -7
- data/db/migrate/20131017162334_add_index_to_user_spree_api_key.rb +0 -7
- data/db/migrate/20180320110726_create_doorkeeper_tables.rb +0 -69
- data/db/migrate/20210727102516_change_integer_id_columns_type.rb +0 -9
- data/db/migrate/20210919183228_enable_polymorphic_resource_owner.rb +0 -21
- data/lib/generators/spree/api/install/install_generator.rb +0 -24
- data/lib/spree/api/testing_support/factories/oauth_application_factory.rb +0 -6
- data/lib/spree/api/testing_support/serializers.rb +0 -15
- data/lib/spree/api/testing_support/v2/base.rb +0 -13
- data/lib/spree/api/testing_support/v2/current_order.rb +0 -116
- data/lib/spree/api/testing_support/v2/platform_contexts.rb +0 -272
- data/lib/spree/api/testing_support/v2/serializers_params.rb +0 -16
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module JwtAuthentication
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
include Spree::Api::V3::ErrorHandler
|
|
8
|
+
|
|
9
|
+
USER_TYPE_CUSTOMER = 'customer'.freeze
|
|
10
|
+
USER_TYPE_ADMIN = 'admin'.freeze
|
|
11
|
+
|
|
12
|
+
included do
|
|
13
|
+
attr_reader :current_user
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Optional authentication - doesn't fail if no token
|
|
17
|
+
def authenticate_user
|
|
18
|
+
token = extract_token
|
|
19
|
+
return unless token.present?
|
|
20
|
+
|
|
21
|
+
payload = decode_jwt(token)
|
|
22
|
+
@current_user = find_user_from_payload(payload)
|
|
23
|
+
rescue JWT::DecodeError, JWT::ExpiredSignature, ActiveRecord::RecordNotFound => e
|
|
24
|
+
Rails.logger.debug { "JWT authentication failed: #{e.message}" }
|
|
25
|
+
@current_user = nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Required authentication - fails if no valid token
|
|
29
|
+
# Returns true if authenticated, false otherwise (also renders error and halts)
|
|
30
|
+
def require_authentication!
|
|
31
|
+
authenticate_user
|
|
32
|
+
|
|
33
|
+
return true if current_user
|
|
34
|
+
|
|
35
|
+
render_error(code: ErrorHandler::ERROR_CODES[:authentication_required], message: 'Authentication required', status: :unauthorized)
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
protected
|
|
40
|
+
|
|
41
|
+
# Generate a JWT token for a user
|
|
42
|
+
# @param user [Object] The user to generate a token for
|
|
43
|
+
# @param expiration [Integer] Time in seconds until expiration (default 24 hours)
|
|
44
|
+
# @return [String] The JWT token
|
|
45
|
+
def generate_jwt(user, expiration: 24.hours.to_i)
|
|
46
|
+
payload = {
|
|
47
|
+
user_id: user.id,
|
|
48
|
+
user_type: determine_user_type(user),
|
|
49
|
+
exp: Time.current.to_i + expiration
|
|
50
|
+
}
|
|
51
|
+
JWT.encode(payload, jwt_secret, 'HS256')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def extract_token
|
|
57
|
+
# Check Authorization header first
|
|
58
|
+
header = request.headers['Authorization']
|
|
59
|
+
return header.split(' ').last if header.present? && header.start_with?('Bearer ')
|
|
60
|
+
|
|
61
|
+
# Fallback to query param for special cases (e.g., digital downloads)
|
|
62
|
+
params[:token]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def decode_jwt(token)
|
|
66
|
+
JWT.decode(token, jwt_secret, true, algorithm: 'HS256').first
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def jwt_secret
|
|
70
|
+
Rails.application.credentials.jwt_secret_key || ENV['JWT_SECRET_KEY'] || Rails.application.secret_key_base
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def find_user_from_payload(payload)
|
|
74
|
+
user_id = payload['user_id']
|
|
75
|
+
user_type = payload['user_type'] || USER_TYPE_CUSTOMER
|
|
76
|
+
|
|
77
|
+
case user_type
|
|
78
|
+
when USER_TYPE_ADMIN
|
|
79
|
+
Spree.admin_user_class.find(user_id)
|
|
80
|
+
else
|
|
81
|
+
Spree.user_class.find(user_id)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def determine_user_type(user)
|
|
86
|
+
if user.is_a?(Spree.admin_user_class)
|
|
87
|
+
USER_TYPE_ADMIN
|
|
88
|
+
else
|
|
89
|
+
USER_TYPE_CUSTOMER
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module LocaleAndCurrency
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :set_market_from_country
|
|
9
|
+
before_action :set_locale_from_header
|
|
10
|
+
before_action :set_currency_from_header
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
# Override current_locale to check header first
|
|
16
|
+
def current_locale
|
|
17
|
+
@current_locale ||= begin
|
|
18
|
+
locale = locale_from_header || locale_from_params || default_locale
|
|
19
|
+
locale.to_s if supported_locale?(locale)
|
|
20
|
+
end || default_locale
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Override current_currency to check header first
|
|
24
|
+
def current_currency
|
|
25
|
+
@current_currency ||= begin
|
|
26
|
+
currency = currency_from_header || currency_from_params || current_store&.default_currency
|
|
27
|
+
currency = currency&.upcase
|
|
28
|
+
supported_currency?(currency) ? currency : current_store&.default_currency
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def set_locale_from_header
|
|
35
|
+
I18n.locale = current_locale
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def set_currency_from_header
|
|
39
|
+
Spree::Current.currency = current_currency
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def locale_from_header
|
|
43
|
+
request.headers['x-spree-locale'].presence
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def currency_from_header
|
|
47
|
+
request.headers['x-spree-currency'].presence
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def locale_from_params
|
|
51
|
+
params[:locale].presence
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def currency_from_params
|
|
55
|
+
params[:currency].presence
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def set_market_from_country
|
|
59
|
+
country_iso = request.headers['x-spree-country'].presence || params[:country].presence
|
|
60
|
+
return unless country_iso
|
|
61
|
+
|
|
62
|
+
country = Spree::Country.find_by(iso: country_iso.upcase)
|
|
63
|
+
return unless country
|
|
64
|
+
|
|
65
|
+
market = current_store&.market_for_country(country)
|
|
66
|
+
return unless market
|
|
67
|
+
|
|
68
|
+
Spree::Current.market = market
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module OrderConcern
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
# Allow access to order via order token for guests or authenticated users
|
|
8
|
+
# Expects @parent to be set to the order
|
|
9
|
+
def authorize_order_access!
|
|
10
|
+
authorize!(:update, @parent, order_token)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def set_parent
|
|
14
|
+
return if params[:order_id].blank?
|
|
15
|
+
|
|
16
|
+
@parent = order_scope.find_by_prefix_id!(params[:order_id])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def order_scope
|
|
20
|
+
base = current_store.orders
|
|
21
|
+
base = if current_user
|
|
22
|
+
base.where(user: current_user)
|
|
23
|
+
elsif order_token.present?
|
|
24
|
+
base.where(token: order_token)
|
|
25
|
+
else
|
|
26
|
+
base.none
|
|
27
|
+
end
|
|
28
|
+
base.preload_associations_lazily
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
protected
|
|
32
|
+
|
|
33
|
+
# Render the parent order as JSON using the order serializer.
|
|
34
|
+
# Use this when sub-resource mutations should return the updated order
|
|
35
|
+
# (e.g., line items, coupon codes, store credits).
|
|
36
|
+
def render_order(status: :ok)
|
|
37
|
+
render json: Spree.api.order_serializer.new(@parent.reload, params: serializer_params).to_h, status: status
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def order_token
|
|
41
|
+
# Check x-spree-order-token header first (lowercase for consistency)
|
|
42
|
+
header = request.headers['x-spree-order-token']
|
|
43
|
+
return header if header.present?
|
|
44
|
+
|
|
45
|
+
# Fallback to query params (support both token and order_token)
|
|
46
|
+
params[:order_token].presence || params[:token]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module ResourceSerializer
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
protected
|
|
8
|
+
|
|
9
|
+
# Serialize a single resource
|
|
10
|
+
def serialize_resource(resource)
|
|
11
|
+
serializer_class.new(resource, params: serializer_params).to_h
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Serialize a collection of resources
|
|
15
|
+
def serialize_collection(collection)
|
|
16
|
+
collection.map { |item| serializer_class.new(item, params: serializer_params).to_h }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Params passed to serializers
|
|
20
|
+
def serializer_params
|
|
21
|
+
{
|
|
22
|
+
currency: current_currency,
|
|
23
|
+
store: current_store,
|
|
24
|
+
user: current_user,
|
|
25
|
+
locale: current_locale,
|
|
26
|
+
includes: include_list
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Parse include parameter into list
|
|
31
|
+
# Supports: ?include=variants,images or ?includes=variants,images
|
|
32
|
+
def include_list
|
|
33
|
+
include_param = params[:include].presence || params[:includes].presence
|
|
34
|
+
return [] unless include_param
|
|
35
|
+
|
|
36
|
+
include_param.to_s.split(',').map(&:strip)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
class BaseController < ActionController::API
|
|
5
|
+
include ActiveStorage::SetCurrent
|
|
6
|
+
include CanCan::ControllerAdditions
|
|
7
|
+
include Spree::Core::ControllerHelpers::StrongParameters
|
|
8
|
+
include Spree::Core::ControllerHelpers::Store
|
|
9
|
+
include Spree::Core::ControllerHelpers::Locale
|
|
10
|
+
include Spree::Core::ControllerHelpers::Currency
|
|
11
|
+
include Spree::Api::V3::LocaleAndCurrency
|
|
12
|
+
include Spree::Api::V3::JwtAuthentication
|
|
13
|
+
include Spree::Api::V3::ApiKeyAuthentication
|
|
14
|
+
include Spree::Api::V3::ErrorHandler
|
|
15
|
+
include Spree::Api::V3::HttpCaching
|
|
16
|
+
include Spree::Api::V3::ResourceSerializer
|
|
17
|
+
include Pagy::Method
|
|
18
|
+
|
|
19
|
+
# Optional JWT authentication by default
|
|
20
|
+
before_action :authenticate_user
|
|
21
|
+
|
|
22
|
+
protected
|
|
23
|
+
|
|
24
|
+
# Override to use current_user from JWT authentication
|
|
25
|
+
def spree_current_user
|
|
26
|
+
current_user
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
alias try_spree_current_user spree_current_user
|
|
30
|
+
|
|
31
|
+
# CanCanCan ability
|
|
32
|
+
def current_ability
|
|
33
|
+
@current_ability ||= Spree::Ability.new(current_user, ability_options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def ability_options
|
|
37
|
+
{ store: current_store }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
class ResourceController < BaseController
|
|
5
|
+
before_action :set_parent
|
|
6
|
+
before_action :set_resource, only: [:show, :update, :destroy]
|
|
7
|
+
|
|
8
|
+
# GET /api/v3/resource
|
|
9
|
+
def index
|
|
10
|
+
@collection = collection
|
|
11
|
+
|
|
12
|
+
# Apply HTTP caching for guests
|
|
13
|
+
return unless cache_collection(@collection)
|
|
14
|
+
|
|
15
|
+
render json: {
|
|
16
|
+
data: serialize_collection(@collection),
|
|
17
|
+
meta: collection_meta(@collection)
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# GET /api/v3/resource/:id
|
|
22
|
+
def show
|
|
23
|
+
# Apply HTTP caching for guests
|
|
24
|
+
return unless cache_resource(@resource)
|
|
25
|
+
|
|
26
|
+
render json: serialize_resource(@resource)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# POST /api/v3/resource
|
|
30
|
+
def create
|
|
31
|
+
@resource = build_resource
|
|
32
|
+
authorize_resource!(@resource, :create)
|
|
33
|
+
|
|
34
|
+
if @resource.save
|
|
35
|
+
render json: serialize_resource(@resource), status: :created
|
|
36
|
+
else
|
|
37
|
+
render_errors(@resource.errors)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# PATCH /api/v3/resource/:id
|
|
42
|
+
def update
|
|
43
|
+
if @resource.update(permitted_params)
|
|
44
|
+
render json: serialize_resource(@resource)
|
|
45
|
+
else
|
|
46
|
+
render_errors(@resource.errors)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# DELETE /api/v3/resource/:id
|
|
51
|
+
def destroy
|
|
52
|
+
@resource.destroy
|
|
53
|
+
head :no_content
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
protected
|
|
57
|
+
|
|
58
|
+
# Override in subclass to set parent resource (e.g., @wishlist, @order)
|
|
59
|
+
# This runs before set_resource, allowing scope to use the parent
|
|
60
|
+
def set_parent
|
|
61
|
+
# No-op by default, override in nested resource controllers
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Sets the resource for show, update, destroy actions
|
|
65
|
+
# Always uses scope to respect controller's custom scoping
|
|
66
|
+
def set_resource
|
|
67
|
+
@resource = find_resource
|
|
68
|
+
authorize_resource!(@resource)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Builds a new resource, using parent association when @parent is set
|
|
72
|
+
def build_resource
|
|
73
|
+
if @parent.present?
|
|
74
|
+
@parent.send(parent_association).build(permitted_params)
|
|
75
|
+
else
|
|
76
|
+
model_class.new(permitted_params)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Finds a single resource within scope using prefixed ID
|
|
81
|
+
def find_resource
|
|
82
|
+
scope.find_by_prefix_id!(params[:id])
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Authorize resource with CanCanCan
|
|
86
|
+
def authorize_resource!(resource = @resource, action = action_name.to_sym)
|
|
87
|
+
authorize!(action, resource)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns ransack-filtered, sorted and paginated collection
|
|
91
|
+
# ar_lazy_preload handles automatic association preloading
|
|
92
|
+
# @return [ActiveRecord::Relation]
|
|
93
|
+
def collection
|
|
94
|
+
return @collection if @collection.present?
|
|
95
|
+
|
|
96
|
+
@search = scope.includes(collection_includes).
|
|
97
|
+
preload_associations_lazily.
|
|
98
|
+
ransack(ransack_params)
|
|
99
|
+
result = @search.result(distinct: collection_distinct?)
|
|
100
|
+
result = apply_collection_sort(result)
|
|
101
|
+
@pagy, @collection = pagy(result, limit: limit, page: page)
|
|
102
|
+
@collection
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Override in subclass to disable distinct (e.g., for custom sorting with computed columns)
|
|
106
|
+
def collection_distinct?
|
|
107
|
+
true
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Override in subclass to apply custom sorting
|
|
111
|
+
def apply_collection_sort(collection)
|
|
112
|
+
collection
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def collection_includes
|
|
116
|
+
[]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Ransack query parameters
|
|
120
|
+
def ransack_params
|
|
121
|
+
params[:q] || {}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Pagination parameters
|
|
125
|
+
def page
|
|
126
|
+
params[:page]&.to_i || 1
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def limit
|
|
130
|
+
limit_param = params[:per_page]&.to_i || params[:limit]&.to_i || 25
|
|
131
|
+
[limit_param, 100].min # Max 100 per page
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Metadata for collection responses
|
|
135
|
+
def collection_meta(_collection)
|
|
136
|
+
return {} unless @pagy
|
|
137
|
+
|
|
138
|
+
{
|
|
139
|
+
page: @pagy.page,
|
|
140
|
+
limit: @pagy.limit,
|
|
141
|
+
count: @pagy.count,
|
|
142
|
+
pages: @pagy.pages,
|
|
143
|
+
from: @pagy.from,
|
|
144
|
+
to: @pagy.to,
|
|
145
|
+
in: @pagy.in,
|
|
146
|
+
previous: @pagy.previous,
|
|
147
|
+
next: @pagy.next
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Base scope with store and ability
|
|
152
|
+
# When @parent is set (nested resources), uses parent association instead
|
|
153
|
+
def scope
|
|
154
|
+
base_scope = if @parent.present?
|
|
155
|
+
@parent.send(parent_association)
|
|
156
|
+
else
|
|
157
|
+
model_class.for_store(current_store)
|
|
158
|
+
end
|
|
159
|
+
base_scope = base_scope.accessible_by(current_ability, :show) unless @parent.present?
|
|
160
|
+
base_scope = base_scope.includes(scope_includes) if scope_includes.any?
|
|
161
|
+
base_scope = base_scope.preload_associations_lazily
|
|
162
|
+
model_class.include?(Spree::TranslatableResource) ? base_scope.i18n : base_scope
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Override to specify the association name on @parent
|
|
166
|
+
# Defaults to controller_name (e.g., 'wished_items' for WishlistItemsController)
|
|
167
|
+
def parent_association
|
|
168
|
+
controller_name
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Override in subclass to eager load associations that don't work well
|
|
172
|
+
# with ar_lazy_preload (e.g., prices, stock_items)
|
|
173
|
+
def scope_includes
|
|
174
|
+
[]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Override in subclass to define the model
|
|
178
|
+
def model_class
|
|
179
|
+
raise NotImplementedError, 'Subclass must implement model_class'
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Override in subclass to define the serializer class
|
|
183
|
+
def serializer_class
|
|
184
|
+
raise NotImplementedError, 'Subclass must implement serializer_class'
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Permit flat parameters based on model class
|
|
188
|
+
# Automatically infers attribute list from Spree::PermittedAttributes
|
|
189
|
+
# e.g., ProductsController -> Spree::PermittedAttributes.product_attributes
|
|
190
|
+
#
|
|
191
|
+
# Override in subclass for custom parameter handling
|
|
192
|
+
def permitted_params
|
|
193
|
+
params.permit(permitted_attributes)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Returns the permitted attributes list for the model
|
|
197
|
+
# Override in subclass for custom attributes
|
|
198
|
+
def permitted_attributes
|
|
199
|
+
Spree::PermittedAttributes.public_send(permitted_attributes_key)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Infers the PermittedAttributes key from model class
|
|
203
|
+
# e.g., Spree::Product -> :product_attributes
|
|
204
|
+
def permitted_attributes_key
|
|
205
|
+
:"#{model_class.model_name.element}_attributes"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Store
|
|
5
|
+
class AuthController < Store::BaseController
|
|
6
|
+
skip_before_action :authenticate_user, only: [:create, :register, :oauth_callback]
|
|
7
|
+
prepend_before_action :require_authentication!, only: [:refresh]
|
|
8
|
+
|
|
9
|
+
# POST /api/v3/store/auth/login
|
|
10
|
+
# Supports multiple authentication providers via :provider param
|
|
11
|
+
# Example:
|
|
12
|
+
# { "provider": "email", "email": "...", "password": "..." }
|
|
13
|
+
def create
|
|
14
|
+
strategy = authentication_strategy
|
|
15
|
+
return unless strategy # Error already rendered by determine_strategy
|
|
16
|
+
|
|
17
|
+
result = strategy.authenticate
|
|
18
|
+
|
|
19
|
+
if result.success?
|
|
20
|
+
user = result.value
|
|
21
|
+
token = generate_jwt(user)
|
|
22
|
+
render json: {
|
|
23
|
+
token: token,
|
|
24
|
+
user: user_serializer.new(user, params: serializer_params).to_h
|
|
25
|
+
}
|
|
26
|
+
else
|
|
27
|
+
render_error(
|
|
28
|
+
code: ERROR_CODES[:authentication_failed],
|
|
29
|
+
message: result.error,
|
|
30
|
+
status: :unauthorized
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# POST /api/v3/store/auth/register
|
|
36
|
+
def register
|
|
37
|
+
user = Spree.user_class.new(registration_params)
|
|
38
|
+
|
|
39
|
+
if user.save
|
|
40
|
+
token = generate_jwt(user)
|
|
41
|
+
render json: {
|
|
42
|
+
token: token,
|
|
43
|
+
user: user_serializer.new(user, params: serializer_params).to_h
|
|
44
|
+
}, status: :created
|
|
45
|
+
else
|
|
46
|
+
render_errors(user.errors)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# POST /api/v3/store/auth/refresh
|
|
51
|
+
def refresh
|
|
52
|
+
token = generate_jwt(current_user)
|
|
53
|
+
render json: {
|
|
54
|
+
token: token,
|
|
55
|
+
user: user_serializer.new(current_user, params: serializer_params).to_h
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# POST /api/v3/store/auth/oauth/callback
|
|
60
|
+
# OAuth callback endpoint for server-side OAuth flows
|
|
61
|
+
def oauth_callback
|
|
62
|
+
# This endpoint is designed for OAuth flows where the server
|
|
63
|
+
# exchanges the authorization code for an access token
|
|
64
|
+
# For client-side flows, use the regular /login endpoint with id_token
|
|
65
|
+
|
|
66
|
+
strategy = authentication_strategy
|
|
67
|
+
return unless strategy # Error already rendered by determine_strategy
|
|
68
|
+
|
|
69
|
+
result = strategy.authenticate
|
|
70
|
+
|
|
71
|
+
if result.success?
|
|
72
|
+
user = result.value
|
|
73
|
+
token = generate_jwt(user)
|
|
74
|
+
render json: {
|
|
75
|
+
token: token,
|
|
76
|
+
user: user_serializer.new(user, params: serializer_params).to_h
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
render_error(
|
|
80
|
+
code: ERROR_CODES[:authentication_failed],
|
|
81
|
+
message: result.error,
|
|
82
|
+
status: :unauthorized
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
protected
|
|
88
|
+
|
|
89
|
+
def serializer_params
|
|
90
|
+
{
|
|
91
|
+
store: current_store,
|
|
92
|
+
locale: current_locale,
|
|
93
|
+
currency: current_currency,
|
|
94
|
+
user: current_user,
|
|
95
|
+
includes: []
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def authentication_strategy
|
|
102
|
+
strategy_class = determine_strategy
|
|
103
|
+
strategy_class.new(
|
|
104
|
+
params: params,
|
|
105
|
+
request_env: request.headers.env,
|
|
106
|
+
user_class: Spree.user_class
|
|
107
|
+
)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def determine_strategy
|
|
111
|
+
provider = params[:provider].presence || 'email'
|
|
112
|
+
provider_key = provider.to_sym
|
|
113
|
+
|
|
114
|
+
# Retrieve pre-loaded strategy class from configuration
|
|
115
|
+
strategy_class = Rails.application.config.spree.store_authentication_strategies[provider_key]
|
|
116
|
+
|
|
117
|
+
unless strategy_class
|
|
118
|
+
render_error(
|
|
119
|
+
code: ERROR_CODES[:invalid_provider],
|
|
120
|
+
message: "Unsupported authentication provider: #{provider}",
|
|
121
|
+
status: :bad_request
|
|
122
|
+
)
|
|
123
|
+
return nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
strategy_class
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def registration_params
|
|
130
|
+
params.permit(:email, :password, :password_confirmation, :first_name, :last_name)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def user_serializer
|
|
134
|
+
Spree.api.customer_serializer
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|