For authorization management, Solidus uses CanCanCan (a fork of the popular, now unmaintained CanCan library), a Ruby/Rails authorization library that allows you to define granular permissions on collection and individual resources. This is combined with an in-house user role system that allows you to assign certain permissions to certain groups of users.
At a high level, here are the main concepts in the authorization system:
The process Solidus follows to determine the current user's permissions is pretty simple:
If the user is authenticated, it retrieves the current user's roles. If the user isn't authenticated, it assumes the user only has the
It collects all the permission sets for the user's roles.
It applies all the permission sets to the current ability.
This simple but flexible system allows you to create custom permissions and roles, both in extensions and in your main application, as well as do things such as store permission sets in the database rather than in Ruby code, allowing the administrator to change them via the UI.
Let's see how we can leverage some of that flexibility.
Let's start with something simple: we'll define a new
customer_service role that has limited access to the Solidus backend. Customer service representatives will only be able to display users, products and stock locations.
The first step is to create the
Spree::Role record that we'll use to store our role. In order to do that, you can simply add the following to your seeds:
# ...Spree::Role.where(name: 'customer_service').first_or_create!
Then, run the seeds:
$ rails db:seeds
Now that you have defined your role, you just need to associate it with the desired permission sets in your Solidus configuration. You can do this in the Solidus initializer:
config/initializers/spree.rbSpree.config do |config|# ...config.roles.assign_permissions :customer_service, [Spree::PermissionSets::OrderDisplay,Spree::PermissionSets::UserDisplay,Spree::PermissionSets::ProductDisplay,]end
Now, if you assign the
customer_service role to a user and sign into the backend with their credentials, you'll see that you only have limited access to user profiles, orders and products.
Let's take it one step further and assume that we also want customer service representatives to be able to update user profiles, perhaps in case a customer forgets their password and wants a reset.
Since there isn't a permission set that does what we need, we'll need to create our own:
app/models/awesome_store/permission_sets/user_update.rbmodule AwesomeStoremodule PermissionSetsclass UserUpdate < PermissionSets::Basedef activate!can :update, Spree::Userendendendend
Now that we have our permission set, the last step is to associate it to the
customer_service role by updating the role definition we created:
config/initializers/spree.rbSpree.config do |config|# ...config.roles.assign_permissions :customer_service, [Spree::PermissionSets::OrderDisplay,Spree::PermissionSets::UserDisplay,Spree::PermissionSets::ProductDisplay,AwesomeStore::PermissionSets::UserUpdate,]end
That's it! Now, customer service representatives can also update user profiles.