开发者

cancan: Storing in the database vs accessible_by?

We have a UI that lets admins change permissions on our users. So we store these permissions in the database.

Our ability class is:

class Ability
include CanCan::Ability

def initialize(user)
user ||= User.new # guest user

if user.role? 开发者_开发知识库:super_admin
  can :manage, :all
else
  if user.role? :live_trader
    can :admin, LiveEvent
  end
  if user.role? :horse_trader
    can :horse_admin, Event
  end
  if user.role? :channel_admin
    can :manage, Channel
  end
  if user.role? :device_admin
    can :manage, Device
  end
  if user.role? :ost
    can :read, Customer.first
  end

  can do |action, subject_class, subject|
    user.roles.find_all_by_action(aliases_for_action(action)).any? do |role|
      role.authorizable_type == subject_class.to_s &&
        (subject.nil? || role.authorizable_id.nil? || role.authorizable_id == subject.id)
    end
  end

  # can always manage ourselves
  can :manage, user

end
 end
end

It works fine, except that we can't use accessible_by. We get:

The accessible_by call cannot be used with a block 'can' definition.

I don't see any other way of limiting result sets... Is this a bug or are we doing it wrong?


The error message says it all, really.

There's two ways use cancan using database permissions. One uses the 'can' block, the other uses explicit 'can' permissions. They achieve the same thing.

You can look at https://github.com/ryanb/cancan/wiki/Abilities-in-Database to see the two examples.

I'd say that you'd want to rewrite your 'can' block to:

user.roles.each do |role|
  if permission.subject_id.nil?
    can permission.action.to_sym, role.authorizable_type.constantize
  else
    can permission.action.to_sym, role.authorizable_type.constantize, :id => role.authorizable_id
  end
end

HTH.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜