CanCan:基于用户角色限制其设置某些模型属性的能力

20

我有一个Post模型,其中有一个:published属性(布尔类型),以及一个User模型,其中有一个role属性(字符串)。有三种角色:ROLES = %w [admin publisher author]

我不希望角色为author的用户能够在Post模型上设置或编辑:published字段。

我正在使用CanCan(和RailsAdmin宝石),我的简化Ability.rb文件如下:

class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new

    if user.role? :admin
      can :manage, :all
    elsif user.role? :publisher
      can :manage, Post
    elsif user.role? :author
      # I want to prevent these guys from setting the :published attribute
    end

  end
end

有人对这种事情有什么建议吗?

4个回答

13

好的,谢谢你的回复,我会关注 CanCan v2.0 的进展。谢谢。 - stephenmurdoch
我知道这不是完美的,但我认为你仍然可以使用cannot <<your attribute>>, :klass bee,因为它们在等待2.0时仍然是Ruby中的方法。 - Francesco Belladonna

3

请看这篇文章:如何在Rails Admin中使用CanCan检查所有权

它展示了如何根据用户角色使字段不可见。

更新: 通过以下代码,我成功地在Rails Admin中设置了选项:

config.model User do
  edit do
    configure :organization do
      visible do
        bindings[:view]._current_user.max_role_name != 'admin' ? false : true
      end
    end

    configure :organization_id, :hidden do
      visible do
        true if bindings[:view]._current_user.max_role_name != 'admin'
      end
      default_value do
        bindings[:view]._current_user.organization_id if bindings[:view]._current_user.max_role_name != 'admin'
      end
    end

    include_all_fields
  end
end

如果登录用户不是管理员,此配置将隐藏组织字段。然后会显示一个organization_id字段(类型为“hidden”),并设置默认值。
希望这能帮到某些人。

3

在CanCan 2.0发布之前,我通过创建一个受限制的模型子类来解决了这个问题,类似于:

class AuthorPost < Post
  attr_protected :published
end

然后给作者访问AuthorPosts的权限: can :manage => AuthorPost

接下来在你的控制器中,你可以在before_filter中设置你想要的资源:

before_filter :set_resource
...
  private
    def set_resource
      if current_user and current_user.author?
        @resource = AuthorPost
      else
        @resource = Post
      end
      params[:post] ||= params[:author_post]
    end

一点需要注意的是:在该控制器中,您将无法使用load_and_authorize_resource。您需要手动执行此操作,详细信息请参见此处:https://github.com/ryanb/cancan/wiki/Controller-Authorization-Example 您需要用@resource替换Project
我对于这种方法是否比railscast中描述的方法更加有效还有些犹豫。对于我的目的而言,它完全保留了原始模型,因此我的其他代码没有受到影响——只是允许我给一些用户提供较少的可编辑字段。

0

有一种方法,我在我的项目中做了类似的事情。但是CanCan并不完全是答案。你需要根据用户角色使模型中的attr_accessible动态化,因此如果您是管理员,则允许您更新已发布字段。如果不是,则在模型保存时,简单地给该字段赋新值将不起作用。

Railscasts再次拯救:http://railscasts.com/episodes/237-dynamic-attr-accessible

在实现后端部分之后,您可以通过在视图中使用角色检查或其他方式来包装发布字段,以根据用户显示或隐藏该字段。以下是我实现的粗略示例...

<% if current_user.roles.where(:name => ['Administrator','Editor']).present? %>
    <%= f.label :display_name %>
    <%= f.text_field :display_name %>
<% end %>

谢谢,我喜欢这个 - 现在去看那个railscast了 - 谢谢 :) - stephenmurdoch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接