spree_api 0.30.0.beta1

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.
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
+