我对如何正确配置CanCanCan感到有些困惑。
对于初学者,我是否必须将load_and_authorize_resource
添加到我想限制访问的每个控制器资源?
这就是我想做的事情:
这就是我ability.rb
的样子:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
#Admin
if user.has_role? :admin
can :manage, :all
can :manage, :newsroom
# Editor
elsif user.has_role? :editor
can :read, :all
can :manage, :newsroom
can :manage, Post
#Member
elsif user.has_role? :member
can :read, :all
can :create, Post
can :status, Post
can :update, Post do |post|
post.try(:user) == user
end
#Guest
else
can :read, :all
can :create, Post
can :status, Post
end
end
end
在我的routes.rb
我有这个:
authenticate :user, lambda { |u| u.has_role? :admin or :editor } do
get 'newsroom', to: 'newsroom#index', as: "newsroom"
get 'newsroom/published', to: 'newsroom#published'
get 'newsroom/unpublished', to: 'newsroom#unpublished'
end
发生的事情是,当我使用尚未分配任何角色的用户登录时(即我想成为"访客"),他们可以访问新闻室。
当我尝试编辑角色为:member
的帖子时,它会给我一个"无权编辑帖子"错误(这是正确的)。
我无法完全锁定Newsroom
而且我不确定原因。
答案 0 :(得分:9)
您不需要在每个控制器中使用load_and_authorize_resource
。这是一个方便的宏,做两件事。首先,它为实例变量分配为当前控制器和操作假定的记录。然后它授权该资源。对于某些控制器操作,第一步可能是错误的,因此您希望加载资源,然后手动对其进行授权。 Railscasts episode about CanCan中的一个示例是这样的:
def edit
@article = Article.find(params[:id])
unauthorized! if cannot? :edit, @article
end
您也可以像CanCan Wiki for authorizing controllers:
中的示例一样执行此操作def show
@project = Project.find(params[:project])
authorize! :show, @project
end
或者您可以使用authorize_resource
并自行加载。最后,您必须确保CanCan以某种方式用于授权(控制器宏或每个操作)。关于你的能力,我想你想要这样的事情:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
#Admin
if user.has_role? :admin
can :manage, :all
# Editor
elsif user.has_role? :editor
can :read, :all
can :manage, :newsroom
can :manage, Post
#Member
elsif user.has_role? :member
can :read, :all
can :create, Post
can :status, Post
can :update, Post do |post|
post.try(:user) == user
end
#Guest
else
can :read, :all
cannot [:index, :published, :unpublished], :newsroom
end
end
end
这里有一个例子,比如你可以如何授权你的新闻编辑室:
class ToolsController < ApplicationController
authorize_resource :class => false
def show
# automatically calls authorize!(:show, :tool)
end
end
关于CanCan的最后一个个人注意事项是,我不建议将它用于新项目,因为它不再被积极维护,并且在定义能力时我发现它有点违反直觉。也就是说,CanCan是我合作过的最有据可查的宝石之一,尤其是the wiki有大量的例子和解释。
答案 1 :(得分:2)
对于它的价值,我必须像我这样设置NewsroomController
:
class NewsroomController < ApplicationController
authorize_resource :class => false
这是ability.rb
的工作版本在我使用我需要的权限后的样子:
#Roles
#Admin
if user.has_role? :admin
can :manage, :all
# Editor
elsif user.has_role? :editor
can :manage, :newsroom
can :manage, Post
#Member
elsif user.has_role? :member
can [:read, :create, :status], Post
can :update, Post do |post|
post.try(:user) == user
end
#Guest
else
can [:read, :status], Post
end
答案 2 :(得分:2)
can :read, :all
表示用户有权阅读您应用的所有资源。它应该是
can :read, Post
还要添加
cannot :manage, :newsroom
您不希望访问新闻编辑室。指定权限的顺序很重要。 正如其他人已经提到的那样,&#39; load_and_authorize_resource&#39;是可选的。仅授权资源&#39;需要授权控制器的所有操作。如果你跳过这些,那么你可以授权&#39;个人控制者行动。
除非绝对必要,否则请避免使用阻挡。例如,如果Post中有user_id,那么你可以做
can :update, Post, user_id: user.id
最后,&#39; class =&gt;假&#39;用于没有支持控制器的型号的地方。 即你没有一个名为&#39;新闻室&#39;但你有一个名为&#39; NewsroomsController&#39;。
的控制器答案 3 :(得分:1)
对于初学者,我是否必须将load_and_authorize_resource添加到我想限制访问的每个控制器资源?
是
然而,正在发生的事情是,当我与拥有的用户一起登录时 没有被分配任何角色(即我想成为&#34;嘉宾&#34;),他们 可以访问新闻室。
来自上面的访客角色:
...
#Guest
else
can :read, :all
can :create, Post
can :status, Post
end
这为访客提供了对所有内容的读取权限以及创建帖子的能力。 如果您希望您的客人只能阅读帖子,那么应该是:
...
#Guest
else
can :read, Post
# can :status, Post # maybe you want this aswell
end