dup_spree_api 1.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +22 -0
  5. data/Rakefile +30 -0
  6. data/app/controllers/spree/api/addresses_controller.rb +20 -0
  7. data/app/controllers/spree/api/base_controller.rb +114 -0
  8. data/app/controllers/spree/api/countries_controller.rb +18 -0
  9. data/app/controllers/spree/api/images_controller.rb +32 -0
  10. data/app/controllers/spree/api/line_items_controller.rb +40 -0
  11. data/app/controllers/spree/api/orders_controller.rb +85 -0
  12. data/app/controllers/spree/api/payments_controller.rb +80 -0
  13. data/app/controllers/spree/api/product_properties_controller.rb +65 -0
  14. data/app/controllers/spree/api/products_controller.rb +49 -0
  15. data/app/controllers/spree/api/return_authorizations_controller.rb +54 -0
  16. data/app/controllers/spree/api/shipments_controller.rb +43 -0
  17. data/app/controllers/spree/api/taxonomies_controller.rb +50 -0
  18. data/app/controllers/spree/api/taxons_controller.rb +53 -0
  19. data/app/controllers/spree/api/variants_controller.rb +75 -0
  20. data/app/controllers/spree/api/zones_controller.rb +46 -0
  21. data/app/helpers/spree/api/api_helpers.rb +76 -0
  22. data/app/models/spree/api_configuration.rb +5 -0
  23. data/app/models/spree/line_item_decorator.rb +3 -0
  24. data/app/models/spree/option_value_decorator.rb +5 -0
  25. data/app/models/spree/order_decorator.rb +13 -0
  26. data/app/models/spree/user_decorator.rb +13 -0
  27. data/app/overrides/api_admin_user_edit_form.rb +6 -0
  28. data/app/views/spree/admin/users/_api_fields.html.erb +32 -0
  29. data/app/views/spree/api/addresses/show.v1.rabl +11 -0
  30. data/app/views/spree/api/countries/index.v1.rabl +7 -0
  31. data/app/views/spree/api/countries/show.v1.rabl +5 -0
  32. data/app/views/spree/api/errors/gateway_error.v1.rabl +2 -0
  33. data/app/views/spree/api/errors/invalid_api_key.v1.rabl +2 -0
  34. data/app/views/spree/api/errors/invalid_resource.v1.rabl +3 -0
  35. data/app/views/spree/api/errors/must_specify_api_key.v1.rabl +2 -0
  36. data/app/views/spree/api/errors/not_found.v1.rabl +2 -0
  37. data/app/views/spree/api/errors/unauthorized.v1.rabl +2 -0
  38. data/app/views/spree/api/images/show.v1.rabl +3 -0
  39. data/app/views/spree/api/line_items/new.v1.rabl +3 -0
  40. data/app/views/spree/api/line_items/show.v1.rabl +5 -0
  41. data/app/views/spree/api/orders/address.v1.rabl +0 -0
  42. data/app/views/spree/api/orders/canceled.v1.rabl +0 -0
  43. data/app/views/spree/api/orders/cart.v1.rabl +0 -0
  44. data/app/views/spree/api/orders/complete.v1.rabl +0 -0
  45. data/app/views/spree/api/orders/could_not_transition.v1.rabl +3 -0
  46. data/app/views/spree/api/orders/delivery.v1.rabl +3 -0
  47. data/app/views/spree/api/orders/index.v1.rabl +7 -0
  48. data/app/views/spree/api/orders/invalid_shipping_method.v1.rabl +2 -0
  49. data/app/views/spree/api/orders/payment.v1.rabl +4 -0
  50. data/app/views/spree/api/orders/show.v1.rabl +29 -0
  51. data/app/views/spree/api/payments/credit_over_limit.v1.rabl +2 -0
  52. data/app/views/spree/api/payments/index.v1.rabl +7 -0
  53. data/app/views/spree/api/payments/new.v1.rabl +6 -0
  54. data/app/views/spree/api/payments/show.v1.rabl +2 -0
  55. data/app/views/spree/api/product_properties/index.v1.rabl +7 -0
  56. data/app/views/spree/api/product_properties/new.v1.rabl +2 -0
  57. data/app/views/spree/api/product_properties/show.v1.rabl +2 -0
  58. data/app/views/spree/api/products/index.v1.rabl +8 -0
  59. data/app/views/spree/api/products/new.v1.rabl +3 -0
  60. data/app/views/spree/api/products/product.v1.rabl +1 -0
  61. data/app/views/spree/api/products/show.v1.rabl +25 -0
  62. data/app/views/spree/api/return_authorizations/index.v1.rabl +7 -0
  63. data/app/views/spree/api/return_authorizations/new.v1.rabl +3 -0
  64. data/app/views/spree/api/return_authorizations/show.v1.rabl +2 -0
  65. data/app/views/spree/api/shipments/cannot_ready_shipment.v1.rabl +2 -0
  66. data/app/views/spree/api/shipments/show.v1.rabl +7 -0
  67. data/app/views/spree/api/taxonomies/index.v1.rabl +7 -0
  68. data/app/views/spree/api/taxonomies/nested.v1.rabl +11 -0
  69. data/app/views/spree/api/taxonomies/new.v1.rabl +3 -0
  70. data/app/views/spree/api/taxonomies/show.v1.rabl +15 -0
  71. data/app/views/spree/api/taxons/index.v1.rabl +4 -0
  72. data/app/views/spree/api/taxons/new.v1.rabl +3 -0
  73. data/app/views/spree/api/taxons/show.v1.rabl +8 -0
  74. data/app/views/spree/api/taxons/taxons.v1.rabl +7 -0
  75. data/app/views/spree/api/variants/index.v1.rabl +10 -0
  76. data/app/views/spree/api/variants/new.v1.rabl +2 -0
  77. data/app/views/spree/api/variants/show.v1.rabl +3 -0
  78. data/app/views/spree/api/variants/variant.v1.rabl +1 -0
  79. data/app/views/spree/api/zones/index.v1.rabl +7 -0
  80. data/app/views/spree/api/zones/show.v1.rabl +6 -0
  81. data/config/initializers/metal_load_paths.rb +1 -0
  82. data/config/locales/en.yml +23 -0
  83. data/config/routes.rb +56 -0
  84. data/db/migrate/20100107141738_add_api_key_to_spree_users.rb +7 -0
  85. data/db/migrate/20120411123334_resize_api_key_field.rb +7 -0
  86. data/db/migrate/20120530054546_rename_api_key_to_spree_api_key.rb +7 -0
  87. data/lib/spree/api.rb +12 -0
  88. data/lib/spree/api/controller_setup.rb +27 -0
  89. data/lib/spree/api/engine.rb +35 -0
  90. data/lib/spree/api/responders.rb +11 -0
  91. data/lib/spree/api/responders/rabl_template.rb +22 -0
  92. data/lib/spree/api/testing_support/helpers.rb +35 -0
  93. data/lib/spree/api/testing_support/setup.rb +28 -0
  94. data/lib/spree/api/version.rb +5 -0
  95. data/lib/spree_api.rb +3 -0
  96. data/script/rails +9 -0
  97. data/spec/controllers/spree/api/addresses_controller_spec.rb +45 -0
  98. data/spec/controllers/spree/api/base_controller_spec.rb +42 -0
  99. data/spec/controllers/spree/api/countries_controller_spec.rb +48 -0
  100. data/spec/controllers/spree/api/images_controller_spec.rb +66 -0
  101. data/spec/controllers/spree/api/line_items_controller_spec.rb +77 -0
  102. data/spec/controllers/spree/api/orders_controller_spec.rb +255 -0
  103. data/spec/controllers/spree/api/payments_controller_spec.rb +203 -0
  104. data/spec/controllers/spree/api/product_properties_controller_spec.rb +116 -0
  105. data/spec/controllers/spree/api/products_controller_spec.rb +211 -0
  106. data/spec/controllers/spree/api/return_authorizations_controller_spec.rb +155 -0
  107. data/spec/controllers/spree/api/shipments_controller_spec.rb +59 -0
  108. data/spec/controllers/spree/api/taxonomies_controller_spec.rb +107 -0
  109. data/spec/controllers/spree/api/taxons_controller_spec.rb +87 -0
  110. data/spec/controllers/spree/api/unauthenticated_products_controller_spec.rb +26 -0
  111. data/spec/controllers/spree/api/variants_controller_spec.rb +155 -0
  112. data/spec/controllers/spree/api/zones_controller_spec.rb +111 -0
  113. data/spec/fixtures/thinking-cat.jpg +0 -0
  114. data/spec/models/spree/legacy_user_spec.rb +19 -0
  115. data/spec/models/spree/order_spec.rb +18 -0
  116. data/spec/shared_examples/protect_product_actions.rb +17 -0
  117. data/spec/spec_helper.rb +27 -0
  118. data/spec/support/controller_hacks.rb +27 -0
  119. data/spec/support/database_cleaner.rb +14 -0
  120. data/spec/support/have_attributes_matcher.rb +13 -0
  121. data/spree_api.gemspec +23 -0
  122. metadata +254 -0
@@ -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/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ eval(File.read(File.dirname(__FILE__) + '/../common_spree_dependencies.rb'))
2
+
3
+ gem 'spree_core', :path => "../core"
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ryan Bigg
2
+
3
+ MIT License
4
+
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:
12
+
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.
@@ -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,20 @@
1
+ module Spree
2
+ module Api
3
+ class AddressesController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ def show
7
+ @address = Address.find(params[:id])
8
+ authorize! :read, @address
9
+ respond_with(@address)
10
+ end
11
+
12
+ def update
13
+ @address = Address.find(params[:id])
14
+ authorize! :read, @address
15
+ @address.update_attributes(params[:address])
16
+ respond_with(@address, :default_template => :show)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,114 @@
1
+ module Spree
2
+ module Api
3
+ class BaseController < ActionController::Metal
4
+ include Spree::Api::ControllerSetup
5
+ include ::ActionController::Head
6
+
7
+ self.responder = Spree::Api::Responders::AppResponder
8
+
9
+ attr_accessor :current_api_user
10
+
11
+ before_filter :set_content_type
12
+ before_filter :check_for_api_key, :if => :requires_authentication?
13
+ before_filter :authenticate_user
14
+ after_filter :set_jsonp_format
15
+
16
+ rescue_from CanCan::AccessDenied, :with => :unauthorized
17
+ rescue_from ActiveRecord::RecordNotFound, :with => :not_found
18
+
19
+ helper Spree::Api::ApiHelpers
20
+
21
+ def set_jsonp_format
22
+ if params[:callback] && request.get?
23
+ self.response_body = "#{params[:callback]}(#{self.response_body})"
24
+ headers["Content-Type"] = 'application/javascript'
25
+ end
26
+ end
27
+
28
+ def map_nested_attributes_keys(klass, attributes)
29
+ nested_keys = klass.nested_attributes_options.keys
30
+ attributes.inject({}) do |h, (k,v)|
31
+ key = nested_keys.include?(k.to_sym) ? "#{k}_attributes" : k
32
+ h[key] = v
33
+ h
34
+ end.with_indifferent_access
35
+ end
36
+
37
+ private
38
+
39
+ def set_content_type
40
+ content_type = case params[:format]
41
+ when "json"
42
+ "application/json"
43
+ when "xml"
44
+ "text/xml"
45
+ end
46
+ headers["Content-Type"] = content_type
47
+ end
48
+
49
+ def check_for_api_key
50
+ render "spree/api/errors/must_specify_api_key", :status => 401 and return if api_key.blank?
51
+ end
52
+
53
+ def authenticate_user
54
+ if requires_authentication? || api_key.present?
55
+ unless @current_api_user = Spree.user_class.find_by_spree_api_key(api_key)
56
+ render "spree/api/errors/invalid_api_key", :status => 401 and return
57
+ end
58
+ else
59
+ # Effectively, an anonymous user
60
+ @current_api_user = Spree.user_class.new
61
+ end
62
+ end
63
+
64
+ def unauthorized
65
+ render "spree/api/errors/unauthorized", :status => 401 and return
66
+ end
67
+
68
+ def requires_authentication?
69
+ Spree::Api::Config[:requires_authentication]
70
+ end
71
+
72
+ def not_found
73
+ render "spree/api/errors/not_found", :status => 404 and return
74
+ end
75
+
76
+ def current_ability
77
+ Spree::Ability.new(current_api_user)
78
+ end
79
+
80
+ def invalid_resource!(resource)
81
+ @resource = resource
82
+ render "spree/api/errors/invalid_resource", :status => 422
83
+ end
84
+
85
+ def api_key
86
+ request.headers["X-Spree-Token"] || params[:token]
87
+ end
88
+ helper_method :api_key
89
+
90
+ def find_product(id)
91
+ begin
92
+ product_scope.find_by_permalink!(id.to_s)
93
+ rescue ActiveRecord::RecordNotFound
94
+ product_scope.find(id)
95
+ end
96
+ end
97
+
98
+ def product_scope
99
+ if current_api_user.has_spree_role?("admin")
100
+ scope = Product
101
+ unless params[:show_deleted]
102
+ scope = scope.not_deleted
103
+ end
104
+ else
105
+ scope = Product.active
106
+ end
107
+
108
+ scope.includes(:master)
109
+ end
110
+
111
+ end
112
+ end
113
+ end
114
+
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ module Api
3
+ class CountriesController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ def index
7
+ @countries = Country.ransack(params[:q]).result.includes(:states).order('name ASC')
8
+ .page(params[:page]).per(params[:per_page])
9
+ respond_with(@countries)
10
+ end
11
+
12
+ def show
13
+ @country = Country.find(params[:id])
14
+ respond_with(@country)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,32 @@
1
+ module Spree
2
+ module Api
3
+ class ImagesController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ def show
7
+ @image = Image.find(params[:id])
8
+ respond_with(@image)
9
+ end
10
+
11
+ def create
12
+ authorize! :create, Image
13
+ @image = Image.create(params[:image])
14
+ respond_with(@image, :status => 201, :default_template => :show)
15
+ end
16
+
17
+ def update
18
+ authorize! :update, Image
19
+ @image = Image.find(params[:id])
20
+ @image.update_attributes(params[:image])
21
+ respond_with(@image, :default_template => :show)
22
+ end
23
+
24
+ def destroy
25
+ authorize! :delete, Image
26
+ @image = Image.find(params[:id])
27
+ @image.destroy
28
+ respond_with(@image, :status => 204)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ module Spree
2
+ module Api
3
+ class LineItemsController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ def create
7
+ authorize! :read, order
8
+ @line_item = order.line_items.build(params[:line_item], :as => :api)
9
+ if @line_item.save
10
+ respond_with(@line_item, :status => 201, :default_template => :show)
11
+ else
12
+ invalid_resource!(@line_item)
13
+ end
14
+ end
15
+
16
+ def update
17
+ authorize! :read, order
18
+ @line_item = order.line_items.find(params[:id])
19
+ if @line_item.update_attributes(params[:line_item])
20
+ respond_with(@line_item, :default_template => :show)
21
+ else
22
+ invalid_resource!(@line_item)
23
+ end
24
+ end
25
+
26
+ def destroy
27
+ authorize! :read, order
28
+ @line_item = order.line_items.find(params[:id])
29
+ @line_item.destroy
30
+ respond_with(@line_item, :status => 204)
31
+ end
32
+
33
+ private
34
+
35
+ def order
36
+ @order ||= Order.find_by_number!(params[:order_id])
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,85 @@
1
+ module Spree
2
+ module Api
3
+ class OrdersController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ before_filter :authorize_read!, :except => [:index, :search, :create]
7
+
8
+ def index
9
+ # should probably look at turning this into a CanCan step
10
+ raise CanCan::AccessDenied unless current_api_user.has_spree_role?("admin")
11
+ @orders = Order.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
12
+ respond_with(@orders)
13
+ end
14
+
15
+ def show
16
+ respond_with(@order)
17
+ end
18
+
19
+ def create
20
+ @order = Order.build_from_api(current_api_user, nested_params)
21
+ next!(:status => 201)
22
+ end
23
+
24
+ def update
25
+ authorize! :update, Order
26
+ if order.update_attributes(nested_params)
27
+ order.update!
28
+ respond_with(order, :default_template => :show)
29
+ else
30
+ invalid_resource!(order)
31
+ end
32
+ end
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
+ def cancel
52
+ order.cancel!
53
+ render :show
54
+ end
55
+
56
+ def empty
57
+ order.line_items.destroy_all
58
+ order.update!
59
+ render :text => nil, :status => 200
60
+ end
61
+
62
+ private
63
+
64
+ def nested_params
65
+ map_nested_attributes_keys Order, params[:order] || {}
66
+ end
67
+
68
+ def order
69
+ @order ||= Order.find_by_number!(params[:id])
70
+ end
71
+
72
+ def next!(options={})
73
+ if @order.valid? && @order.next
74
+ render :show, :status => options[:status] || 200
75
+ else
76
+ render :could_not_transition, :status => 422
77
+ end
78
+ end
79
+
80
+ def authorize_read!
81
+ authorize! :read, order
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,80 @@
1
+ module Spree
2
+ module Api
3
+ class PaymentsController < Spree::Api::BaseController
4
+ respond_to :json
5
+
6
+ before_filter :find_order
7
+ before_filter :find_payment, :only => [:show, :authorize, :purchase, :capture, :void, :credit]
8
+
9
+ def index
10
+ @payments = @order.payments.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
11
+ respond_with(@payments)
12
+ end
13
+
14
+ def new
15
+ @payment_methods = Spree::PaymentMethod.where(:environment => Rails.env)
16
+ respond_with(@payment_method)
17
+ end
18
+
19
+ def create
20
+ @payment = @order.payments.build(params[:payment])
21
+ if @payment.save
22
+ respond_with(@payment, :status => 201, :default_template => :show)
23
+ else
24
+ invalid_resource!(@payment)
25
+ end
26
+ end
27
+
28
+ def show
29
+ respond_with(@payment)
30
+ end
31
+
32
+ def authorize
33
+ perform_payment_action(:authorize)
34
+ end
35
+
36
+ def capture
37
+ perform_payment_action(:capture)
38
+ end
39
+
40
+ def purchase
41
+ perform_payment_action(:purchase)
42
+ end
43
+
44
+ def void
45
+ perform_payment_action(:void_transaction)
46
+ end
47
+
48
+ def credit
49
+ if params[:amount].to_f > @payment.credit_allowed
50
+ render "spree/api/payments/credit_over_limit", :status => 422
51
+ else
52
+ perform_payment_action(:credit, params[:amount])
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def find_order
59
+ @order = Order.find_by_number(params[:order_id])
60
+ authorize! :read, @order
61
+ end
62
+
63
+ def find_payment
64
+ @payment = @order.payments.find(params[:id])
65
+ end
66
+
67
+ def perform_payment_action(action, *args)
68
+ authorize! action, Payment
69
+
70
+ begin
71
+ @payment.send("#{action}!", *args)
72
+ respond_with(@payment, :default_template => :show)
73
+ rescue Spree::Core::GatewayError => e
74
+ @error = e.message
75
+ render "spree/api/errors/gateway_error", :status => 422
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end