spree_api 0.30.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2007-2010, Rails Dog LLC and other contributors
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
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.
15
+
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.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ Spree API
2
+ =========
3
+ Manage orders,shipments etc. with a simple REST API
4
+
5
+ See [RESTful API guide](http://spreecommerce.com/documentation/rest.html) for more details.
@@ -0,0 +1,97 @@
1
+ class Api::BaseController < Spree::BaseController
2
+
3
+ def self.resource_controller_for_api
4
+ resource_controller
5
+ skip_before_filter :verify_authenticity_token, :if => lambda { admin_token_passed_in_headers }
6
+
7
+ index.response do |wants|
8
+ wants.json { render :json => collection.to_json(collection_serialization_options) }
9
+ end
10
+
11
+ show.response do |wants|
12
+ wants.json { render :json => object.to_json(object_serialization_options) }
13
+ end
14
+
15
+ create do
16
+ wants.json { redirect_to object_url, :status => 201 }
17
+ failure.wants.json { render :json => object_errors.to_json, :status => 422 }
18
+ end
19
+
20
+ update do
21
+ wants.json { render :nothing => true }
22
+ failure.wants.json { render :json => object_errors.to_json, :status => 422 }
23
+ end
24
+
25
+ define_method :admin_token_passed_in_headers do
26
+ token = request.headers['X-SpreeAPIKey']
27
+ return false unless token
28
+ @current_user = User.find_by_api_key(token)
29
+ @current_user.has_role? 'admin'
30
+ end
31
+
32
+ define_method :end_of_association_chain do
33
+ (parent? ? parent_association : model).scoped(:include => eager_load_associations)
34
+ end
35
+
36
+ define_method :collection do
37
+ @collection ||= search.all(:limit => 100)
38
+ end
39
+ end
40
+
41
+ def access_denied
42
+ render :text => 'access_denied', :status => 401
43
+ end
44
+
45
+ # Generic action to handle firing of state events on an object
46
+ def event
47
+ valid_events = model.state_machine.events.map(&:name)
48
+ valid_events_for_object = object.state_transitions.map(&:event)
49
+
50
+ if params[:e].blank?
51
+ errors = t('api.errors.missing_event')
52
+ elsif valid_events_for_object.include?(params[:e].to_sym)
53
+ object.send("#{params[:e]}!")
54
+ errors = nil
55
+ elsif valid_events.include?(params[:e].to_sym)
56
+ errors = t('api.errors.invalid_event_for_object', :events => valid_events_for_object.join(','))
57
+ else
58
+ errors = t('api.errors.invalid_event', :events => valid_events.join(','))
59
+ end
60
+
61
+ respond_to do |wants|
62
+ wants.json do
63
+ if errors.blank?
64
+ render :nothing => true
65
+ else
66
+ render :json => errors.to_json, :status => 422
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def search
75
+ return @search unless @search.nil?
76
+ @search = end_of_association_chain.searchlogic(params[:search])
77
+ @search.order ||= "descend_by_created_at"
78
+ @search
79
+ end
80
+
81
+ def collection_serialization_options
82
+ {}
83
+ end
84
+
85
+ def object_serialization_options
86
+ {}
87
+ end
88
+
89
+ def eager_load_associations
90
+ nil
91
+ end
92
+
93
+ def object_errors
94
+ {:errors => object.errors.full_messages}
95
+ end
96
+
97
+ end
@@ -0,0 +1,4 @@
1
+ class Api::CountriesController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show
4
+ end
@@ -0,0 +1,12 @@
1
+ class Api::InventoryUnitsController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show, :update, :create
4
+ belongs_to :shipment, :order
5
+
6
+ private
7
+
8
+ def eager_load_associations
9
+ [:variant]
10
+ end
11
+
12
+ end
@@ -0,0 +1,16 @@
1
+ class Api::LineItemsController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show, :update, :create
4
+ belongs_to :order
5
+
6
+ private
7
+
8
+ def collection_serialization_options
9
+ { :include => [:variant], :methods => [:description] }
10
+ end
11
+
12
+ def object_serialization_options
13
+ collection_serialization_options
14
+ end
15
+
16
+ end
@@ -0,0 +1,17 @@
1
+ class Api::OrdersController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show
4
+
5
+ private
6
+
7
+ def object_serialization_options
8
+ { :include => {
9
+ :bill_address => {:include => [:country, :state]},
10
+ :ship_address => {:include => [:country, :state]},
11
+ :shipments => {:include => [:shipping_method, :address]},
12
+ :line_items => {:include => [:variant]}
13
+ }
14
+ }
15
+ end
16
+
17
+ end
@@ -0,0 +1,14 @@
1
+ class Api::ProductsController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show, :create, :update
4
+ include Spree::Search
5
+
6
+ private
7
+ define_method :collection do
8
+ @collection = retrieve_products
9
+ end
10
+
11
+ def object_serialization_options
12
+ { :include => [:master, :variants, :taxons] }
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ class Api::ShipmentsController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show, :update, :create
4
+ belongs_to :order
5
+
6
+ private
7
+
8
+ def collection_serialization_options
9
+ { :include => {:shipping_method => {}, :address => {}, :inventory_units => {:include => :variant}},
10
+ :except => [:shipping_method_id, :address_id] }
11
+ end
12
+
13
+ def object_serialization_options
14
+ { :include => {
15
+ :shipping_method => {},
16
+ :address => {:include => [:country, :state]},
17
+ :inventory_units => {
18
+ :include => {
19
+ :variant => {
20
+ :include => {
21
+ :product => {:only => [:name]}
22
+ }
23
+ }
24
+ }
25
+ }
26
+ },
27
+ :except => [:shipping_method_id, :address_id]
28
+ }
29
+ end
30
+
31
+ def eager_load_associations
32
+ [:shipping_method, {:shipping_charge => :order}, :address, {:inventory_units => [:variant]}]
33
+ end
34
+
35
+ end
@@ -0,0 +1,5 @@
1
+ class Api::StatesController < Api::BaseController
2
+ resource_controller_for_api
3
+ actions :index, :show
4
+ belongs_to :country
5
+ end
@@ -0,0 +1,2 @@
1
+ module Api::ShipmentsHelper
2
+ end
@@ -0,0 +1,16 @@
1
+ <h2><%= t('api.access') %></h2>
2
+
3
+ <% if @user.api_key.present? %>
4
+ <p><strong><%= t('api.key') %></strong> <%= @user.api_key %></p>
5
+ <%= form_tag clear_api_key_admin_user_path(@user), :method => :put do %>
6
+ <%= button t("api.clear_key") %>
7
+ <% end %>
8
+ <%= form_tag generate_api_key_admin_user_path(@user), :method => :put do %>
9
+ <%= button t("api.regenerate_key") %>
10
+ <% end %>
11
+ <% else %>
12
+ <p><%= t('api.no_key') %></p>
13
+ <%= form_tag generate_api_key_admin_user_path(@user), :method => :put do %>
14
+ <%= button t("api.generate_key") %>
15
+ <% end %>
16
+ <% end %>
@@ -0,0 +1,16 @@
1
+ en:
2
+ api: "API"
3
+ api:
4
+ access: "API Access"
5
+ clear_key: "Clear API key"
6
+ errors:
7
+ invalid_event: "Invalid event name, valid names are %{events}"
8
+ invalid_event_for_object: "Valid event name but not allowed for this object, valid names are %{events}"
9
+ missing_event: "No event name supplied"
10
+ generate_key: "Generate API key"
11
+ key: "API Key"
12
+ regenerate_key: "Regenerate API key"
13
+ no_key: "No key defined"
14
+ key_generated: "API key generated"
15
+ key_cleared: "API key cleared"
16
+
@@ -0,0 +1,16 @@
1
+ ru-RU:
2
+ api: "API"
3
+ api:
4
+ access: "API доступ"
5
+ clear_key: "Удалить ключ API"
6
+ errors:
7
+ invalid_event: "Недопустимое действие, допустимые действия: %{events}"
8
+ invalid_event_for_object: "Допустимое действие, но не разрешённое для заданного объекта, разрешённые действия: %{events}"
9
+ missing_event: "Действие не указано"
10
+ generate_key: "Сгенирировать ключ API"
11
+ key: "Ключ API"
12
+ regenerate_key: "Перегенерировать ключ API"
13
+ no_key: "Ключ не определён"
14
+ key_generated: "Ключ API сгенерирован"
15
+ key_cleared: "Ключ API удалён"
16
+
data/config/routes.rb ADDED
@@ -0,0 +1,36 @@
1
+ Rails.application.routes.draw do
2
+ namespace :admin do
3
+ resources :users do
4
+ member do
5
+ put :generate_api_key
6
+ put :clear_api_key
7
+ end
8
+ end
9
+ end
10
+
11
+ namespace :api do
12
+ resources :shipments, :except => [:new,:edit] do
13
+ put :event, :on => :member
14
+ resources :inventory_units, :except => [:new,:edit] do
15
+ put :event, :on => :member
16
+ end
17
+ end
18
+ resources :orders, :except => [:new,:edit] do
19
+ put :event, :on => :member
20
+ resources :shipments, :except => [:new,:edit]
21
+ resources :line_items, :except => [:new,:edit]
22
+ resources :inventory_units, :except => [:new,:edit] do
23
+ put :event, :on => :member
24
+ end
25
+ end
26
+ resources :inventory_units, :except => [:new,:edit] do
27
+ put :event, :on => :member
28
+ end
29
+ resources :products, :except => [:new,:edit]
30
+ resources :countries, :except => [:new,:edit] do
31
+ resources :states, :except => [:new,:edit]
32
+ end
33
+ resources :states, :except => [:new,:edit]
34
+ end
35
+
36
+ end
@@ -0,0 +1,14 @@
1
+ module SpreeApi
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../../templates", __FILE__)
5
+
6
+ desc "Configures an existing Rails application to use spree_api"
7
+
8
+ def copy_migrations
9
+ directory "db"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ class AddApiKeyToUsers < ActiveRecord::Migration
2
+ def self.up
3
+ add_column "users", "api_key", :string, :limit => 40
4
+ end
5
+
6
+ def self.down
7
+ remove_column "users", "api_key"
8
+ end
9
+ end
data/lib/spree_api.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'spree_core'
2
+ require 'spree_api_hooks'
3
+
4
+ module SpreeApi
5
+ class Engine < Rails::Engine
6
+ def self.activate
7
+ lambda{
8
+
9
+ Admin::UsersController.class_eval do
10
+
11
+ def generate_api_key
12
+ if object.generate_api_key!
13
+ flash.notice = t('api.key_generated')
14
+ end
15
+ redirect_to edit_object_path
16
+ end
17
+
18
+ end
19
+
20
+ # RAILS3 TODO: Get the API stuff working with Devise
21
+ # Spree::BaseController.class_eval do
22
+ # private
23
+ # def current_user
24
+ # return @current_user if defined?(@current_user)
25
+ # if current_user_session && current_user_session.user
26
+ # return @current_user = current_user_session.user
27
+ # end
28
+ # if token = request.headers['X-SpreeAPIKey']
29
+ # @current_user = User.find_by_api_key(token)
30
+ # end
31
+ # end
32
+ # end
33
+
34
+ LineItem.class_eval do
35
+ def description
36
+ d = variant.product.name.clone
37
+ d << " (#{variant.options_text})" unless variant.option_values.empty?
38
+ d
39
+ end
40
+ end
41
+ }
42
+ end
43
+ config.autoload_paths += %W(#{config.root}/lib)
44
+ config.to_prepare &self.activate
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ class ApiHooks < Spree::ThemeSupport::HookListener
2
+ insert_after :admin_user_edit_form, :partial => "admin/users/api_fields"
3
+ end
@@ -0,0 +1,8 @@
1
+ namespace :spree do
2
+ desc "Synchronize public assets, migrations, seed and sample data from the Spree gems"
3
+ task :sync do
4
+ migration_dir = File.join(File.dirname(__FILE__), '..', '..', 'db', 'migrate')
5
+ puts "Mirror: #{migration_dir}"
6
+ Spree::FileUtilz.mirror_with_backup(migration_dir, File.join(Rails.root, 'db', 'migrate'))
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_api
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 0
7
+ - 30
8
+ - 0
9
+ - beta1
10
+ version: 0.30.0.beta1
11
+ platform: ruby
12
+ authors:
13
+ - David North
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-03 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: spree_core
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 30
31
+ - 0
32
+ - beta1
33
+ version: 0.30.0.beta1
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: Required dependancy for Spree
37
+ email: david@railsdog.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - LICENSE
46
+ - README.md
47
+ - app/controllers/api/base_controller.rb
48
+ - app/controllers/api/countries_controller.rb
49
+ - app/controllers/api/inventory_units_controller.rb
50
+ - app/controllers/api/line_items_controller.rb
51
+ - app/controllers/api/orders_controller.rb
52
+ - app/controllers/api/products_controller.rb
53
+ - app/controllers/api/shipments_controller.rb
54
+ - app/controllers/api/states_controller.rb
55
+ - app/helpers/api/shipments_helper.rb
56
+ - app/views/admin/users/_api_fields.html.erb
57
+ - config/locales/en.yml
58
+ - config/locales/ru-RU.yml
59
+ - config/routes.rb
60
+ - lib/generators/spree_api/install_generator.rb
61
+ - lib/generators/templates/db/migrate/20100107141738_add_api_key_to_users.rb
62
+ - lib/spree_api.rb
63
+ - lib/spree_api_hooks.rb
64
+ - lib/tasks/api.rake
65
+ has_rdoc: true
66
+ homepage: http://spreecommerce.com
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 1
80
+ - 8
81
+ - 7
82
+ version: 1.8.7
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">"
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 1
89
+ - 3
90
+ - 1
91
+ version: 1.3.1
92
+ requirements:
93
+ - none
94
+ rubyforge_project: spree_api
95
+ rubygems_version: 1.3.6
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: Provides RESTful access for Spree.
99
+ test_files: []
100
+