Our Blog

Ongoing observations by End Point people

Spree Authorization Failure for Customized Role

By Matt Galvin
September 22, 2014

Hello again all. Recently I was working on another Spree site running Spree 2.1.1. The client wanted to create some custom roles. For example, the client wanted there to be a Sales Manager role. A Sales Manager could log in and have read and write access to all the orders. However, a sales manager should not have read/write access to products, configuration, promotions, users, etc. This was easily accomplished by following the steps in the Spree documentation. As I will describe, this documentation assumes that the custom role will have access to Orders#index.

The client wanted to create a second custom role that had create, read, update and delete access to the Training model and nothing more. The training model belongs to a taxon and has a unique event date and taxon id. An example would be a training instance with an event date of September 9th, 2014 that belongs to a taxon with the name “Fire Safety 101” and a description “Teaching fire safety in accordance with OSHA standards. 10 hours and lunch is provided”. So, I planned to create a training personnel role that should be able to log in and only have read/write access to Trainings. However, the Spree documentation did not provide an explanation on how to create a custom role that does not have read or write access to orders.


Following the pattern described in the Spree documentation for creating custom roles and their respective authorization, I created an ability_decorator.rb with the contents:

class AbilityDecorator
     include CanCan::Ability
     def initialize(user)
       if user.respond_to?(:has_spree_role?) && user.has_spree_role?('sales_manager')
         can [:admin, :index, :show], Spree::Order
       if user.respond_to?(:has_spree_role?) && user.has_spree_role?('training')
         can [:admin, :manage], Spree::Training

However, after creating a training user and attempting to log in, I got an unauthorized error. So, I checked the logs:

The log output above shows that while I was logged in as a user with the training role, the application was checking for authorization on Spree::Admin::OrdersController#index (the orders list page), because the base admin URL ("/admin") points to this controller action. I reviewed the Devise documentation to modify where a user with the training role is redirected to upon login (via Spree Auth Devise’s after_sign_in method), as shown in the code shown below.

def after_sign_in_path_for(resource)
    stored_location_for(resource) ||
      if resource.is_a?(Spree::User) && resource.has_spree_role?('training')

After making this change, I tried once again and was able to successfully log in as a training user and only have the desired access to Trainings.


To summarize, if you’d like to have a custom role and not give them access to Orders, you will need to make some adjustments outside the steps listed in Spree’s documentation for custom role authorization.

ruby rails spree


Popular Tags


Search our blog