spree_api 2.1.12 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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