spree_api 2.1.12 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/app/controllers/spree/api/addresses_controller.rb +25 -10
  4. data/app/controllers/spree/api/base_controller.rb +18 -29
  5. data/app/controllers/spree/api/checkouts_controller.rb +23 -29
  6. data/app/controllers/spree/api/classifications_controller.rb +18 -0
  7. data/app/controllers/spree/api/line_items_controller.rb +13 -1
  8. data/app/controllers/spree/api/option_types_controller.rb +2 -2
  9. data/app/controllers/spree/api/option_values_controller.rb +1 -1
  10. data/app/controllers/spree/api/orders_controller.rb +12 -34
  11. data/app/controllers/spree/api/products_controller.rb +22 -23
  12. data/app/controllers/spree/api/taxons_controller.rb +9 -0
  13. data/app/controllers/spree/api/variants_controller.rb +1 -1
  14. data/app/helpers/spree/api/api_helpers.rb +5 -3
  15. data/app/models/spree/order_decorator.rb +2 -11
  16. data/app/views/spree/api/line_items/show.v1.rabl +4 -0
  17. data/app/views/spree/api/orders/order.v1.rabl +0 -1
  18. data/app/views/spree/api/products/show.v1.rabl +7 -10
  19. data/app/views/spree/api/promotions/handler.v1.rabl +4 -0
  20. data/app/views/spree/api/variants/index.v1.rabl +1 -1
  21. data/app/views/spree/api/variants/show.v1.rabl +2 -3
  22. data/app/views/spree/api/variants/variant.v1.rabl +2 -0
  23. data/app/views/spree/api/variants/{big_variant.v1.rabl → variant_full.v1.rabl} +0 -0
  24. data/config/routes.rb +6 -4
  25. data/lib/spree/api/controller_setup.rb +0 -1
  26. data/lib/spree/api/testing_support/helpers.rb +1 -0
  27. data/spec/controllers/spree/api/addresses_controller_spec.rb +57 -31
  28. data/spec/controllers/spree/api/base_controller_spec.rb +0 -36
  29. data/spec/controllers/spree/api/checkouts_controller_spec.rb +8 -41
  30. data/spec/controllers/spree/api/classifications_controller_spec.rb +38 -0
  31. data/spec/controllers/spree/api/line_items_controller_spec.rb +10 -21
  32. data/spec/controllers/spree/api/option_values_controller_spec.rb +0 -7
  33. data/spec/controllers/spree/api/orders_controller_spec.rb +24 -121
  34. data/spec/controllers/spree/api/products_controller_spec.rb +26 -48
  35. data/spec/controllers/spree/api/promotion_application_spec.rb +48 -0
  36. data/spec/controllers/spree/api/shipments_controller_spec.rb +1 -22
  37. data/spec/controllers/spree/api/unauthenticated_products_controller_spec.rb +1 -1
  38. data/spec/controllers/spree/api/users_controller_spec.rb +3 -2
  39. data/spec/controllers/spree/api/variants_controller_spec.rb +13 -7
  40. data/spec/models/spree/order_spec.rb +3 -28
  41. metadata +12 -7
  42. data/app/views/spree/api/orders/apply_coupon_code.v1.rabl +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a08ed7200c466d0fd9ec9f30a023e25762b0818
4
- data.tar.gz: 7e46adff6873f64f2cbfeeb272ea0b9a1cd72ed5
3
+ metadata.gz: 4e802b7e59fd0ecbd4af2cdaae70e049780d4f2f
4
+ data.tar.gz: 296836af524b2aff916ac7f7d5fa6a4211997194
5
5
  SHA512:
6
- metadata.gz: e2b70fb725a233dca2913251d058a3ff0ede0ba0f6490eaba055e439a96764db21eaa0a4b2206ad4538cebce2a61fa9215b76cde3d3b50e9463992559e3f713e
7
- data.tar.gz: d822c1904e28486d7d6e79e6e4d485a32457bfb03daf035ba039bdaa6c80343a2368bc3ac0c638e2f7eb1e3e3676b12860eaac33823faabef618b75a5a74c701
6
+ metadata.gz: fce325a070ade67fa025cbbc9026736ab956537adfa2fb8bf3858cb1fc2eab7c827f1ea543db9d9f5a35864d718fe94ef37cb92f37cfef96faf460bc641584e7
7
+ data.tar.gz: 7d346032e759b80968da1deb2081c73d266f97853a388461b90febddcfa510baa7b6ed366d11eac6866fe4dcaa8de126a6e788ce11bdfd673b1b76c4b12b895d
data/CHANGELOG.md CHANGED
@@ -1 +1,51 @@
1
- ## Spree 2.1.5 (unreleased) ##
1
+ ## Spree 2.2.0 (unreleased) ##
2
+
3
+ * Api requires authentication by default now
4
+
5
+ Peter Berkenbosch
6
+
7
+ * Improve products_controller #create and #update for better support to create
8
+ and update variants, option types and option values.
9
+ See #4172 and #4240
10
+
11
+ Bruno Buccolo / Washington Luiz / John Dyer
12
+
13
+ * ApiHelpers attributes can now be extended without overriding instance
14
+ methods. By using the same approach in PermittedAttributes. e.g.
15
+
16
+ Spree::Api::ApiHelpers.order_attributes.push :locked_at
17
+
18
+ Washington Luiz
19
+
20
+ * Admin users can set the order channel when importing orders. By sing the
21
+ channel attribute on Order model
22
+
23
+ Washington Luiz
24
+
25
+ * Cached products/show template, which can lead to drastically (65x) faster loading times on product requests. 806319709c4ce9a3d0026e00ec2d07372f51cdb8
26
+
27
+ Ryan Bigg
28
+
29
+ * The parts that make up an order's response from /api/orders/:num are cached, which can lead to a 5x improvement of speed for this API endpoint. 80ffb1e739606ac02ac86336ac13a51583bcc225
30
+
31
+ Ryan Bigg
32
+
33
+ * Cached variant objects which can lead to slightly faster loading times (4x) for each variant.
34
+
35
+ Ryan Bigg
36
+
37
+ * Added a route to allow for /api/variants/:id requests
38
+
39
+ Ryan Bigg
40
+
41
+ * Products response now contains a master variant separately from all the other variants. Previously all variants were grouped together.
42
+
43
+ Ryan Bigg
44
+
45
+ * Added API endpoint to retrieve a user's orders: /api/orders/mine. #4022
46
+
47
+ Richard Nuno
48
+
49
+ * Order token can now be passed as a header: `X-Spree-Order-Token`. #4148
50
+
51
+ Lucjan Suski
@@ -4,14 +4,12 @@ module Spree
4
4
  before_filter :find_order
5
5
 
6
6
  def show
7
- authorize! :read, @order, order_token
8
- find_address
7
+ load_and_authorize_address(:read)
9
8
  respond_with(@address)
10
9
  end
11
10
 
12
11
  def update
13
- authorize! :update, @order, order_token
14
- find_address
12
+ load_and_authorize_address(:update)
15
13
 
16
14
  if @address.update_attributes(address_params)
17
15
  respond_with(@address, :default_template => :show)
@@ -26,16 +24,33 @@ module Spree
26
24
  end
27
25
 
28
26
  def find_order
29
- @order = Spree::Order.find_by!(number: params[:order_id])
27
+ @order = Spree::Order.find_by!(number: params[:order_id]) if params[:order_id]
30
28
  end
31
29
 
32
30
  def find_address
33
- @address = if @order.bill_address_id == params[:id].to_i
34
- @order.bill_address
35
- elsif @order.ship_address_id == params[:id].to_i
36
- @order.ship_address
31
+ if @order
32
+ @address = if @order.bill_address_id == params[:id].to_i
33
+ @order.bill_address
34
+ elsif @order.ship_address_id == params[:id].to_i
35
+ @order.ship_address
36
+ else
37
+ raise CanCan::AccessDenied
38
+ end
37
39
  else
38
- raise CanCan::AccessDenied
40
+ @address = Spree::Address.find(params[:id])
41
+ end
42
+ end
43
+
44
+ def order_token
45
+ request.headers["X-Spree-Order-Token"] || params[:order_token]
46
+ end
47
+
48
+ def load_and_authorize_address(permission)
49
+ find_address
50
+ if @order
51
+ authorize! permission, @order, order_token
52
+ else
53
+ authorize! permission, @address
39
54
  end
40
55
  end
41
56
  end
@@ -9,18 +9,11 @@ module Spree
9
9
  include Spree::Core::ControllerHelpers::StrongParameters
10
10
  include ::ActionController::Head
11
11
  include ::ActionController::ConditionalGet
12
- include ::ActionController::Redirecting
13
- include Spree::Core::Engine.routes.url_helpers
14
-
15
- self.responder = Spree::Api::Responders::AppResponder
16
-
17
- respond_to :json
18
12
 
19
13
  attr_accessor :current_api_user
20
14
 
21
15
  before_filter :set_content_type
22
- before_filter :load_user
23
- before_filter :authorize_for_order, :if => Proc.new { order_token.present? }
16
+ before_filter :check_for_user_or_api_key, :if => :requires_authentication?
24
17
  before_filter :authenticate_user
25
18
  after_filter :set_jsonp_format
26
19
 
@@ -51,7 +44,7 @@ module Spree
51
44
  # users should be able to set price when importing orders via api
52
45
  def permitted_line_item_attributes
53
46
  if current_api_user.has_spree_role?("admin")
54
- super + [:price, :variant_id, :sku]
47
+ super << [:price, :variant_id, :sku]
55
48
  else
56
49
  super
57
50
  end
@@ -62,23 +55,28 @@ module Spree
62
55
  def set_content_type
63
56
  content_type = case params[:format]
64
57
  when "json"
65
- "application/json; charset=utf-8"
58
+ "application/json"
66
59
  when "xml"
67
- "text/xml; charset=utf-8"
60
+ "text/xml"
68
61
  end
69
62
  headers["Content-Type"] = content_type
70
63
  end
71
64
 
72
- def load_user
73
- @current_api_user = (try_spree_current_user || Spree.user_class.find_by(spree_api_key: api_key.to_s))
65
+ def check_for_user_or_api_key
66
+ # User is already authenticated with Spree, make request this way instead.
67
+ return true if @current_api_user = try_spree_current_user || !Spree::Api::Config[:requires_authentication]
68
+
69
+ if api_key.blank?
70
+ render "spree/api/errors/must_specify_api_key", :status => 401 and return
71
+ end
74
72
  end
75
73
 
76
74
  def authenticate_user
77
75
  unless @current_api_user
78
- if requires_authentication? && api_key.blank? && order_token.blank?
79
- render "spree/api/errors/must_specify_api_key", :status => 401 and return
80
- elsif order_token.blank? && (requires_authentication? || api_key.present?)
81
- render "spree/api/errors/invalid_api_key", :status => 401 and return
76
+ if requires_authentication? || api_key.present?
77
+ unless @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s)
78
+ render "spree/api/errors/invalid_api_key", :status => 401 and return
79
+ end
82
80
  else
83
81
  # An anonymous user
84
82
  @current_api_user = Spree.user_class.new
@@ -125,13 +123,9 @@ module Spree
125
123
  end
126
124
  helper_method :api_key
127
125
 
128
- def order_token
129
- request.headers["X-Spree-Order-Token"] || params[:order_token]
130
- end
131
-
132
126
  def find_product(id)
133
127
  begin
134
- product_scope.find_by_permalink!(id.to_s)
128
+ product_scope.friendly.find(id.to_s)
135
129
  rescue ActiveRecord::RecordNotFound
136
130
  product_scope.find(id)
137
131
  end
@@ -141,23 +135,18 @@ module Spree
141
135
  variants_associations = [{ option_values: :option_type }, :default_price, :prices, :images]
142
136
  if current_api_user.has_spree_role?("admin")
143
137
  scope = Product.with_deleted.accessible_by(current_ability, :read)
144
- .includes(:product_properties, :option_types, variants_including_master: variants_associations)
138
+ .includes(:properties, :option_types, variants: variants_associations, master: variants_associations)
145
139
 
146
140
  unless params[:show_deleted]
147
141
  scope = scope.not_deleted
148
142
  end
149
143
  else
150
144
  scope = Product.accessible_by(current_ability, :read).active
151
- .includes(:product_properties, :option_types, variants_including_master: variants_associations)
145
+ .includes(:properties, :option_types, variants: variants_associations, master: variants_associations)
152
146
  end
153
147
 
154
148
  scope
155
149
  end
156
-
157
- def authorize_for_order
158
- @order = Spree::Order.find_by(number: params[:order_id] || params[:id])
159
- authorize! :read, @order, order_token
160
- end
161
150
  end
162
151
  end
163
152
  end
@@ -31,7 +31,8 @@ module Spree
31
31
  end
32
32
 
33
33
  def show
34
- redirect_to(api_order_path(params[:id]), status: 301)
34
+ load_order
35
+ respond_with(@order, default_template: 'spree/api/orders/show', status: 200)
35
36
  end
36
37
 
37
38
  def update
@@ -53,28 +54,11 @@ module Spree
53
54
  end
54
55
 
55
56
  private
56
- def object_params
57
- modify_payment_attributes params[:order] || {}
58
-
59
- protected_params = if params[:order]
60
- params.require(:order).permit(permitted_checkout_attributes)
61
- else
62
- {}
63
- end
64
57
 
65
- map_nested_attributes_keys Order, protected_params
66
- end
67
-
68
- def user_id
69
- params[:order][:user_id] if params[:order]
70
- end
71
-
72
- # For payment step, filter order parameters to produce the expected
73
- # nested attributes for a single payment and its source, discarding
74
- # attributes for payment methods other than the one selected
75
- #
76
- # respond_to check is necessary due to issue described in #2910
77
- def modify_payment_attributes(object_params)
58
+ def object_params
59
+ # For payment step, filter order parameters to produce the expected nested attributes for a single payment and its source, discarding attributes for payment methods other than the one selected
60
+ # respond_to check is necessary due to issue described in #2910
61
+ object_params = nested_params
78
62
  if @order.has_checkout_step?('payment') && @order.payment?
79
63
  if object_params[:payments_attributes].is_a?(Hash)
80
64
  object_params[:payments_attributes] = [object_params[:payments_attributes]]
@@ -86,6 +70,11 @@ module Spree
86
70
  object_params[:payments_attributes].first[:amount] = @order.total.to_s
87
71
  end
88
72
  end
73
+ object_params
74
+ end
75
+
76
+ def user_id
77
+ params[:order][:user_id] if params[:order]
89
78
  end
90
79
 
91
80
  def nested_params
@@ -105,10 +94,6 @@ module Spree
105
94
  state_callback(:before)
106
95
  end
107
96
 
108
- def current_currency
109
- Spree::Config[:currency]
110
- end
111
-
112
97
  def ip_address
113
98
  ''
114
99
  end
@@ -122,6 +107,10 @@ module Spree
122
107
  send(method_name) if respond_to?(method_name, true)
123
108
  end
124
109
 
110
+ def before_payment
111
+ @order.payments.destroy_all if request.put?
112
+ end
113
+
125
114
  def next!(options={})
126
115
  if @order.valid? && @order.next
127
116
  render 'spree/api/orders/show', status: options[:status] || 200
@@ -132,15 +121,20 @@ module Spree
132
121
 
133
122
  def after_update_attributes
134
123
  if object_params && object_params[:coupon_code].present?
135
- coupon_result = Spree::Promo::CouponApplicator.new(@order).apply
136
- if !coupon_result[:coupon_applied?]
137
- @coupon_message = coupon_result[:error]
124
+ handler = PromotionHandler::Coupon.new(@order).apply
125
+
126
+ if handler.error.present?
127
+ @coupon_message = handler.error
138
128
  respond_with(@order, default_template: 'spree/api/orders/could_not_apply_coupon')
139
129
  return true
140
130
  end
141
131
  end
142
132
  false
143
133
  end
134
+
135
+ def order_token
136
+ request.headers["X-Spree-Order-Token"] || params[:order_token]
137
+ end
144
138
  end
145
139
  end
146
140
  end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ module Api
3
+ class ClassificationsController < Spree::Api::BaseController
4
+ def update
5
+ authorize! :update, Product
6
+ authorize! :update, Taxon
7
+ classification = Spree::Classification.find_by(
8
+ :product_id => params[:product_id],
9
+ :taxon_id => params[:taxon_id]
10
+ )
11
+ # Because position we get back is 0-indexed.
12
+ # acts_as_list is 1-indexed.
13
+ classification.insert_at(params[:position].to_i + 1)
14
+ render :nothing => true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -15,8 +15,9 @@ module Spree
15
15
 
16
16
  def update
17
17
  @line_item = order.line_items.find(params[:id])
18
- if @line_item.update_attributes(line_item_params)
18
+ if @order.contents.update_cart(line_items_attributes)
19
19
  @order.ensure_updated_shipments
20
+ @line_item.reload
20
21
  respond_with(@line_item, default_template: :show)
21
22
  else
22
23
  invalid_resource!(@line_item)
@@ -38,9 +39,20 @@ module Spree
38
39
  authorize! :update, @order, order_token
39
40
  end
40
41
 
42
+ def line_items_attributes
43
+ { line_items_attributes: {
44
+ id: params[:id],
45
+ quantity: params[:line_item][:quantity]
46
+ } }
47
+ end
48
+
41
49
  def line_item_params
42
50
  params.require(:line_item).permit(:quantity, :variant_id)
43
51
  end
52
+
53
+ def order_token
54
+ request.headers["X-Spree-Order-Token"] || params[:order_token]
55
+ end
44
56
  end
45
57
  end
46
58
  end
@@ -3,9 +3,9 @@ module Spree
3
3
  class OptionTypesController < Spree::Api::BaseController
4
4
  def index
5
5
  if params[:ids]
6
- @option_types = Spree::OptionType.includes(:option_values).accessible_by(current_ability, :read).where(id: params[:ids].split(','))
6
+ @option_types = Spree::OptionType.accessible_by(current_ability, :read).where(:id => params[:ids].split(','))
7
7
  else
8
- @option_types = Spree::OptionType.includes(:option_values).accessible_by(current_ability, :read).load.ransack(params[:q]).result
8
+ @option_types = Spree::OptionType.accessible_by(current_ability, :read).load.ransack(params[:q]).result
9
9
  end
10
10
  respond_with(@option_types)
11
11
  end
@@ -51,7 +51,7 @@ module Spree
51
51
  end
52
52
 
53
53
  def option_value_params
54
- params.require(:option_value).permit(permitted_option_value_attributes)
54
+ params.require(:option_value).permit(permitted_option_type_attributes)
55
55
  end
56
56
  end
57
57
  end
@@ -28,7 +28,6 @@ module Spree
28
28
 
29
29
  def empty
30
30
  find_order
31
- authorize! :update, @order, order_token
32
31
  @order.empty!
33
32
  @order.update!
34
33
  render text: nil, status: 200
@@ -42,7 +41,6 @@ module Spree
42
41
 
43
42
  def show
44
43
  find_order
45
- authorize! :show, @order, order_token
46
44
  method = "before_#{@order.state}"
47
45
  send(method) if respond_to?(method, true)
48
46
  respond_with(@order)
@@ -50,7 +48,6 @@ module Spree
50
48
 
51
49
  def update
52
50
  find_order(true)
53
- authorize! :update, @order, order_token
54
51
  # Parsing line items through as an update_attributes call in the API will result in
55
52
  # many line items for the same variant_id being created. We must be smarter about this,
56
53
  # hence the use of the update_line_items method, defined within order_decorator.rb.
@@ -66,7 +63,7 @@ module Spree
66
63
  invalid_resource!(@order)
67
64
  end
68
65
  end
69
-
66
+
70
67
  def mine
71
68
  if current_api_user.persisted?
72
69
  @orders = current_api_user.orders.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
@@ -75,37 +72,12 @@ module Spree
75
72
  end
76
73
  end
77
74
 
78
- ##
79
- # Applies a promotion code to the user's most recent order
80
- # This is a temporary API method until we move to next Spree release which has this logic already in this commit.
81
- #
82
- # https://github.com/spree/spree/commit/72a5b74c47af975fc3492580415a4cdc2dc02c0c
83
- #
84
- # Source references:
85
- #
86
- # https://github.com/spree/spree/blob/master/frontend/app/controllers/spree/store_controller.rb#L13
87
- # https://github.com/spree/spree/blob/2-1-stable/frontend/app/controllers/spree/orders_controller.rb#L100
88
75
  def apply_coupon_code
89
76
  find_order
90
- authorize! :update, @order, order_token
91
77
  @order.coupon_code = params[:coupon_code]
92
- @order.save
93
-
94
- # https://github.com/spree/spree/blob/2-1-stable/core/lib/spree/promo/coupon_applicator.rb
95
- result = Spree::Promo::CouponApplicator.new(@order).apply
96
-
97
- result[:coupon_applied?] ||= false
98
-
99
- # Move flash.notice fields into success if applied
100
- # An error message is in result[:error]
101
- if result[:coupon_applied?] && result[:notice]
102
- result[:success] = result[:notice]
103
- end
104
-
105
- # Need to turn hash result into object for RABL
106
- # https://github.com/nesquena/rabl/wiki/Rendering-hash-objects-in-rabl
107
- @coupon_result = OpenStruct.new(result)
108
- render status: @coupon_result.coupon_applied? ? 200 : 422
78
+ @handler = PromotionHandler::Coupon.new(@order).apply
79
+ status = @handler.successful? ? 200 : 422
80
+ render "spree/api/promotions/handler", :status => status
109
81
  end
110
82
 
111
83
  private
@@ -134,7 +106,7 @@ module Spree
134
106
 
135
107
  def permitted_order_attributes
136
108
  if current_api_user.has_spree_role? "admin"
137
- super + admin_order_attributes
109
+ super << admin_order_attributes
138
110
  else
139
111
  super
140
112
  end
@@ -142,7 +114,7 @@ module Spree
142
114
 
143
115
  def permitted_shipment_attributes
144
116
  if current_api_user.has_spree_role? "admin"
145
- super + admin_shipment_attributes
117
+ super << admin_shipment_attributes
146
118
  else
147
119
  super
148
120
  end
@@ -166,11 +138,17 @@ module Spree
166
138
 
167
139
  def find_order(lock = false)
168
140
  @order = Spree::Order.lock(lock).find_by!(number: params[:id])
141
+ authorize! :update, @order, order_token
169
142
  end
170
143
 
171
144
  def before_delivery
172
145
  @order.create_proposed_shipments
173
146
  end
147
+
148
+ def order_token
149
+ request.headers["X-Spree-Order-Token"] || params[:order_token]
150
+ end
151
+
174
152
  end
175
153
  end
176
154
  end