• Home

  • Custom Ecommerce
  • Application Development
  • Database Consulting
  • Cloud Hosting
  • Systems Integration
  • Legacy Business Systems
  • Security & Compliance
  • GIS

  • Expertise

  • About Us
  • Our Team
  • Clients
  • Blog
  • Careers

  • VisionPort

  • Contact
  • Our Blog

    Ongoing observations by End Point Dev people

    Spree Authorization Failure for Customized Role

    Matt Galvin

    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
           end
           if user.respond_to?(:has_spree_role?) && user.has_spree_role?('training')
             can [:admin, :manage], Spree::Training
           end
         end
       end
     
       Spree::Ability.register_ability(AbilityDecorator)
    

    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')
            admin_trainings_path
          else
            super
          end
      end
    

    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


    Comments