具有cancan的资源的多种能力

时间:2012-03-27 18:57:03

标签: ruby-on-rails ruby-on-rails-3 cancan

我正在尝试使用cancan实施一些授权,用户可以在其中管理自己的用户帐户,其员工的用户帐户及其成员的用户帐户。像这样:

# own account
can :manage, User, :ID => user.ID

# staff
can :manage, User, :provider_staff => {:ProviderID => user.ID}

#members
can :manage, User, :consumer => { :ProviderID => user.ID }

不幸的是,我发现在授权控制器操作时这不起作用,因为cancan在provider_staff和consumer上执行INNER JOIN,这有效地阻止了任何查询结果的返回:

SELECT TOP (10) [__rnt].ID FROM ( SELECT ROW_NUMBER() OVER (ORDER BY [User].UserDisplayAs ASC) AS [__rn], [User].ID FROM [User] INNER JOIN [Consumer] ON [Consumer].[ID] = [User].[ID] INNER JOIN [ProviderStaff] ON [ProviderStaff].[ID] = [User].[ID] LEFT OUTER JOIN [UserView] ON [UserView].[ID] = [User].[ID] LEFT OUTER JOIN [Address] ON [Address].[UserID] = [User].[ID] LEFT OUTER JOIN [Phone] ON [Phone].[ID] = [User].[PhoneID] WHERE [User].[DeletedFlag] = 0 AND (([Consumer].[ProviderID] = 32) OR (([ProviderStaff].[ProviderID] = 32) OR ([User].[ID] = 32))) AND (UserView.IsConsumer = 1) GROUP BY [User].ID, [User].UserDisplayAs ) AS [__rnt] WHERE [__rnt].[__rn] > (0) ORDER BY [__rnt].[__rn] ASC

很抱歉这是一个丑陋的MSSQL查询,对于一个奇怪的数据库模式有一些恐惧,如果它试图在内部加入消费者和员工表,你什么也得不到。

使用块我可以处理个人负载,例如用户#show。但是我不太确定如何将这个sql查询更改为允许我需要的东西,除了完全跳过load_resource并在用户#index code中实现我自己的查询。

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

CanCan对您处理权限的方式没有任何限制:

can manage, :User do |user|
  staff_ids.include?(current_user.id)  
end

当然,检查用户是否是员工的一部分可以以更好的方式完成。理想情况如下:

if current_user.has_role? :staff
  can manage, :User
end

如果您需要,部分员工只能更改受监管用户:

if current_user.has_role? :staff
  can manage, :User do |user|
    current_user.id == user.supervisor_id
  end
end

其中'current_user'只是 initialize(current_user)

答案 1 :(得分:0)

所以这是我对自己问题的回答......我能找到的唯一解决方案是有效的,但我无法想象这是一种有效的方法......

      can :manage, User, ["( [User].[ID] IN (SELECT [ID] FROM [ProviderStaff] WHERE ProviderID = ?) OR [User].[ID] IN (SELECT [ID] FROM [Consumer] WHERE ProviderID = ?) )", user.ID, user.ID] do |u|
        if !u.consumer.nil?
          u.consumer.ProviderID == user.ID
        elsif !u.provider_staff.nil?
          u.provider_staff.ProviderID == user.ID
        end
      end