2012-11-14 24 views
1

我试图更好地理解CanCan在授权方面的功能。想象一下这样的控制器操作:可在CanCan中执行多个操作授权

def update 
    if can? :action, Model or can? :resolve, Model or can? :authorize, AnotherModel 
    # My Code here 
    respond_with @model 
    else 
    raise CanCan::AccessDenied.new(nil, :update, Model) 
    end 
end 

我得到了这一点,同时试图找到上述使用authorize!到一个解决方案。至于我可以看到(也看签名)authorize!只接受一个许可(动作)和一个主题,一个可选的消息,像这样:

def authorize!(action, subject, *args) 
    # code 
end 

有没有我可以俯瞰的方式指示授权检查多个操作?把两个授权一个接一个地作为AND条件之间的权限,我想它是像OR条件工作,基本上类似于上面的自定义代码(这有问题在CanCan中提高AuthorizationNotPerformed,可以避免与这不是我真正想做的事情)。

回答

1

最后,我添加了这个相当不错的解决方案的能力类:

def multi_authorize!(*actions, message_hash) 
    message = nil 
    if message_hash.kind_of?(Hash) && message_hash.has_key?(:message) 
     message = message_hash[:message] 
    end 
    auth = false 
    actions.each do |act| 
     auth = auth || can?(act[0], act[1]) 
    end 
    if !auth 
     message ||= unauthorized_message(actions[0][0], actions[0][1]) 
     raise CanCan::AccessDenied.new(message, actions[0][0], actions[0][1]) 
    end 
end 

包括为控制器的帮手:

module CanCanAddition 
    def multi_authorize!(*args) 
    @_authorized = true 
    current_ability.multi_authorize!(*args) 
    end 
end 

if defined? ActionController::Base 
    ActionController::Base.class_eval do 
    include ApplicationHelper::CanCanAddition 
    end 
end 

我称之为是这样的:

def create 
    multi_authorize! [:create, Model1], [:authorize, Model2], :message => "You are not authorized to perform this action!" 
    # other code... 
    end 

警告:由于能力等级中的代码,您必须提供一条消息,否则最后一对授权将不会在*args中传递。我需要一些时间来克服这个问题,但是我认为这个解决方案适合我。

+0

好的,但是你可以用循环和能力文件中的一些条件(使用自定义动作)构建相同的东西。而且你可以重复使用这些自定义操作,从而产生更简洁的代码库。那么无论你为什么工作;) – spas

2

您可以创建一个custom action并根据需要创建尽可能多的or条件。

can :my_update_action, Project do |project| 
    can?(:read, ModelX) || can?(:read, ModelY) || ... 
end 
+0

+1。很好的解决方案,但我觉得需要更通用的东西,而不是创建很多自定义的“可以”操作。我已经添加了自己的解决方案。 – Tallmaris