2011-08-20 28 views
1

在我的rails应用程序(我使用devise和cancan)中,每个(注册)用户都属于,完全是一个角色('管理员'或'用户'),而是至少一组(类似'家庭','朋友','同事')。在运行时,当创建一个新文件夹(见下文)时,可以设置与一个或多个组的habtm关系,该关系定义谁可以访问该文件夹。如果选择组应该会导致在全球范围内访问文件夹(即用户不必登录即可访问这些文件夹)。但现在,我还不知道如何在我的ability.rb中定义这样的全球可访问的文件夹,因为我不知道如何定义“可以读取没有与其关联的组的文件夹”。在角色和组模型更复杂的环境中定义能力

app/models/ability.rb的相关片段看起来是这样的:

user ||= User.new 
if user.role? :Administrator 
    can :manage, :all 
elsif user.role? :Users 
    # user should only be able to read folders, whose associated groups they are member of 
    can :read, Folder, :groups => { :id => user.group_ids } 
else 
    # here goes the world-wide-accessible-folders part, I guess 
    # but I don't know how to define it: 
    ## can :read, Folder, :groups => { 0 } ??? 
end 

app/controllers/folders_controller.rb的相关片段看起来是这样的:

class FoldersController < ApplicationController 
    before_filter :authenticate_user! 
    load_and_authorize_resource 

有人可以给我一个提示?

回答

4

我前几天有同样的问题。在阅读CanCan自述文件后,我想出了解决方案,如果您尚未完成,应该这样做。

你可以在这里查看我的解决方案:Context aware authorization using CanCan

给你更多具体到您的使用情况的解答,做如下:

在你的应用程序控制器,你需要定义一些逻辑,这将挑选自己能力。

class ApplicationController < ActionController::Base 
    check_authorization 

    def current_ability 
    if <no group selected logic> # Maybe: params[:controller] == 'groups' 
     @current_ability = NoGroupSelectedAbility.new(current_user) 
    else 
     @current_ability = GroupSelectedAbility.new(current_user) 
    end 
    end 

    # Application Controller Logic Below 
end 

然后,您需要在应用/模型/文件夹中创建新的能力(或能力)。你也可以这样做很酷的东西:

if request.path_parameters[:controller] == groups 
    @current_ability = GroupsAbility.new(current_group_relation) 
end 

其中current_group_relation是在app/controllers/groups_controller.rb中定义的。这将为您提供特定控制器的特定功能。请记住,父类可以在Ruby中的子类中调用方法。您可以在控制器中定义一个方法,并从ApplicationController中调用它,只要您确定当前正在使用哪个控制器来处理请求。

希望有所帮助。

编辑:我想告诉你什么是自定义功能。

# File path: app/models/group_ability.rb 
class GroupsAbility 
    include CanCan::Ability 

    # This can take in whatever you want, you decide what to argument to 
    # use in your Application Controller 
    def initialize(group_relation) 
    group_relation ||= GroupRelation.new 

    if group_relation.id.nil? 
     # User does not have a relation to a group 
     can :read, all 
    elsif group_relation.moderator? 
     # Allow a mod to manage all group relations associated with the mod's group. 
     can :manage, :all, :id => group_relation.group.id 
    end 
    end 
end 
+0

哇,怪异! :) 谢谢。猜猜它需要一段时间才能完成。 – dennis