如何为 Solidus / Spree 添加具有自定义权限集的新角色?

Howto add a new role with a custom permission set for Solidus / Spree?

我想添加一个新的 'vendor' 角色。 供应商可以管理自己的产品和订单,但看不到属于其他供应商的任何订单或产品。

我正计划在 Stock Location 周围实施这个。 例如:一位具有供应商角色的用户属于东京库存位置。具有供应商角色的其他用户属于其他库存位置。

我需要采取哪些步骤才能使其正常工作?

1。创建供应商角色

$ rails console
Spree::Role.create(name: 'vendor')

2。定义 CanCan 权限:

app/models/spree/multi_vendor_ability.rb

module Spree
  class MultiVendorAbility
    include CanCan::Ability

    def initialize(user)
      user ||= Spree::User.new # guest user (not logged in)
      if user.admin?
        can :manage, :all
        puts "IS admin"
      else
        can :read, :all
        puts "NOT admin"
      end

      if user.stock_locations.present?
        can  :manage, Spree::StockItem, :stock_location_id => user.stock_locations.first.id
      end
    end

  end
end

3。添加新方法到 Spree::User

config/initializers/spree_user.rb

Spree::User.class_eval do

    def vendor?
      self.role_users.any? { |ru| ru.role.name == 'vendor' }
    end

end

4。 RSpec

spec/models/multi_vendor_spec.rb

require 'spec_helper'

describe Spree::MultiVendorAbility do
  let(:ability) { Spree::MultiVendorAbility.new(user) }
  let(:user)    { create(:user) }
  let(:product) { create :product }
  let(:stock_location) { create(:stock_location_with_items) }
  let(:stock_item) { stock_location.stock_items.order(:id).first }

  subject { ability }

  context "test" do
    before do
      Rails.logger.debug "The StockItem is #{stock_item.inspect}"
      user.stock_locations = [stock_location]
      user.save
    end

    context "when the user is associated with the stock location" do
       it { is_expected.to be_able_to(:manage,  Spree::StockItem) }
    end

    context "when the user is NOT associated with the stock location" do
        before do
          stock_item.stock_location_id = nil
          stock_item.save
          user.stock_locations = []
          user.save
          puts "The StockItem is #{stock_item.inspect}"
          user.stock_locations = []
        end
        it { is_expected.to_not be_able_to(:manage, Spree::StockItem) }
    end

  end

end

我相信在 Solidus 中您会创建一个权限集,并且在您的 Spree/Solidus 初始化程序中您会为该新角色分配权限集。您可以避免所有 if/then/elses 并通过这种方式轻松存储具有重叠权限集的多个角色。