【问题标题】:CanCan: limiting a user's ability to set certain model attributes based on their roleCanCan:限制用户根据角色设置某些模型属性的能力
【发布时间】:2011-05-07 14:11:12
【问题描述】:

我有一个带有 :published 属性 (boolean) 的 Post 模型和一个带有 role 属性 (字符串)。共有三个角色:ROLES = %w[admin publisher author]

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

我正在使用 CanCan(和 RailsAdmin gem),我简化的 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

任何人有做这种事情的任何提示吗?

【问题讨论】:

    标签: ruby-on-rails cancan


    【解决方案1】:

    到目前为止,这是不可能的。但据此:https://github.com/ryanb/cancan/issues/326这个功能应该在cancan 2.0中。

    更新:你可以在这里看到 CanCan 2.0 分支:https://github.com/ryanb/cancan/tree/2.0 在“资源属性”部分

    【讨论】:

    • 好的,谢谢,那我会关注CanCan v2.0。谢谢
    • 我知道它并不完美,但我认为你仍然可以使用cannot <<your attribute>>, :klass bee,因为它们在等待 2.0 时仍然是 ruby​​ 中的方法。
    【解决方案2】:

    查看这篇文章:How do I use CanCan with rails admin to check for ownership

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

    更新 我可以使用以下代码在 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 字段(设置为 type='hidden' )并设置默认值。

    希望这对某人有所帮助。

    【讨论】:

      【解决方案3】:

      在 CanCan 2.0 出现之前,我已经通过创建一个可访问性受限的模型子类来解决这个问题,例如:

      class AuthorPost < Post
        attr_protected :published
      end
      

      然后授予作者访问 AuthorPosts 的权限:can :manage =&gt; 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

      您需要将Project 替换为@resource

      我不确定这是否比 railscast 中描述的方法更有效。出于我的目的,它使原始模型完全完好无损,因此我的其他代码没有受到影响——并且只允许我为一些用户提供更少的可编辑字段。

      【讨论】:

        【解决方案4】:

        有一种方法,我在我的项目中做了这样的事情。但 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 - 谢谢 :)
        猜你喜欢
        • 2012-08-30
        • 1970-01-01
        • 1970-01-01
        • 2022-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-07
        相关资源
        最近更新 更多