spree_api 3.6.6 → 3.7.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spree/api/main.js +36 -0
- data/app/assets/javascripts/spree/api/storefront/cart.js +49 -0
- data/app/controllers/concerns/spree/api/v2/storefront/order_concern.rb +48 -0
- data/app/controllers/spree/api/errors_controller.rb +9 -0
- data/app/controllers/spree/api/v1/checkouts_controller.rb +12 -0
- data/app/controllers/spree/api/v1/customer_returns_controller.rb +1 -0
- data/app/controllers/spree/api/v1/line_items_controller.rb +11 -10
- data/app/controllers/spree/api/v1/orders_controller.rb +6 -6
- data/app/controllers/spree/api/v1/product_properties_controller.rb +1 -0
- data/app/controllers/spree/api/v1/products_controller.rb +6 -6
- data/app/controllers/spree/api/v1/promotions_controller.rb +1 -0
- data/app/controllers/spree/api/v1/reimbursements_controller.rb +1 -0
- data/app/controllers/spree/api/v1/shipments_controller.rb +12 -3
- data/app/controllers/spree/api/v1/variants_controller.rb +5 -3
- data/app/controllers/spree/api/v2/base_controller.rb +94 -0
- data/app/controllers/spree/api/v2/storefront/account/credit_cards_controller.rb +55 -0
- data/app/controllers/spree/api/v2/storefront/account_controller.rb +33 -0
- data/app/controllers/spree/api/v2/storefront/cart_controller.rb +124 -0
- data/app/controllers/spree/api/v2/storefront/checkout_controller.rb +108 -0
- data/app/controllers/spree/api/v2/storefront/countries_controller.rb +57 -0
- data/app/controllers/spree/api/v2/storefront/products_controller.rb +87 -0
- data/app/controllers/spree/api/v2/storefront/taxons_controller.rb +82 -0
- data/app/helpers/spree/api/api_helpers.rb +1 -1
- data/app/helpers/spree/api/v2/collection_options_helpers.rb +37 -0
- data/app/models/doorkeeper/access_grant_decorator.rb +3 -0
- data/app/models/doorkeeper/access_token_decorator.rb +3 -0
- data/app/models/doorkeeper/application_decorator.rb +3 -0
- data/app/serializers/spree/v2/storefront/account/credit_card_serializer.rb +16 -0
- data/app/serializers/spree/v2/storefront/account_serializer.rb +29 -0
- data/app/serializers/spree/v2/storefront/address_serializer.rb +14 -0
- data/app/serializers/spree/v2/storefront/base_serializer.rb +9 -0
- data/app/serializers/spree/v2/storefront/cart_serializer.rb +40 -0
- data/app/serializers/spree/v2/storefront/country_serializer.rb +18 -0
- data/app/serializers/spree/v2/storefront/image_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/line_item_serializer.rb +17 -0
- data/app/serializers/spree/v2/storefront/option_type_serializer.rb +13 -0
- data/app/serializers/spree/v2/storefront/option_value_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/payment_method_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/payment_serializer.rb +12 -0
- data/app/serializers/spree/v2/storefront/product_property_serializer.rb +14 -0
- data/app/serializers/spree/v2/storefront/product_serializer.rb +35 -0
- data/app/serializers/spree/v2/storefront/promotion_serializer.rb +12 -0
- data/app/serializers/spree/v2/storefront/shipment_serializer.rb +16 -0
- data/app/serializers/spree/v2/storefront/shipping_rate_serializer.rb +14 -0
- data/app/serializers/spree/v2/storefront/state_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/taxon_image_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/taxon_serializer.rb +28 -0
- data/app/serializers/spree/v2/storefront/taxonomy_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/user_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/variant_serializer.rb +21 -0
- data/app/views/spree/api/v1/orders/order.v1.rabl +1 -1
- data/config/initializers/doorkeeper.rb +20 -0
- data/config/locales/en.yml +4 -0
- data/config/routes.rb +51 -3
- data/db/migrate/20180320110726_create_doorkeeper_tables.rb +69 -0
- data/docs/oauth/index.yml +77 -0
- data/docs/v2/storefront/index.yaml +2444 -0
- data/lib/spree/api/engine.rb +9 -2
- data/lib/spree_api.rb +2 -0
- data/spree_api.gemspec +5 -1
- metadata +92 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 966dd14cce417e7119d423b7b05d052b85e0f0372f7bcb04c966f239cf8aafae
|
4
|
+
data.tar.gz: e6903c09540a78763157058235d32dc07405747646dc24f2b980ab7df19249d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8ad9bc26e1c98498461bd06975be490627cb53857cb2ca64a01a40e410e866978c7387ee46102d1a39b96f0f751bd14d2da33c3f8928617fb28e12d4b37e4cb
|
7
|
+
data.tar.gz: cfc7d9802acc6f4a82bf5ccc56028ed303663fe1495292d2f0a1c507a7da63adcd82dbfbaea29fcf3c334e3c17aab63a811487d33a75c29f1a020671de62d06c
|
@@ -0,0 +1,36 @@
|
|
1
|
+
//= require spree
|
2
|
+
|
3
|
+
var SpreeAPI = {
|
4
|
+
oauthToken: null, // user Bearer token to authorize operations for the given user
|
5
|
+
orderToken: null // order token to authorize operations on current order (cart)
|
6
|
+
}
|
7
|
+
|
8
|
+
SpreeAPI.Storefront = {}
|
9
|
+
SpreeAPI.Platform = {}
|
10
|
+
|
11
|
+
// API routes
|
12
|
+
Spree.routes.api_v2_storefront_cart_create = Spree.pathFor('api/v2/storefront/cart')
|
13
|
+
Spree.routes.api_v2_storefront_cart_add_item = Spree.pathFor('api/v2/storefront/cart/add_item')
|
14
|
+
Spree.routes.api_v2_storefront_cart_apply_coupon_code = Spree.pathFor('api/v2/storefront/cart/apply_coupon_code')
|
15
|
+
|
16
|
+
// helpers
|
17
|
+
SpreeAPI.handle500error = function () {
|
18
|
+
alert('Internal Server Error')
|
19
|
+
}
|
20
|
+
|
21
|
+
SpreeAPI.prepareHeaders = function (headers) {
|
22
|
+
if (typeof headers === 'undefined') {
|
23
|
+
headers = {}
|
24
|
+
}
|
25
|
+
|
26
|
+
// if signed in we need to pass the Bearer authorization token
|
27
|
+
// so backend will recognize that actions are authorized in scope of this user
|
28
|
+
if (SpreeAPI.oauthToken) {
|
29
|
+
headers['Authorization'] = 'Bearer ' + SpreeAPI.oauthToken
|
30
|
+
}
|
31
|
+
|
32
|
+
// default headers, required for POST/PATCH/DELETE requests
|
33
|
+
headers['Accept'] = 'application/json'
|
34
|
+
headers['Content-Type'] = 'application/json'
|
35
|
+
return headers
|
36
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
//= require spree/api/main
|
2
|
+
|
3
|
+
SpreeAPI.Storefront.createCart = function (successCallback, failureCallback) {
|
4
|
+
fetch(Spree.routes.api_v2_storefront_cart_create, {
|
5
|
+
method: 'POST',
|
6
|
+
headers: SpreeAPI.prepareHeaders()
|
7
|
+
}).then(function (response) {
|
8
|
+
switch (response.status) {
|
9
|
+
case 422:
|
10
|
+
response.json().then(function (json) { failureCallback(json.error) })
|
11
|
+
break
|
12
|
+
case 500:
|
13
|
+
SpreeAPI.handle500error()
|
14
|
+
break
|
15
|
+
case 201:
|
16
|
+
response.json().then(function (json) {
|
17
|
+
SpreeAPI.orderToken = json.data.attributes.token
|
18
|
+
successCallback()
|
19
|
+
})
|
20
|
+
break
|
21
|
+
}
|
22
|
+
})
|
23
|
+
}
|
24
|
+
|
25
|
+
SpreeAPI.Storefront.addToCart = function (variantId, quantity, options, successCallback, failureCallback) {
|
26
|
+
fetch(Spree.routes.api_v2_storefront_cart_add_item, {
|
27
|
+
method: 'POST',
|
28
|
+
headers: SpreeAPI.prepareHeaders({ 'X-Spree-Order-Token': SpreeAPI.orderToken }),
|
29
|
+
body: JSON.stringify({
|
30
|
+
variant_id: variantId,
|
31
|
+
quantity: quantity,
|
32
|
+
options: options
|
33
|
+
})
|
34
|
+
}).then(function (response) {
|
35
|
+
switch (response.status) {
|
36
|
+
case 422:
|
37
|
+
response.json().then(function (json) { failureCallback(json.error) })
|
38
|
+
break
|
39
|
+
case 500:
|
40
|
+
SpreeAPI.handle500error()
|
41
|
+
break
|
42
|
+
case 200:
|
43
|
+
response.json().then(function (json) {
|
44
|
+
successCallback(json.data)
|
45
|
+
})
|
46
|
+
break
|
47
|
+
}
|
48
|
+
})
|
49
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Storefront
|
5
|
+
module OrderConcern
|
6
|
+
private
|
7
|
+
|
8
|
+
def render_order(result)
|
9
|
+
if result.success?
|
10
|
+
render_serialized_payload { serialized_current_order }
|
11
|
+
else
|
12
|
+
render_error_payload(result.error)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def ensure_order
|
17
|
+
raise ActiveRecord::RecordNotFound if spree_current_order.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def order_token
|
21
|
+
request.headers['X-Spree-Order-Token'] || params[:order_token]
|
22
|
+
end
|
23
|
+
|
24
|
+
def spree_current_order
|
25
|
+
@spree_current_order ||= find_spree_current_order
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_spree_current_order
|
29
|
+
Spree::Orders::FindCurrent.new.execute(
|
30
|
+
store: spree_current_store,
|
31
|
+
user: spree_current_user,
|
32
|
+
token: order_token,
|
33
|
+
currency: current_currency
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def serialize_order(order)
|
38
|
+
dependencies[:cart_serializer].new(order.reload, include: resource_includes, fields: sparse_fields).serializable_hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def serialized_current_order
|
42
|
+
serialize_order(spree_current_order)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -32,6 +32,8 @@ module Spree
|
|
32
32
|
@order.associate_user!(Spree.user_class.find(user_id))
|
33
33
|
end
|
34
34
|
|
35
|
+
log_state_changes if params[:state]
|
36
|
+
|
35
37
|
return if after_update_attributes
|
36
38
|
|
37
39
|
if @order.completed? || @order.next
|
@@ -91,6 +93,16 @@ module Spree
|
|
91
93
|
false
|
92
94
|
end
|
93
95
|
|
96
|
+
def log_state_changes
|
97
|
+
if @order.previous_changes[:state]
|
98
|
+
@order.log_state_changes(
|
99
|
+
state_name: 'order',
|
100
|
+
old_state: @order.previous_changes[:state].first,
|
101
|
+
new_state: @order.previous_changes[:state].last
|
102
|
+
)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
94
106
|
def order_id
|
95
107
|
super || params[:id]
|
96
108
|
end
|
@@ -10,12 +10,11 @@ module Spree
|
|
10
10
|
|
11
11
|
def create
|
12
12
|
variant = Spree::Variant.find(params[:line_item][:variant_id])
|
13
|
-
@line_item = order.contents.add(
|
14
|
-
variant,
|
15
|
-
params[:line_item][:quantity] || 1,
|
16
|
-
line_item_params[:options] || {}
|
17
|
-
)
|
18
13
|
|
14
|
+
@line_item = Spree::Cart::AddItem.call(order: order,
|
15
|
+
variant: variant,
|
16
|
+
quantity: params[:line_item][:quantity],
|
17
|
+
options: line_item_params[:options]).value
|
19
18
|
if @line_item.errors.empty?
|
20
19
|
respond_with(@line_item, status: 201, default_template: :show)
|
21
20
|
else
|
@@ -25,7 +24,8 @@ module Spree
|
|
25
24
|
|
26
25
|
def update
|
27
26
|
@line_item = find_line_item
|
28
|
-
|
27
|
+
|
28
|
+
if Spree::Cart::Update.call(order: @order, params: line_items_attributes).success?
|
29
29
|
@line_item.reload
|
30
30
|
respond_with(@line_item, default_template: :show)
|
31
31
|
else
|
@@ -35,7 +35,8 @@ module Spree
|
|
35
35
|
|
36
36
|
def destroy
|
37
37
|
@line_item = find_line_item
|
38
|
-
|
38
|
+
Spree::Cart::RemoveLineItem.new.call(order: @order, line_item: @line_item)
|
39
|
+
|
39
40
|
respond_with(@line_item, status: 204)
|
40
41
|
end
|
41
42
|
|
@@ -54,9 +55,9 @@ module Spree
|
|
54
55
|
|
55
56
|
def line_items_attributes
|
56
57
|
{ line_items_attributes: {
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
id: params[:id],
|
59
|
+
quantity: params[:line_item][:quantity],
|
60
|
+
options: line_item_params[:options] || {}
|
60
61
|
} }
|
61
62
|
end
|
62
63
|
|
@@ -30,10 +30,10 @@ module Spree
|
|
30
30
|
authorize! :create, Spree::Order
|
31
31
|
if can?(:admin, Spree::Order)
|
32
32
|
order_user = if @current_user_roles.include?('admin') && order_params[:user_id]
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
Spree.user_class.find(order_params[:user_id])
|
34
|
+
else
|
35
|
+
current_api_user
|
36
|
+
end
|
37
37
|
|
38
38
|
import_params = if @current_user_roles.include?('admin')
|
39
39
|
params[:order].present? ? params[:order].permit! : {}
|
@@ -46,7 +46,7 @@ module Spree
|
|
46
46
|
respond_with(@order, default_template: :show, status: 201)
|
47
47
|
else
|
48
48
|
@order = Spree::Order.create!(user: current_api_user, store: current_store)
|
49
|
-
if @order
|
49
|
+
if Cart::Update.call(order: @order, params: order_params).success?
|
50
50
|
respond_with(@order, default_template: :show, status: 201)
|
51
51
|
else
|
52
52
|
invalid_resource!(@order)
|
@@ -75,7 +75,7 @@ module Spree
|
|
75
75
|
find_order(true)
|
76
76
|
authorize! :update, @order, order_token
|
77
77
|
|
78
|
-
if @order
|
78
|
+
if Cart::Update.call(order: @order, params: order_params).success?
|
79
79
|
user_id = params[:order][:user_id]
|
80
80
|
if current_api_user.has_spree_role?('admin') && user_id
|
81
81
|
@order.associate_user!(Spree.user_class.find(user_id))
|
@@ -59,6 +59,7 @@ module Spree
|
|
59
59
|
@product_property ||= @product.product_properties.find_by(id: params[:id])
|
60
60
|
@product_property ||= @product.product_properties.includes(:property).where(spree_properties: { name: params[:id] }).first
|
61
61
|
raise ActiveRecord::RecordNotFound unless @product_property
|
62
|
+
|
62
63
|
authorize! :read, @product_property
|
63
64
|
end
|
64
65
|
end
|
@@ -5,11 +5,11 @@ module Spree
|
|
5
5
|
before_action :find_product, only: [:update, :show, :destroy]
|
6
6
|
|
7
7
|
def index
|
8
|
-
if params[:ids]
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
@products = if params[:ids]
|
9
|
+
product_scope.where(id: params[:ids].split(',').flatten)
|
10
|
+
else
|
11
|
+
product_scope.ransack(params[:q]).result
|
12
|
+
end
|
13
13
|
|
14
14
|
@products = @products.distinct.page(params[:page]).per(params[:per_page])
|
15
15
|
expires_in 15.minutes, public: true
|
@@ -104,7 +104,7 @@ module Spree
|
|
104
104
|
:variants
|
105
105
|
else
|
106
106
|
:variants_attributes
|
107
|
-
|
107
|
+
end
|
108
108
|
|
109
109
|
params.require(:product).permit(
|
110
110
|
variants_key => [permitted_variant_attributes, :id]
|
@@ -24,7 +24,11 @@ module Spree
|
|
24
24
|
authorize! :create, Shipment
|
25
25
|
quantity = params[:quantity].to_i
|
26
26
|
@shipment = @order.shipments.create(stock_location_id: params.fetch(:stock_location_id))
|
27
|
-
|
27
|
+
|
28
|
+
@line_item = Spree::Cart::AddItem.call(order: @order,
|
29
|
+
variant: variant,
|
30
|
+
quantity: quantity,
|
31
|
+
options: { shipment: @shipment }).value
|
28
32
|
|
29
33
|
respond_with(@shipment.reload, default_template: :show)
|
30
34
|
end
|
@@ -55,7 +59,11 @@ module Spree
|
|
55
59
|
def add
|
56
60
|
quantity = params[:quantity].to_i
|
57
61
|
|
58
|
-
|
62
|
+
Spree::Cart::AddItem.call(order: @shipment.order,
|
63
|
+
variant: variant,
|
64
|
+
quantity: quantity,
|
65
|
+
options: { shipment: @shipment })
|
66
|
+
|
59
67
|
respond_with(@shipment, default_template: :show)
|
60
68
|
end
|
61
69
|
|
@@ -65,7 +73,8 @@ module Spree
|
|
65
73
|
else
|
66
74
|
@shipment.inventory_units_for(variant).sum(:quantity)
|
67
75
|
end
|
68
|
-
|
76
|
+
|
77
|
+
Spree::Cart::RemoveItem.call(order: @shipment.order, variant: variant, quantity: quantity, options: { shipment: @shipment })
|
69
78
|
|
70
79
|
if @shipment.inventory_units.any?
|
71
80
|
@shipment.reload
|
@@ -48,8 +48,10 @@ module Spree
|
|
48
48
|
private
|
49
49
|
|
50
50
|
def product
|
51
|
-
|
52
|
-
|
51
|
+
if params[:product_id]
|
52
|
+
@product ||= Spree::Product.accessible_by(current_ability, :read).
|
53
|
+
friendly.find(params[:product_id])
|
54
|
+
end
|
53
55
|
end
|
54
56
|
|
55
57
|
def scope
|
@@ -63,7 +65,7 @@ module Spree
|
|
63
65
|
variants = variants.with_deleted
|
64
66
|
end
|
65
67
|
|
66
|
-
variants.accessible_by(current_ability, :read)
|
68
|
+
variants.eligible.accessible_by(current_ability, :read)
|
67
69
|
end
|
68
70
|
|
69
71
|
def variant_params
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
class BaseController < ActionController::API
|
5
|
+
include CanCan::ControllerAdditions
|
6
|
+
include Spree::Core::ControllerHelpers::StrongParameters
|
7
|
+
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
|
8
|
+
rescue_from CanCan::AccessDenied, with: :access_denied
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def render_serialized_payload(status = 200)
|
13
|
+
render json: yield, status: status
|
14
|
+
rescue ArgumentError => exception
|
15
|
+
render_error_payload(exception.message, 400)
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_error_payload(error, status = 422)
|
19
|
+
if error.is_a?(Struct)
|
20
|
+
render json: { error: error.to_s, errors: error.to_h }, status: status
|
21
|
+
elsif error.is_a?(String)
|
22
|
+
render json: { error: error }, status: status
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def spree_current_store
|
27
|
+
@spree_current_store ||= Spree::Store.current(request.env['SERVER_NAME'])
|
28
|
+
end
|
29
|
+
|
30
|
+
def spree_current_user
|
31
|
+
@spree_current_user ||= Spree.user_class.find_by(id: doorkeeper_token.resource_owner_id) if doorkeeper_token
|
32
|
+
end
|
33
|
+
|
34
|
+
def spree_authorize!(action, subject, *args)
|
35
|
+
authorize!(action, subject, *args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def require_spree_current_user
|
39
|
+
raise CanCan::AccessDenied if spree_current_user.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
# Needs to be overriden so that we use Spree's Ability rather than anyone else's.
|
43
|
+
def current_ability
|
44
|
+
@current_ability ||= Spree::Ability.new(spree_current_user)
|
45
|
+
end
|
46
|
+
|
47
|
+
def request_includes
|
48
|
+
# if API user want's to receive only the bare-minimum
|
49
|
+
# the API will return only the main resource without any included
|
50
|
+
if params[:include]&.blank?
|
51
|
+
[]
|
52
|
+
elsif params[:include].present?
|
53
|
+
params[:include].split(',')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def resource_includes
|
58
|
+
(request_includes || default_resource_includes).map(&:intern)
|
59
|
+
end
|
60
|
+
|
61
|
+
# overwrite this method in your controllers to set JSON API default include value
|
62
|
+
# https://jsonapi.org/format/#fetching-includes
|
63
|
+
# eg.:
|
64
|
+
# %w[images variants]
|
65
|
+
# ['variant.images', 'line_items']
|
66
|
+
def default_resource_includes
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
|
70
|
+
def sparse_fields
|
71
|
+
return unless params[:fields]&.respond_to?(:each)
|
72
|
+
|
73
|
+
fields = {}
|
74
|
+
params[:fields].
|
75
|
+
select { |_, v| v.is_a?(String) }.
|
76
|
+
each { |type, values| fields[type.intern] = values.split(',').map(&:intern) }
|
77
|
+
fields.presence
|
78
|
+
end
|
79
|
+
|
80
|
+
def current_currency
|
81
|
+
spree_current_store.default_currency || Spree::Config[:currency]
|
82
|
+
end
|
83
|
+
|
84
|
+
def record_not_found
|
85
|
+
render_error_payload(I18n.t(:resource_not_found, scope: 'spree.api'), 404)
|
86
|
+
end
|
87
|
+
|
88
|
+
def access_denied(exception)
|
89
|
+
render_error_payload(exception.message, 403)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|