spree_api 1.3.1 → 1.3.2

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 (27) hide show
  1. data/LICENSE +23 -18
  2. data/app/controllers/spree/api/base_controller.rb +1 -1
  3. data/app/controllers/spree/api/checkouts_controller.rb +90 -0
  4. data/app/controllers/spree/api/inventory_units_controller.rb +48 -0
  5. data/app/controllers/spree/api/orders_controller.rb +0 -17
  6. data/app/controllers/spree/api/product_properties_controller.rb +3 -2
  7. data/app/controllers/spree/api/return_authorizations_controller.rb +3 -2
  8. data/app/controllers/spree/api/taxonomies_controller.rb +3 -2
  9. data/app/controllers/spree/api/users_controller.rb +51 -0
  10. data/app/helpers/spree/api/api_helpers.rb +4 -0
  11. data/app/models/spree/order_decorator.rb +4 -2
  12. data/app/views/spree/api/images/show.v1.rabl +1 -0
  13. data/app/views/spree/api/{v1/inventory_units → inventory_units}/show.rabl +0 -0
  14. data/app/views/spree/api/users/index.v1.rabl +7 -0
  15. data/app/views/spree/api/users/new.v1.rabl +3 -0
  16. data/app/views/spree/api/users/show.v1.rabl +3 -0
  17. data/config/routes.rb +2 -0
  18. data/lib/spree/api/responders/rabl_template.rb +1 -1
  19. data/spec/controllers/spree/api/checkouts_controller_spec.rb +102 -0
  20. data/spec/controllers/spree/api/{v1/inventory_units_controller_spec.rb → inventory_units_controller_spec.rb} +1 -2
  21. data/spec/controllers/spree/api/orders_controller_spec.rb +1 -74
  22. data/spec/controllers/spree/api/product_properties_controller_spec.rb +2 -2
  23. data/spec/controllers/spree/api/users_controller_spec.rb +126 -0
  24. data/spec/models/spree/order_spec.rb +1 -1
  25. metadata +19 -11
  26. data/app/controllers/spree/api/v1/base_controller.rb +0 -111
  27. data/app/controllers/spree/api/v1/inventory_units_controller.rb +0 -50
data/LICENSE CHANGED
@@ -1,22 +1,27 @@
1
- Copyright (c) 2012 Ryan Bigg
1
+ Copyright (c) 2007-2013, Spree Commerce, Inc. and other contributors
2
+ All rights reserved.
2
3
 
3
- MIT License
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
4
6
 
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
12
15
 
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
27
 
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -53,7 +53,7 @@ module Spree
53
53
 
54
54
  def authenticate_user
55
55
  if requires_authentication? || api_key.present?
56
- unless @current_api_user = Spree.user_class.find_by_spree_api_key(api_key)
56
+ unless @current_api_user = Spree.user_class.find_by_spree_api_key(api_key.to_s)
57
57
  render "spree/api/errors/invalid_api_key", :status => 401 and return
58
58
  end
59
59
  else
@@ -0,0 +1,90 @@
1
+ module Spree
2
+ module Api
3
+ class CheckoutsController < Spree::Api::BaseController
4
+ before_filter :load_order, :only => :update
5
+ before_filter :associate_user, :only => :update
6
+
7
+ include Spree::Core::ControllerHelpers::Auth
8
+ include Spree::Core::ControllerHelpers::Order
9
+
10
+ respond_to :json
11
+
12
+ def create
13
+ @order = Order.build_from_api(current_api_user, nested_params)
14
+ next!(:status => 201)
15
+ end
16
+
17
+ def update
18
+ if @order.update_attributes(object_params)
19
+ state_callback(:after) if @order.next
20
+ respond_with(@order, :default_template => 'spree/api/orders/show')
21
+ else
22
+ respond_with(@order, :default_template => 'spree/api/orders/could_not_transition', :status => 422)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def object_params
29
+ # 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
30
+ if @order.payment?
31
+ if params[:payment_source].present? && source_params = params.delete(:payment_source)[params[:order][:payments_attributes].first[:payment_method_id].underscore]
32
+ params[:order][:payments_attributes].first[:source_attributes] = source_params
33
+ end
34
+ if params[:order].present? && params[:order][:payments_attributes]
35
+ params[:order][:payments_attributes].first[:amount] = @order.total
36
+ end
37
+ end
38
+ params[:order]
39
+ end
40
+
41
+ def nested_params
42
+ map_nested_attributes_keys Order, params[:order] || {}
43
+ end
44
+
45
+ # Should be overriden if you have areas of your checkout that don't match
46
+ # up to a step within checkout_steps, such as a registration step
47
+ def skip_state_validation?
48
+ false
49
+ end
50
+
51
+ def load_order
52
+ @order = Spree::Order.find_by_number!(params[:id])
53
+ raise_insufficient_quantity and return if @order.insufficient_stock_lines.present?
54
+ @order.state = params[:state] if params[:state]
55
+ state_callback(:before)
56
+ end
57
+
58
+ def raise_insufficient_quantity
59
+ respond_with(@order, :default_template => 'spree/api/orders/insufficient_quantity')
60
+ end
61
+
62
+ def state_callback(before_or_after = :before)
63
+ method_name = :"#{before_or_after}_#{@order.state}"
64
+ send(method_name) if respond_to?(method_name, true)
65
+ end
66
+
67
+ def before_address
68
+ @order.bill_address ||= Address.default
69
+ @order.ship_address ||= Address.default
70
+ end
71
+
72
+ def before_delivery
73
+ return if params[:order].present?
74
+ @order.shipping_method ||= (@order.rate_hash.first && @order.rate_hash.first[:shipping_method])
75
+ end
76
+
77
+ def before_payment
78
+ @order.payments.destroy_all if request.put?
79
+ end
80
+
81
+ def next!(options={})
82
+ if @order.valid? && @order.next
83
+ render 'spree/api/orders/show', :status => options[:status] || 200
84
+ else
85
+ render 'spree/api/orders/could_not_transition', :status => 422
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,48 @@
1
+ module Spree
2
+ module Api
3
+ class InventoryUnitsController < Spree::Api::BaseController
4
+ before_filter :prepare_event, :only => :update
5
+
6
+ def show
7
+ @inventory_unit = inventory_unit
8
+ end
9
+
10
+ def update
11
+ authorize! :update, Order
12
+
13
+ inventory_unit.transaction do
14
+ if inventory_unit.update_attributes(params[:inventory_unit])
15
+ fire
16
+ render :show, :status => 200
17
+ else
18
+ invalid_resource!(inventory_unit)
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def inventory_unit
26
+ @inventory_unit ||= InventoryUnit.find(params[:id])
27
+ end
28
+
29
+ def prepare_event
30
+ return unless @event = params[:fire]
31
+
32
+ can_event = "can_#{@event}?"
33
+
34
+ unless inventory_unit.respond_to?(can_event) &&
35
+ inventory_unit.send(can_event)
36
+ render :text => { :exception => "cannot transition to #{@event}" }.to_json,
37
+ :status => 200
38
+ false
39
+ end
40
+ end
41
+
42
+ def fire
43
+ inventory_unit.send("#{@event}!") if @event
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -31,23 +31,6 @@ module Spree
31
31
  end
32
32
  end
33
33
 
34
- def address
35
- order.build_ship_address(params[:shipping_address]) if params[:shipping_address]
36
- order.build_bill_address(params[:billing_address]) if params[:billing_address]
37
- next!
38
- end
39
-
40
- def delivery
41
- begin
42
- ShippingMethod.find(params[:shipping_method_id])
43
- rescue ActiveRecord::RecordNotFound
44
- render :invalid_shipping_method, :status => 422
45
- else
46
- order.update_attribute(:shipping_method_id, params[:shipping_method_id])
47
- next!
48
- end
49
- end
50
-
51
34
  def cancel
52
35
  order.cancel!
53
36
  render :show
@@ -7,8 +7,9 @@ module Spree
7
7
  before_filter :product_property, :only => [:show, :update, :destroy]
8
8
 
9
9
  def index
10
- @product_properties = @product.product_properties.ransack(params[:q]).result
11
- .page(params[:page]).per(params[:per_page])
10
+ @product_properties = @product.product_properties.
11
+ ransack(params[:q]).result.
12
+ page(params[:page]).per(params[:per_page])
12
13
  respond_with(@product_properties)
13
14
  end
14
15
 
@@ -6,8 +6,9 @@ module Spree
6
6
  before_filter :authorize_admin!
7
7
 
8
8
  def index
9
- @return_authorizations = order.return_authorizations.ransack(params[:q]).result
10
- .page(params[:page]).per(params[:per_page])
9
+ @return_authorizations = order.return_authorizations.
10
+ ransack(params[:q]).result.
11
+ page(params[:page]).per(params[:per_page])
11
12
  respond_with(@return_authorizations)
12
13
  end
13
14
 
@@ -4,8 +4,9 @@ module Spree
4
4
  respond_to :json
5
5
 
6
6
  def index
7
- @taxonomies = Taxonomy.order('name').includes(:root => :children).ransack(params[:q]).result
8
- .page(params[:page]).per(params[:per_page])
7
+ @taxonomies = Taxonomy.order('name').includes(:root => :children).
8
+ ransack(params[:q]).result.
9
+ page(params[:page]).per(params[:per_page])
9
10
  respond_with(@taxonomies)
10
11
  end
11
12
 
@@ -0,0 +1,51 @@
1
+ module Spree
2
+ module Api
3
+ class UsersController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ def index
7
+ @users = Spree.user_class.accessible_by(current_ability,:read).ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
8
+ respond_with(@users)
9
+ end
10
+
11
+ def show
12
+ authorize! :show, user
13
+ respond_with(user)
14
+ end
15
+
16
+ def new
17
+ end
18
+
19
+ def create
20
+ authorize! :create, Spree.user_class
21
+ @user = Spree.user_class.new(params[:user])
22
+ if @user.save
23
+ respond_with(@user, :status => 201, :default_template => :show)
24
+ else
25
+ invalid_resource!(@user)
26
+ end
27
+ end
28
+
29
+ def update
30
+ authorize! :update, user
31
+ if user.update_attributes(params[:user])
32
+ respond_with(user, :status => 200, :default_template => :show)
33
+ else
34
+ invalid_resource!(user)
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ authorize! :destroy, user
40
+ user.destroy
41
+ respond_with(user, :status => 204)
42
+ end
43
+
44
+ private
45
+
46
+ def user
47
+ @user ||= Spree.user_class.find(params[:id])
48
+ end
49
+ end
50
+ end
51
+ end
@@ -76,6 +76,10 @@ module Spree
76
76
  def country_attributes
77
77
  [:id, :iso_name, :iso, :iso3, :name, :numcode]
78
78
  end
79
+
80
+ def user_attributes
81
+ [:id, :email, :created_at, :updated_at]
82
+ end
79
83
  end
80
84
  end
81
85
  end
@@ -2,8 +2,10 @@ Spree::Order.class_eval do
2
2
  def self.build_from_api(user, params)
3
3
  order = create
4
4
  params[:line_items_attributes] ||= []
5
- params[:line_items_attributes].each do |line_item|
6
- order.add_variant(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
5
+ unless params[:line_items_attributes].empty?
6
+ params[:line_items_attributes].each_key do |k|
7
+ order.add_variant(Spree::Variant.find(params[:line_items_attributes][k][:variant_id]), params[:line_items_attributes][k][:quantity])
8
+ end
7
9
  end
8
10
 
9
11
  order.user = user
@@ -1,3 +1,4 @@
1
1
  object @image
2
2
  attributes *image_attributes
3
3
  attributes :viewable_type, :viewable_id
4
+ node(:attachment_url) { |i| i.attachment.to_s }
@@ -0,0 +1,7 @@
1
+ object false
2
+ child(@users => :users) do
3
+ extends "spree/api/users/show"
4
+ end
5
+ node(:count) { @users.count }
6
+ node(:current_page) { params[:page] || 1 }
7
+ node(:pages) { @users.num_pages }
@@ -0,0 +1,3 @@
1
+ object false
2
+ node(:attributes) { [*user_attributes] }
3
+ node(:required_attributes) { required_fields_for(Spree.user_class) }
@@ -0,0 +1,3 @@
1
+ object @user
2
+
3
+ attributes *user_attributes
data/config/routes.rb CHANGED
@@ -15,6 +15,7 @@ Spree::Core::Engine.routes.prepend do
15
15
  end
16
16
 
17
17
  resources :images
18
+ resources :checkouts
18
19
  resources :variants, :only => [:index] do
19
20
  end
20
21
 
@@ -53,5 +54,6 @@ Spree::Core::Engine.routes.prepend do
53
54
  resources :taxons
54
55
  end
55
56
  resources :inventory_units, :only => [:show, :update]
57
+ resources :users
56
58
  end
57
59
  end
@@ -4,7 +4,7 @@ module Spree
4
4
  module RablTemplate
5
5
  def to_format
6
6
  if template
7
- render template.to_sym, :status => options[:status] || 200
7
+ render template, :status => options[:status] || 200
8
8
  else
9
9
  super
10
10
  end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::CheckoutsController do
5
+ render_views
6
+
7
+ before(:each) do
8
+ stub_authentication!
9
+ Spree::Config[:track_inventory_levels] = false
10
+ country_zone = create(:zone, :name => 'CountryZone')
11
+ @state = create(:state)
12
+ @country = @state.country
13
+ country_zone.members.create(:zoneable => @country)
14
+
15
+ @shipping_method = create(:shipping_method, :zone => country_zone)
16
+ @payment_method = create(:payment_method)
17
+ end
18
+
19
+ after do
20
+ Spree::Config[:track_inventory_levels] = true
21
+ end
22
+
23
+ context "POST 'create'" do
24
+ it "creates a new order when no parameters are passed" do
25
+ api_post :create
26
+
27
+ json_response['number'].should be_present
28
+ response.status.should == 201
29
+ end
30
+ end
31
+
32
+ context "PUT 'update'" do
33
+ let(:order) { create(:order) }
34
+
35
+ before(:each) do
36
+ Order.any_instance.stub(:confirmation_required? => true)
37
+ Order.any_instance.stub(:payment_required? => true)
38
+ end
39
+
40
+ it "will return an error if the order cannot transition" do
41
+ order.update_column(:state, "address")
42
+ api_put :update, :id => order.to_param
43
+ json_response['error'].should =~ /could not be transitioned/
44
+ response.status.should == 422
45
+ end
46
+
47
+ it "can update addresses and transition from address to delivery" do
48
+ order.update_column(:state, "address")
49
+ shipping_address = billing_address = {
50
+ :firstname => 'John',
51
+ :lastname => 'Doe',
52
+ :address1 => '7735 Old Georgetown Road',
53
+ :city => 'Bethesda',
54
+ :phone => '3014445002',
55
+ :zipcode => '20814',
56
+ :state_id => @state.id,
57
+ :country_id => @country.id
58
+ }
59
+ api_put :update,
60
+ :id => order.to_param,
61
+ :order => { :bill_address_attributes => billing_address, :ship_address_attributes => shipping_address }
62
+
63
+ json_response['state'].should == 'delivery'
64
+ json_response['bill_address']['firstname'].should == 'John'
65
+ json_response['ship_address']['firstname'].should == 'John'
66
+ response.status.should == 200
67
+ end
68
+
69
+ it "can update shipping method and transition from delivery to payment" do
70
+ order.update_column(:state, "delivery")
71
+ api_put :update, :id => order.to_param, :order => { :shipping_method_id => @shipping_method.id }
72
+
73
+ json_response['shipments'][0]['shipping_method']['name'].should == @shipping_method.name
74
+ json_response['state'].should == 'payment'
75
+ response.status.should == 200
76
+ end
77
+
78
+ it "can update payment method and transition from payment to confirm" do
79
+ order.update_column(:state, "payment")
80
+ api_put :update, :id => order.to_param, :order => { :payments_attributes => [{ :payment_method_id => @payment_method.id }] }
81
+ json_response['state'].should == 'confirm'
82
+ json_response['payments'][0]['payment_method']['name'].should == @payment_method.name
83
+ response.status.should == 200
84
+ end
85
+
86
+ it "can transition from confirm to complete" do
87
+ order.update_column(:state, "confirm")
88
+ Spree::Order.any_instance.stub(:payment_required? => false)
89
+ api_put :update, :id => order.to_param
90
+ json_response['state'].should == 'complete'
91
+ response.status.should == 200
92
+ end
93
+
94
+ it "returns the order if the order is already complete" do
95
+ order.update_column(:state, "complete")
96
+ api_put :update, :id => order.to_param
97
+ json_response['number'].should == order.number
98
+ response.status.should == 200
99
+ end
100
+ end
101
+ end
102
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Spree
4
- describe Api::V1::InventoryUnitsController do
4
+ describe Api::InventoryUnitsController do
5
5
  render_views
6
6
 
7
7
  before do
@@ -41,6 +41,5 @@ module Spree
41
41
  json_response['exception'].should match /cannot transition to bad/
42
42
  end
43
43
  end
44
-
45
44
  end
46
45
  end
@@ -53,14 +53,9 @@ module Spree
53
53
  assert_unauthorized!
54
54
  end
55
55
 
56
- it "cannot change delivery information on an order that doesn't belong to them" do
57
- api_put :delivery, :id => order.to_param
58
- assert_unauthorized!
59
- end
60
-
61
56
  it "can create an order" do
62
57
  variant = create(:variant)
63
- api_post :create, :order => { :line_items => [{ :variant_id => variant.to_param, :quantity => 5 }] }
58
+ api_post :create, :order => { :line_items => { "0" => { :variant_id => variant.to_param, :quantity => 5 } } }
64
59
  response.status.should == 201
65
60
  order = Order.last
66
61
  order.line_items.count.should == 1
@@ -97,52 +92,6 @@ module Spree
97
92
  let!(:shipping_method) { create(:shipping_method) }
98
93
  let!(:payment_method) { create(:payment_method) }
99
94
 
100
- it "can add address information to an order" do
101
- api_put :address, :id => order.to_param, :shipping_address => shipping_address, :billing_address => billing_address
102
-
103
- response.status.should == 200
104
- order.reload
105
- order.shipping_address.reload
106
- order.billing_address.reload
107
- # We can assume the rest of the parameters are set if these two are
108
- order.shipping_address.firstname.should == shipping_address[:firstname]
109
- order.billing_address.firstname.should == billing_address[:firstname]
110
- order.state.should == "delivery"
111
- json_response["shipping_methods"].should_not be_empty
112
- end
113
-
114
- it "can add just shipping address information to an order" do
115
- api_put :address, :id => order.to_param, :shipping_address => shipping_address
116
- response.status.should == 200
117
- order.reload
118
- order.shipping_address.reload
119
- order.shipping_address.firstname.should == shipping_address[:firstname]
120
- order.bill_address.should be_nil
121
- end
122
-
123
- it "cannot use an address that has no valid shipping methods" do
124
- shipping_method.destroy
125
- api_put :address, :id => order.to_param, :shipping_address => shipping_address, :billing_address => billing_address
126
- response.status.should == 422
127
- json_response["errors"]["base"].should == ["No shipping methods available for selected location, please change your address and try again."]
128
- end
129
-
130
- it "can not add invalid ship address information to an order" do
131
- shipping_address[:firstname] = ""
132
- api_put :address, :id => order.to_param, :shipping_address => shipping_address, :billing_address => billing_address
133
-
134
- response.status.should == 422
135
- json_response["errors"]["ship_address.firstname"].should_not be_blank
136
- end
137
-
138
- it "can not add invalid ship address information to an order" do
139
- billing_address[:firstname] = ""
140
- api_put :address, :id => order.to_param, :shipping_address => shipping_address, :billing_address => billing_address
141
-
142
- response.status.should == 422
143
- json_response["errors"]["bill_address.firstname"].should_not be_blank
144
- end
145
-
146
95
  it "can add line items" do
147
96
  api_put :update, :id => order.to_param, :order => { :line_items => [{:variant_id => create(:variant).id, :quantity => 2}] }
148
97
 
@@ -155,28 +104,6 @@ module Spree
155
104
  order.line_items << create(:line_item)
156
105
  end
157
106
 
158
- context "for delivery" do
159
- before do
160
- order.update_attribute(:state, "delivery")
161
- end
162
-
163
- it "can select a shipping method for an order" do
164
- order.shipping_method.should be_nil
165
- api_put :delivery, :id => order.to_param, :shipping_method_id => shipping_method.id
166
- response.status.should == 200
167
- order.reload
168
- order.state.should == "payment"
169
- order.shipping_method.should == shipping_method
170
- end
171
-
172
- it "cannot select an invalid shipping method for an order" do
173
- order.shipping_method.should be_nil
174
- api_put :delivery, :id => order.to_param, :shipping_method_id => '1234567890'
175
- response.status.should == 422
176
- json_response["errors"].should include("Invalid shipping method specified.")
177
- end
178
- end
179
-
180
107
  it "can empty an order" do
181
108
  api_put :empty, :id => order.to_param
182
109
  response.status.should == 200
@@ -6,8 +6,8 @@ module Spree
6
6
  render_views
7
7
 
8
8
  let!(:product) { create(:product) }
9
- let!(:property_1) {product.product_properties.create(:property_name => "My Property 1", :value => "my value 1")}
10
- let!(:property_2) {product.product_properties.create(:property_name => "My Property 2", :value => "my value 2")}
9
+ let!(:property_1) {product.product_properties.create(:property_name => "My Property 1", :value => "my value 1", :position => 0)}
10
+ let!(:property_2) {product.product_properties.create(:property_name => "My Property 2", :value => "my value 2", :position => 1)}
11
11
 
12
12
  let(:attributes) { [:id, :product_id, :property_id, :value, :property_name] }
13
13
  let(:resource_scoping) { { :product_id => product.to_param } }
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe Api::UsersController do
5
+ render_views
6
+
7
+ let(:user) { create(:user) }
8
+ let(:stranger) { create(:user, :email => 'stranger@example.com') }
9
+ let(:attributes) { [:id, :email, :created_at, :updated_at] }
10
+
11
+ before { stub_authentication! }
12
+
13
+ context "as a normal user" do
14
+ before { Spree::LegacyUser.stub :find_by_spree_api_key => user }
15
+
16
+ it "can get own details" do
17
+ api_get :show, :id => user.id
18
+
19
+ json_response['email'].should eq user.email
20
+ end
21
+
22
+ it "cannot get other users details" do
23
+ api_get :show, :id => stranger.id
24
+
25
+ assert_unauthorized!
26
+ end
27
+
28
+ it "can learn how to create a new user" do
29
+ api_get :new
30
+ json_response["attributes"].should == attributes.map(&:to_s)
31
+ end
32
+
33
+ it "can create a new user" do
34
+ api_post :create, :user => { :email => 'new@example.com', :password => 'spree123', :password_confirmation => 'spree123' }
35
+ json_response['email'].should eq 'new@example.com'
36
+ end
37
+
38
+ # there's no validations on LegacyUser?
39
+ xit "cannot create a new user with invalid attributes" do
40
+ api_post :create, :user => {}
41
+ response.status.should == 422
42
+ json_response["error"].should == "Invalid resource. Please fix errors and try again."
43
+ errors = json_response["errors"]
44
+ end
45
+
46
+ it "can update own details" do
47
+ api_put :update, :id => user.id, :user => { :email => "mine@example.com" }
48
+ json_response['email'].should eq 'mine@example.com'
49
+ end
50
+
51
+ it "cannot update other users details" do
52
+ api_put :update, :id => stranger.id, :user => { :email => "mine@example.com" }
53
+ assert_unauthorized!
54
+ end
55
+
56
+ it "can delete itself" do
57
+ api_delete :destroy, :id => user.id
58
+ response.status.should == 204
59
+ end
60
+
61
+ it "cannot delete other user" do
62
+ api_delete :destroy, :id => stranger.id
63
+ assert_unauthorized!
64
+ end
65
+
66
+ it "should only get own details on index" do
67
+ 2.times { create(:user) }
68
+ api_get :index
69
+
70
+ Spree.user_class.count.should eq 3
71
+ json_response['count'].should eq 1
72
+ json_response['users'].size.should eq 1
73
+ end
74
+ end
75
+
76
+ context "as an admin" do
77
+ sign_in_as_admin!
78
+
79
+ it "gets all users" do
80
+ Spree::LegacyUser.stub :find_by_spree_api_key => current_api_user
81
+
82
+ 2.times { create(:user) }
83
+
84
+ api_get :index
85
+ Spree.user_class.count.should eq 2
86
+ json_response['count'].should eq 2
87
+ json_response['users'].size.should eq 2
88
+ end
89
+
90
+ it 'can control the page size through a parameter' do
91
+ 2.times { create(:user) }
92
+ api_get :index, :per_page => 1
93
+ json_response['count'].should == 1
94
+ json_response['current_page'].should == 1
95
+ json_response['pages'].should == 2
96
+ end
97
+
98
+ it 'can query the results through a paramter' do
99
+ expected_result = create(:user, :email => 'brian@spreecommerce.com')
100
+ api_get :index, :q => { :email_cont => 'brian' }
101
+ json_response['count'].should == 1
102
+ json_response['users'].first['email'].should eq expected_result.email
103
+ end
104
+
105
+ it "can create" do
106
+ api_post :create, :user => { :email => "new@example.com", :password => 'spree123', :password_confirmation => 'spree123' }
107
+ json_response.should have_attributes(attributes)
108
+ response.status.should == 201
109
+ end
110
+
111
+ it "can destroy user without orders" do
112
+ user.orders.destroy_all
113
+ api_delete :destroy, :id => user.id
114
+ response.status.should == 204
115
+ end
116
+
117
+ it "cannot destroy user with orders" do
118
+ create(:completed_order_with_totals, :user => user)
119
+ api_delete :destroy, :id => user.id
120
+ json_response["exception"].should eq "Spree::LegacyUser::DestroyWithOrdersError"
121
+ response.status.should == 422
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -7,7 +7,7 @@ module Spree
7
7
  it 'can build an order from API parameters' do
8
8
  product = Spree::Product.create!(:name => 'Test', :sku => 'TEST-1', :price => 33.22)
9
9
  variant_id = product.master.id
10
- order = Order.build_from_api(user, { :line_items_attributes => [{ :variant_id => variant_id, :quantity => 5 }]})
10
+ order = Order.build_from_api(user, { :line_items_attributes => { "0" => { :variant_id => variant_id, :quantity => 5 }}})
11
11
 
12
12
  order.user.should == user
13
13
  line_item = order.line_items.first
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-06 00:00:00.000000000 Z
12
+ date: 2013-02-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: spree_core
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 1.3.1
21
+ version: 1.3.2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - '='
28
28
  - !ruby/object:Gem::Version
29
- version: 1.3.1
29
+ version: 1.3.2
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: versioncake
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -89,8 +89,10 @@ files:
89
89
  - Rakefile
90
90
  - app/controllers/spree/api/addresses_controller.rb
91
91
  - app/controllers/spree/api/base_controller.rb
92
+ - app/controllers/spree/api/checkouts_controller.rb
92
93
  - app/controllers/spree/api/countries_controller.rb
93
94
  - app/controllers/spree/api/images_controller.rb
95
+ - app/controllers/spree/api/inventory_units_controller.rb
94
96
  - app/controllers/spree/api/line_items_controller.rb
95
97
  - app/controllers/spree/api/orders_controller.rb
96
98
  - app/controllers/spree/api/payments_controller.rb
@@ -100,8 +102,7 @@ files:
100
102
  - app/controllers/spree/api/shipments_controller.rb
101
103
  - app/controllers/spree/api/taxonomies_controller.rb
102
104
  - app/controllers/spree/api/taxons_controller.rb
103
- - app/controllers/spree/api/v1/base_controller.rb
104
- - app/controllers/spree/api/v1/inventory_units_controller.rb
105
+ - app/controllers/spree/api/users_controller.rb
105
106
  - app/controllers/spree/api/variants_controller.rb
106
107
  - app/controllers/spree/api/zones_controller.rb
107
108
  - app/helpers/spree/api/api_helpers.rb
@@ -122,6 +123,7 @@ files:
122
123
  - app/views/spree/api/errors/not_found.v1.rabl
123
124
  - app/views/spree/api/errors/unauthorized.v1.rabl
124
125
  - app/views/spree/api/images/show.v1.rabl
126
+ - app/views/spree/api/inventory_units/show.rabl
125
127
  - app/views/spree/api/line_items/new.v1.rabl
126
128
  - app/views/spree/api/line_items/show.v1.rabl
127
129
  - app/views/spree/api/orders/address.v1.rabl
@@ -158,7 +160,9 @@ files:
158
160
  - app/views/spree/api/taxons/new.v1.rabl
159
161
  - app/views/spree/api/taxons/show.v1.rabl
160
162
  - app/views/spree/api/taxons/taxons.v1.rabl
161
- - app/views/spree/api/v1/inventory_units/show.rabl
163
+ - app/views/spree/api/users/index.v1.rabl
164
+ - app/views/spree/api/users/new.v1.rabl
165
+ - app/views/spree/api/users/show.v1.rabl
162
166
  - app/views/spree/api/variants/index.v1.rabl
163
167
  - app/views/spree/api/variants/new.v1.rabl
164
168
  - app/views/spree/api/variants/show.v1.rabl
@@ -183,8 +187,10 @@ files:
183
187
  - script/rails
184
188
  - spec/controllers/spree/api/addresses_controller_spec.rb
185
189
  - spec/controllers/spree/api/base_controller_spec.rb
190
+ - spec/controllers/spree/api/checkouts_controller_spec.rb
186
191
  - spec/controllers/spree/api/countries_controller_spec.rb
187
192
  - spec/controllers/spree/api/images_controller_spec.rb
193
+ - spec/controllers/spree/api/inventory_units_controller_spec.rb
188
194
  - spec/controllers/spree/api/line_items_controller_spec.rb
189
195
  - spec/controllers/spree/api/orders_controller_spec.rb
190
196
  - spec/controllers/spree/api/payments_controller_spec.rb
@@ -195,7 +201,7 @@ files:
195
201
  - spec/controllers/spree/api/taxonomies_controller_spec.rb
196
202
  - spec/controllers/spree/api/taxons_controller_spec.rb
197
203
  - spec/controllers/spree/api/unauthenticated_products_controller_spec.rb
198
- - spec/controllers/spree/api/v1/inventory_units_controller_spec.rb
204
+ - spec/controllers/spree/api/users_controller_spec.rb
199
205
  - spec/controllers/spree/api/variants_controller_spec.rb
200
206
  - spec/controllers/spree/api/zones_controller_spec.rb
201
207
  - spec/fixtures/thinking-cat.jpg
@@ -221,7 +227,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
221
227
  version: '0'
222
228
  segments:
223
229
  - 0
224
- hash: -4546587640053475121
230
+ hash: 2361962546786859221
225
231
  required_rubygems_version: !ruby/object:Gem::Requirement
226
232
  none: false
227
233
  requirements:
@@ -230,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
236
  version: '0'
231
237
  segments:
232
238
  - 0
233
- hash: -4546587640053475121
239
+ hash: 2361962546786859221
234
240
  requirements: []
235
241
  rubyforge_project:
236
242
  rubygems_version: 1.8.23
@@ -240,8 +246,10 @@ summary: Spree's API
240
246
  test_files:
241
247
  - spec/controllers/spree/api/addresses_controller_spec.rb
242
248
  - spec/controllers/spree/api/base_controller_spec.rb
249
+ - spec/controllers/spree/api/checkouts_controller_spec.rb
243
250
  - spec/controllers/spree/api/countries_controller_spec.rb
244
251
  - spec/controllers/spree/api/images_controller_spec.rb
252
+ - spec/controllers/spree/api/inventory_units_controller_spec.rb
245
253
  - spec/controllers/spree/api/line_items_controller_spec.rb
246
254
  - spec/controllers/spree/api/orders_controller_spec.rb
247
255
  - spec/controllers/spree/api/payments_controller_spec.rb
@@ -252,7 +260,7 @@ test_files:
252
260
  - spec/controllers/spree/api/taxonomies_controller_spec.rb
253
261
  - spec/controllers/spree/api/taxons_controller_spec.rb
254
262
  - spec/controllers/spree/api/unauthenticated_products_controller_spec.rb
255
- - spec/controllers/spree/api/v1/inventory_units_controller_spec.rb
263
+ - spec/controllers/spree/api/users_controller_spec.rb
256
264
  - spec/controllers/spree/api/variants_controller_spec.rb
257
265
  - spec/controllers/spree/api/zones_controller_spec.rb
258
266
  - spec/fixtures/thinking-cat.jpg
@@ -1,111 +0,0 @@
1
- module Spree
2
- module Api
3
- module V1
4
- class BaseController < ActionController::Metal
5
- include Spree::Api::ControllerSetup
6
-
7
- attr_accessor :current_api_user
8
-
9
- before_filter :set_content_type
10
- before_filter :check_for_api_key, :if => :requires_authentication?
11
- before_filter :authenticate_user
12
-
13
- rescue_from Exception, :with => :error_during_processing
14
- rescue_from CanCan::AccessDenied, :with => :unauthorized
15
- rescue_from ActiveRecord::RecordNotFound, :with => :not_found
16
-
17
- helper Spree::Api::ApiHelpers
18
-
19
- def map_nested_attributes_keys(klass, attributes)
20
- nested_keys = klass.nested_attributes_options.keys
21
- attributes.inject({}) do |h, (k,v)|
22
- key = nested_keys.include?(k.to_sym) ? "#{k}_attributes" : k
23
- h[key] = v
24
- h
25
- end.with_indifferent_access
26
- end
27
-
28
- private
29
-
30
- def set_content_type
31
- content_type = case params[:format]
32
- when "json"
33
- "application/json"
34
- when "xml"
35
- "text/xml"
36
- end
37
- headers["Content-Type"] = content_type
38
- end
39
-
40
- def check_for_api_key
41
- render "spree/api/v1/errors/must_specify_api_key", :status => 401 and return if api_key.blank?
42
- end
43
-
44
- def authenticate_user
45
- if requires_authentication? || api_key.present?
46
- unless @current_api_user = Spree.user_class.find_by_spree_api_key(api_key)
47
- render "spree/api/v1/errors/invalid_api_key", :status => 401 and return
48
- end
49
- else
50
- # Effectively, an anonymous user
51
- @current_api_user = Spree.user_class.new
52
- end
53
- end
54
-
55
- def unauthorized
56
- render "spree/api/v1/errors/unauthorized", :status => 401 and return
57
- end
58
-
59
- def requires_authentication?
60
- Spree::Api::Config[:requires_authentication]
61
- end
62
-
63
- def not_found
64
- render "spree/api/v1/errors/not_found", :status => 404 and return
65
- end
66
-
67
- def error_during_processing(exception)
68
- render :text => { exception: exception.message }.to_json,
69
- :status => 422 and return
70
- end
71
-
72
- def current_ability
73
- Spree::Ability.new(current_api_user)
74
- end
75
-
76
- def invalid_resource!(resource)
77
- @resource = resource
78
- render "spree/api/v1/errors/invalid_resource", :status => 422
79
- end
80
-
81
- def api_key
82
- request.headers["X-Spree-Token"] || params[:token]
83
- end
84
- helper_method :api_key
85
-
86
- def find_product(id)
87
- begin
88
- product_scope.find_by_permalink!(id.to_s)
89
- rescue ActiveRecord::RecordNotFound
90
- product_scope.find(id)
91
- end
92
- end
93
-
94
- def product_scope
95
- if current_api_user.has_spree_role?("admin")
96
- scope = Product
97
- unless params[:show_deleted]
98
- scope = scope.not_deleted
99
- end
100
- else
101
- scope = Product.active
102
- end
103
-
104
- scope.includes(:master)
105
- end
106
-
107
- end
108
- end
109
- end
110
- end
111
-
@@ -1,50 +0,0 @@
1
- module Spree
2
- module Api
3
- module V1
4
- class InventoryUnitsController < Spree::Api::V1::BaseController
5
- before_filter :prepare_event, :only => :update
6
-
7
- def show
8
- @inventory_unit = inventory_unit
9
- end
10
-
11
- def update
12
- authorize! :update, Order
13
-
14
- inventory_unit.transaction do
15
- if inventory_unit.update_attributes(params[:inventory_unit])
16
- fire
17
- render :show, :status => 200
18
- else
19
- invalid_resource!(inventory_unit)
20
- end
21
- end
22
- end
23
-
24
- private
25
-
26
- def inventory_unit
27
- @inventory_unit ||= InventoryUnit.find(params[:id])
28
- end
29
-
30
- def prepare_event
31
- return unless @event = params[:fire]
32
-
33
- can_event = "can_#{@event}?"
34
-
35
- unless inventory_unit.respond_to?(can_event) &&
36
- inventory_unit.send(can_event)
37
- render :text => { exception: "cannot transition to #{@event}" }.to_json,
38
- :status => 200
39
- false
40
- end
41
- end
42
-
43
- def fire
44
- inventory_unit.send("#{@event}!") if @event
45
- end
46
-
47
- end
48
- end
49
- end
50
- end