spree_api 1.0.7 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +6 -0
  3. data/LICENSE +19 -23
  4. data/README.md +22 -10
  5. data/Rakefile +30 -0
  6. data/app/controllers/spree/api/v1/base_controller.rb +71 -0
  7. data/app/controllers/spree/api/v1/images_controller.rb +46 -0
  8. data/app/controllers/spree/api/v1/line_items_controller.rb +40 -0
  9. data/app/controllers/spree/api/v1/orders_controller.rb +53 -0
  10. data/app/controllers/spree/api/v1/products_controller.rb +46 -0
  11. data/app/controllers/spree/api/v1/variants_controller.rb +56 -0
  12. data/app/helpers/spree/api/api_helpers.rb +44 -0
  13. data/app/models/spree/line_item_decorator.rb +3 -0
  14. data/app/models/spree/option_value_decorator.rb +5 -0
  15. data/app/models/spree/order_decorator.rb +12 -0
  16. data/app/models/spree/user_decorator.rb +11 -0
  17. data/app/views/spree/api/v1/errors/invalid_api_key.rabl +2 -0
  18. data/app/views/spree/api/v1/errors/invalid_resource.rabl +3 -0
  19. data/app/views/spree/api/v1/errors/must_specify_api_key.rabl +2 -0
  20. data/app/views/spree/api/v1/errors/not_found.rabl +2 -0
  21. data/app/views/spree/api/v1/errors/unauthorized.rabl +2 -0
  22. data/app/views/spree/api/v1/images/show.rabl +2 -0
  23. data/app/views/spree/api/v1/line_items/new.rabl +3 -0
  24. data/app/views/spree/api/v1/line_items/show.rabl +5 -0
  25. data/app/views/spree/api/v1/orders/address.rabl +0 -0
  26. data/app/views/spree/api/v1/orders/cart.rabl +0 -0
  27. data/app/views/spree/api/v1/orders/complete.rabl +0 -0
  28. data/app/views/spree/api/v1/orders/could_not_transition.rabl +3 -0
  29. data/app/views/spree/api/v1/orders/delivery.rabl +3 -0
  30. data/app/views/spree/api/v1/orders/index.rabl +7 -0
  31. data/app/views/spree/api/v1/orders/invalid_shipping_method.rabl +2 -0
  32. data/app/views/spree/api/v1/orders/payment.rabl +0 -0
  33. data/app/views/spree/api/v1/orders/show.rabl +3 -0
  34. data/app/views/spree/api/v1/products/index.rabl +8 -0
  35. data/app/views/spree/api/v1/products/new.rabl +3 -0
  36. data/app/views/spree/api/v1/products/product.rabl +1 -0
  37. data/app/views/spree/api/v1/products/show.rabl +21 -0
  38. data/app/views/spree/api/v1/variants/index.rabl +3 -0
  39. data/app/views/spree/api/v1/variants/new.rabl +2 -0
  40. data/app/views/spree/api/v1/variants/show.rabl +3 -0
  41. data/app/views/spree/api/v1/variants/variant.rabl +1 -0
  42. data/config/locales/en.yml +11 -15
  43. data/config/routes.rb +14 -28
  44. data/db/migrate/{20100107141738_add_api_key_to_users.rb → 20100107141738_add_api_key_to_spree_users.rb} +1 -1
  45. data/lib/spree/api.rb +7 -4
  46. data/lib/spree/api/controller_setup.rb +27 -0
  47. data/lib/spree/api/engine.rb +3 -13
  48. data/lib/spree/api/version.rb +5 -0
  49. data/lib/spree_api.rb +0 -2
  50. data/script/rails +5 -0
  51. data/spec/controllers/spree/api/v1/base_controller_spec.rb +29 -0
  52. data/spec/controllers/spree/api/v1/images_controller_spec.rb +50 -0
  53. data/spec/controllers/spree/api/v1/line_items_controller_spec.rb +77 -0
  54. data/spec/controllers/spree/api/v1/orders_controller_spec.rb +148 -0
  55. data/spec/controllers/spree/api/v1/products_controller_spec.rb +159 -0
  56. data/spec/controllers/spree/api/v1/variants_controller_spec.rb +90 -0
  57. data/spec/fixtures/thinking-cat.jpg +0 -0
  58. data/spec/models/spree/order_spec.rb +18 -0
  59. data/spec/models/spree/user_spec.rb +19 -0
  60. data/spec/spec_helper.rb +28 -0
  61. data/spec/support/api_helpers.rb +68 -0
  62. data/spec/support/controller_hacks.rb +27 -0
  63. data/spree_api.gemspec +24 -0
  64. metadata +123 -56
  65. data/app/assets/javascripts/admin/spree.js +0 -4
  66. data/app/assets/javascripts/admin/spree_api.js +0 -2
  67. data/app/assets/javascripts/store/spree.js +0 -4
  68. data/app/assets/javascripts/store/spree_api.js +0 -2
  69. data/app/assets/stylesheets/admin/spree.css +0 -6
  70. data/app/assets/stylesheets/admin/spree_api.css +0 -4
  71. data/app/assets/stylesheets/store/spree.css +0 -6
  72. data/app/assets/stylesheets/store/spree_api.css +0 -4
  73. data/app/controllers/spree/admin/users_controller_decorator.rb +0 -17
  74. data/app/controllers/spree/api/base_controller.rb +0 -172
  75. data/app/controllers/spree/api/countries_controller.rb +0 -3
  76. data/app/controllers/spree/api/inventory_units_controller.rb +0 -18
  77. data/app/controllers/spree/api/line_items_controller.rb +0 -20
  78. data/app/controllers/spree/api/orders_controller.rb +0 -19
  79. data/app/controllers/spree/api/products_controller.rb +0 -14
  80. data/app/controllers/spree/api/shipments_controller.rb +0 -35
  81. data/app/controllers/spree/api/states_controller.rb +0 -8
  82. data/app/models/line_item_decorator.rb +0 -7
  83. data/app/models/order_decorator.rb +0 -9
  84. data/app/models/shipment_decorator.rb +0 -9
  85. data/app/models/user_decorator.rb +0 -19
  86. data/app/overrides/api_admin_user_edit_form.rb +0 -6
  87. data/app/views/spree/admin/users/_api_fields.html.erb +0 -16
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ eval(File.read(File.dirname(__FILE__) + '/../common_spree_dependencies.rb'))
2
+
3
+ gem 'spree_core', :path => "../core"
4
+ gem 'spree_auth', :path => "../auth"
5
+
6
+ gemspec
data/LICENSE CHANGED
@@ -1,26 +1,22 @@
1
- Copyright (c) 2007-2012, Spree Commerce, Inc. and other contributors
2
- All rights reserved.
1
+ Copyright (c) 2012 Ryan Bigg
3
2
 
4
- Redistribution and use in source and binary forms, with or without modification,
5
- are permitted provided that the following conditions are met:
3
+ MIT License
6
4
 
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.
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:
15
12
 
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.
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
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.
data/README.md CHANGED
@@ -1,17 +1,29 @@
1
- API
2
- ===
1
+ # Api
3
2
 
4
- Manage orders,shipments etc. with a simple REST API
3
+ TODO: Write a gem description
5
4
 
6
- See [RESTful API guide](http://spreecommerce.com/documentation/rest.html) for more details.
5
+ ## Installation
7
6
 
8
- Testing
9
- -------
7
+ Add this line to your application's Gemfile:
10
8
 
11
- Create the test site
9
+ gem 'api'
12
10
 
13
- bundle exec rake test_app
11
+ And then execute:
14
12
 
15
- Run the tests
13
+ $ bundle
16
14
 
17
- bundle exec rake spec
15
+ Or install it yourself as:
16
+
17
+ $ gem install api
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/packagetask'
5
+ require 'rubygems/package_task'
6
+ require 'rspec/core/rake_task'
7
+ require 'spree/core/testing_support/common_rake'
8
+ require 'rails/all'
9
+
10
+ Bundler::GemHelper.install_tasks
11
+ RSpec::Core::RakeTask.new
12
+
13
+ spec = eval(File.read('spree_api.gemspec'))
14
+ Gem::PackageTask.new(spec) do |p|
15
+ p.gem_spec = spec
16
+ end
17
+
18
+ desc "Release to gemcutter"
19
+ task :release do
20
+ version = File.read(File.expand_path("../../SPREE_VERSION", __FILE__)).strip
21
+ cmd = "cd pkg && gem push spree_api-#{version}.gem"; puts cmd; system cmd
22
+ end
23
+
24
+ task :default => :spec
25
+
26
+ desc "Generates a dummy app for testing"
27
+ task :test_app do
28
+ ENV['LIB_NAME'] = 'spree/api'
29
+ Rake::Task['common:test_app'].invoke
30
+ end
@@ -0,0 +1,71 @@
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 :check_for_api_key
10
+ before_filter :authenticate_user
11
+
12
+ rescue_from CanCan::AccessDenied, :with => :unauthorized
13
+ rescue_from ActiveRecord::RecordNotFound, :with => :not_found
14
+
15
+ helper Spree::Api::ApiHelpers
16
+
17
+ private
18
+
19
+ def check_for_api_key
20
+ render "spree/api/v1/errors/must_specify_api_key", :status => 401 and return if api_key.blank?
21
+ end
22
+
23
+ def authenticate_user
24
+ unless @current_api_user = User.find_by_api_key(api_key)
25
+ render "spree/api/v1/errors/invalid_api_key", :status => 401 and return
26
+ end
27
+ end
28
+
29
+ def unauthorized
30
+ render "spree/api/v1/errors/unauthorized", :status => 401 and return
31
+ end
32
+
33
+ def not_found
34
+ render "spree/api/v1/errors/not_found", :status => 404 and return
35
+ end
36
+
37
+ def current_ability
38
+ Spree::Ability.new(current_api_user)
39
+ end
40
+
41
+ def invalid_resource!(resource)
42
+ render "spree/api/v1/errors/invalid_resource", :resource => resource, :status => 422
43
+ end
44
+
45
+ def api_key
46
+ request.headers["X-Spree-Token"] || params[:token]
47
+ end
48
+ helper_method :api_key
49
+
50
+ def find_product(id)
51
+ begin
52
+ product_scope.find_by_permalink!(id)
53
+ rescue ActiveRecord::RecordNotFound
54
+ product_scope.find(id)
55
+ end
56
+ end
57
+
58
+ def product_scope
59
+ if current_api_user.has_role?("admin")
60
+ scope = Product
61
+ else
62
+ scope = Product.active
63
+ end
64
+ scope.includes(:master)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+ end
71
+
@@ -0,0 +1,46 @@
1
+ module Spree
2
+ module Api
3
+ module V1
4
+ class ImagesController < Spree::Api::V1::BaseController
5
+ def create
6
+ @image = product_or_variant.images.create!(params[:image])
7
+ render :show, :status => 201
8
+ end
9
+
10
+ def update
11
+ image.update_attributes(params[:image])
12
+ render :show, :status => 200
13
+ end
14
+
15
+ def destroy
16
+ image.destroy
17
+ render :text => nil
18
+ end
19
+
20
+ private
21
+
22
+ def image
23
+ @image = product_or_variant.images.find(params[:id])
24
+ end
25
+
26
+ def product_or_variant
27
+ return @product_or_variant if @product_or_variant
28
+ if params[:product_id]
29
+ @product_or_variant = product
30
+ else
31
+ @product_or_variant = variant
32
+ end
33
+ end
34
+
35
+ def variant
36
+ Variant.find(params[:variant_id])
37
+ end
38
+
39
+ def product
40
+ find_product(params[:product_id]).master
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,40 @@
1
+ module Spree
2
+ module Api
3
+ module V1
4
+ class LineItemsController < Spree::Api::V1::BaseController
5
+ def create
6
+ authorize! :read, order
7
+ @line_item = order.line_items.build(params[:line_item], :as => :api)
8
+ if @line_item.save
9
+ render :show, :status => 201
10
+ else
11
+ invalid_resource!(@line_item)
12
+ end
13
+ end
14
+
15
+ def update
16
+ authorize! :read, order
17
+ @line_item = order.line_items.find(params[:id])
18
+ if @line_item.update_attributes(params[:line_item])
19
+ render :show
20
+ else
21
+ invalid_resource!(@line_item)
22
+ end
23
+ end
24
+
25
+ def destroy
26
+ authorize! :read, order
27
+ @line_item = order.line_items.find(params[:id])
28
+ @line_item.destroy
29
+ render :text => nil, :status => 200
30
+ end
31
+
32
+ private
33
+
34
+ def order
35
+ @order ||= Order.find_by_number!(params[:order_id])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,53 @@
1
+ module Spree
2
+ module Api
3
+ module V1
4
+ class OrdersController < Spree::Api::V1::BaseController
5
+ def index
6
+ # should probably look at turning this into a CanCan step
7
+ raise CanCan::AccessDenied unless current_api_user.has_role?("admin")
8
+ @orders = Order.page(params[:page])
9
+ end
10
+
11
+ def show
12
+ authorize! :read, order
13
+ end
14
+
15
+ def create
16
+ @order = Order.build_from_api(current_api_user, params[:order])
17
+ next!
18
+ end
19
+
20
+ def address
21
+ order.build_ship_address(params[:shipping_address])
22
+ order.build_bill_address(params[:billing_address])
23
+ next!
24
+ end
25
+
26
+ def delivery
27
+ begin
28
+ ShippingMethod.find(params[:shipping_method_id])
29
+ rescue ActiveRecord::RecordNotFound
30
+ render :invalid_shipping_method, :status => 422
31
+ else
32
+ order.update_attribute(:shipping_method_id, params[:shipping_method_id])
33
+ next!
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def order
40
+ @order ||= Order.find_by_number!(params[:id])
41
+ end
42
+
43
+ def next!
44
+ if @order.valid? && @order.next
45
+ render :show, :status => 200
46
+ else
47
+ render :could_not_transition, :status => 422
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ module Spree
2
+ module Api
3
+ module V1
4
+ class ProductsController < Spree::Api::V1::BaseController
5
+ def index
6
+ @products = product_scope.page(params[:page])
7
+ end
8
+
9
+ def show
10
+ @product = find_product(params[:id])
11
+ end
12
+
13
+ def new
14
+ end
15
+
16
+ def create
17
+ authorize! :create, Product
18
+ @product = Product.new(params[:product])
19
+ if @product.save
20
+ render :show, :status => 201
21
+ else
22
+ invalid_resource!(@product)
23
+ end
24
+ end
25
+
26
+ def update
27
+ authorize! :update, Product
28
+ @product = find_product(params[:id])
29
+ if @product.update_attributes(params[:product])
30
+ render :show, :status => 200
31
+ else
32
+ invalid_resource!(@product)
33
+ end
34
+ end
35
+
36
+ def destroy
37
+ authorize! :delete, Product
38
+ @product = find_product(params[:id])
39
+ @product.update_attribute(:deleted_at, Time.now)
40
+ @product.variants_including_master.update_all(:deleted_at => Time.now)
41
+ render :text => nil, :status => 200
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,56 @@
1
+ module Spree
2
+ module Api
3
+ module V1
4
+ class VariantsController < Spree::Api::V1::BaseController
5
+ before_filter :product
6
+
7
+ def index
8
+ @variants = scope.includes(:option_values).scoped
9
+ end
10
+
11
+ def show
12
+ @variant = scope.includes(:option_values).find(params[:id])
13
+ end
14
+
15
+ def new
16
+ end
17
+
18
+ def create
19
+ authorize! :create, Variant
20
+ @variant = scope.new(params[:product])
21
+ if @variant.save
22
+ render :show, :status => 201
23
+ else
24
+ invalid_resource!(@variant)
25
+ end
26
+ end
27
+
28
+ def update
29
+ authorize! :update, Variant
30
+ @variant = scope.find(params[:id])
31
+ if @variant.update_attributes(params[:variant])
32
+ render :show, :status => 200
33
+ else
34
+ invalid_resource!(@product)
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ authorize! :delete, Variant
40
+ @variant = scope.find(params[:id])
41
+ @variant.destroy
42
+ render :text => nil, :status => 200
43
+ end
44
+
45
+ private
46
+ def product
47
+ @product ||= Spree::Product.find_by_permalink(params[:product_id]) if params[:product_id]
48
+ end
49
+
50
+ def scope
51
+ @product ? @product.variants_including_master : Variant
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end