Spree Commerce is an open-source Ruby on Rails e-commerce platform with a role-based permission system built on the cancancan authorization library.
Built-in Roles
| Role | Orders | Products | Promotions | Users | Configuration | Reports |
|---|---|---|---|---|---|---|
| admin | Full | Full | Full | Full | Full | Full |
| user | Own only | View | View | Own only | No | No |
The admin role has unrestricted access. The user role is for storefront customers.
Custom Admin Roles
Spree supports custom roles via the spree_auth_devise gem and ability definitions:
# app/models/spree/ability_decorator.rb
module Spree
class AbilityDecorator
include CanCan::Ability
def initialize(user)
if user.has_spree_role?('analytics_manager')
can :admin, :dashboards
can :manage, Spree::Preference, key: /^google_analytics/
can :read, Spree::Order
can :read, Spree::Product
cannot :manage, Spree::User
cannot :manage, Spree::Role
end
if user.has_spree_role?('order_manager')
can :admin, :dashboards
can :manage, Spree::Order
can :manage, Spree::Shipment
can :read, Spree::Product
end
end
end
end
Spree::Ability.register_ability(Spree::AbilityDecorator)
Creating Roles
# Rails console: Create a custom role
Spree::Role.create!(name: 'analytics_manager')
Spree::Role.create!(name: 'order_manager')
# Assign role to user
user = Spree::User.find_by(email: 'analyst@company.com')
user.spree_roles << Spree::Role.find_by(name: 'analytics_manager')
API Authentication
Spree uses OAuth 2.0 tokens for API access:
# Create an OAuth token
curl -X POST "https://store.example.com/spree_oauth/token" \
-d "grant_type=password&username=admin@example.com&password=password"
# Use the token for API requests
curl "https://store.example.com/api/v2/platform/orders" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Analytics Integration
Add tracking via the Spree layout template:
<%# app/views/spree/layouts/spree_application.html.erb %>
<head>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
</head>
Best Practices
- Define custom abilities using CanCanCan rather than giving admin role broadly
- Create purpose-specific roles (order_manager, analytics_manager, content_editor)
- Use OAuth tokens with appropriate scoping for API integrations
- Store API credentials in environment variables, never in code
- Audit role assignments via
Spree::User.joins(:spree_roles).where(spree_roles: { name: 'admin' })