Blog

Archive for January, 2010

January 26 2010

Potential XSS Security Issue in LocaleControllerby railsdog

We've just patched the edge code to address a potential security hole. The vulnerability also affects prior versions of Spree including the latest 0.9.4 release. The upcoming 1.0.0 release will contain the fix. We will not be issuing a patch release but you can easily address the problem by patching the LocaleController in your site extension as follows:


class LocaleController < ApplicationController
  def set
    if params[:locale] && AVAILABLE_LOCALES.include?(params[:locale])
      I18n.locale = params[:locale]
      session[:locale] = params[:locale]
      flash[:notice] = t("locale_changed")
    else
      flash[:error] = t("locale_not_changed")
    end
    redirect_back_or_default(root_path)
  end
end

Special thanks to Alexander Kozliakov for reporting the bug and providing a fix. Please continue to report any suspected security issues to security@railsdog.com.

January 26 2010

New on Edge: RESTful APIby railsdog

The REST API is designed to give developers a convenient way to access data contained within Spree. With a standard read/write interface to store data, it is now very simple to write third party applications (ex. iPhone) that can talk to Spree. It is also possible to build sophisticated middleware applications that can serve as a bridge between Spree and a warehouse or inventory system.

The API currently only supports a limited number of resources. The current list reflects the needs of paying clients who funded the development of the API. The list will be expanded soon to cover additional resources. Adding more resources is simply a matter of making the time for testing and investigating possible security implications.

Spree currently supports RESTful access to the following resources:

  • Order
  • LineItem
  • Shipment
  • InventoryUnit

Making an API Call

You will need an API key to authenticate. These keys can be generated on the user edit screen within the admin interface. Your requests should include this key in the X-SpreeAPIKey header.


curl -H "Content-Type:application/json" 
-H "Accept:application/json" 
-H "X-SpreeAPIKey: YOUR_KEY" http://example.com/api/orders  

The token allows the request to assume the same level of permissions as the actual user to whom the token belongs. The admin role is fairly "powerful" by default. Consider creating a new role and assign a more limited set of permissions. This way you can create a user and corresponding token that has more narrow permissions (ex. read only access to orders.)

HTTP Methods

Your requests must use the correct HTTP method.

  • GET for listing and viewing individual resources
  • POST for creating resources
  • PUT for updating existing resources
  • DELETE for deleting resources

Currently the API supports only the JSON. Supporting the XML format should not be difficult since Rails supports it out of the box. Volunteers who are willing to provide a patch (and tests) for XML support are encouraged to do so.

Searching

All list actions support filtering using Search Logic parameters. For example, to view all shipments that are ready to ship and that were created since the date 2010-01-01:


/api/shipments?search[state]=ready_to_ship&search;[created_at_greater_than]=2010-01-01

NOTE: Use --globoff when passing SL params through Curl to avoid syntax issues. You can also use -i to view the return header information.

Please see the REST documentation for a more detailed explanation of the API.

January 13 2010

New on Edge: Refactored Checkout (Again)by railsdog

For those of you following the "edge" version of Spree, you probably noticed a massive new commit that introduced a much anticipated refactoring of the checkout process. These changes are significant and will likely require some modifications to your custom site extension in order to upgrade to the latest version of Spree. The refactoring was the result of additional real world experience building Spree sites as well as extensive developer feedback.

Checkout Gets a State Machine

One of the first major changes was the inclusion of a new state machine for the Checkout model.


state_machine :initial => 'address' do
  after_transition :to => 'complete', :do => :complete_order
  before_transition :to => 'complete', :do => :process_payment
  event :next do
    transition :to => 'delivery', :from  => 'address'
    transition :to => 'payment', :from => 'delivery'
    transition :to => 'complete', :from => 'payment'
  end
end

The state machine offers a standard approach for customizing the checkout steps and their sequence.

picture-14

Each step is rendered with a partial of the same name and the steps themselves are automatically transformed into a "progress train" that can be used for navigation. The look and feel of the progress train can be customized (or omitted) by your site theme and the logic for constructing it can be tweaked in your site extension.

Simplified Custom Controller Logic

The CheckoutsController now provides its own “hook mechanism” (not to be confused with theme hooks) which allow for the developer to perform additional logic (or to change the default) logic that is applied during the edit and/or update operation for a particular step. The Spree::Checkout::Hooks module provides this additional functionality and makes use of methods provided by the resource_controller gem.

The CheckoutsController will automatically call an edit_hook (if one is defined) before moving on to the standard edit functionality for a particular step. There is also a corresponding update_hook that can be used to execute additional functionality during an update. Both hooks can accept either a symbol (which is the name of a method) or a block.

The CheckoutsController itself makes limited use of these hooks – its expected that developers will add their own through a site extension. Here’s an example of an edit_hook defined in checkouts_controller.rb:

 
delivery.edit_hook :load_available_methods

This tells the controller to call load_available_methods before presenting the standard edit form for the delivery step. The hook will be called only during the delivery step – it is ignored for all other steps. In this specific case, Spree uses the hook to load all available shipping methods.

Perhaps more interestingly, hooks can also be appended to. In other words, if you wanted to perform some additional logic before presenting the delivery form, you could add something like the following in your site extension.

 
delivery.edit_hook << :perform_additional_logic

Please see the documentation for more details on hooks and the rest of the checkout architecture.

Back to Multi Step

The other major change is that Spree is moving back to a multi step checkout as the default. Previous versions of Spree have experimented with a single page checkout similar to the one offered by Magento. After building several sites with the single step we decided to abandon it for several reasons.

  1. Single page approach requires javascript in order to checkout. Our new checkout makes minimal use of javascript (ex. populating the list of states based on countries) but it degrades nicely and is not required to move between checkout states.

  2. Old approach was very difficult to customize. The old checkout.js file was 500+ lines of code and growing. We're not interested in debugging javascript everytime we make a change to the checkout process.

  3. Some of the previous issues with multi step no longer apply. Thanks to the Rails inclusion of nested attributes and some interesting third party work done on partial model validation, we're no longer facing many of the issues that initially motivated us to try the single page checkout.

Moving Forward

We're hoping to eventually support an simplified single page checkout based on the new state machine approach. The idea would be to use AJAX to render the individual steps and to simulate the effects of the multi page process. We're interested in offering our users the flexibility to use either the multi step or single step approach. Contributions are always welcome.

Even though this is a non trivial change to how checkout is handled we definitely feel its worth the potential disruption to allow future development (and upgrades) to be less painful. Enjoy!