【问题标题】:Why doesn't the data is not displayed when going through the ability check?(rails,cancancan)为什么通过能力检查时数据不显示?(rails,cancancan)
【发布时间】:2017-07-20 06:24:07
【问题描述】:

我希望在我的 rails 应用程序中拥有 3 个用户级别,分别是管理员、经理、客户。所以我创建了一个设计模型作为用户,并添加了一个迁移来添加用户角色。所以当用户注册时,它存储用户角色(无论他是管理员、经理还是客户)。在我的应用程序中,有产品、交付、服务的模型和控制器。我想为每个模型设置访问级别。

因此管理员可以访问所有模型、控制器

经理有权访问产品、交付

客户可以访问服务

我已经编写了如下的能力模型

class Ability
  include CanCan::Ability

  def initialize(user)

    user ||= User.new # guest user (not logged in)

    if user.roles == "admin"
      can :manage , :all
    elsif user.roles == "manager"
      can :read, Products, Delivery
    elsif user.roles == "customer"
      can :read, Services
    end
end
end

在我的产品展示视图中,我有以下代码

<% if can? :manage ,@products%>

<h1>Products</h1>

<% @products.each do |product| %>
<p>     <%= product.name%>
<p>         <%= product.price %><br>
<p>    <%= product.qty %><br>

  <%end%>
<%end%>

但即使我以管理员身份登录,我也看不到内容。但是当我删除能力检查行时,它可以毫无问题地查看。所以我预测问题应该是使用过的方式授权。 我的用户模型如下。

    class User < ApplicationRecord
  belongs_to :role
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

         ROLES = %i[admin manager customer]
def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation, :role)
end

end

在views/devise/registrations/new.html.erb 我已包含以下代码块。

<div>
    <%= f.collection_select(:role, User::ROLES, :to_s, lambda{|i| i.to_s.humanize}) %>
  </div>

这就是我必须检查我的产品/显示视图中的能力

<% if can? :manage ,@products%>

<h1>Products</h1>

<% @products.each do |product| %>
<p>     <%= product.name%>
<p>         <%= product.price %><br>
<p>    <%= product.qty %><br>

  <%end%>
<%end%>

【问题讨论】:

    标签: ruby-on-rails ruby devise cancan cancancan


    【解决方案1】:

    user.roles 返回一个数组,您将数组与字符串user.roles == "admin" 进行比较,字符串始终为false。

    改为使用User 模型中的方法,例如user.role?(:admin) 来检查角色

    所以你的能力应该是这样的

    class Ability
      include CanCan::Ability
    
      def initialize(user)
        user ||= User.new # guest user (not logged in)
        if user.role? :admin
          can :manage, :all
        elsif user.role? :manager
          can :read, [Product, Delivery]
        elsif user.role? :customer
          can :read, Service
        end
      end
    end
    

    现在你应该在你的控制器中写一些谎言

    class ProductsController < ActionController
      load_and_authorize_resource
    
      def index
      ...
      end
    
      # and other resouceful actions
    end
    

    load_and_authorize_resource 有很多魔力,其中之一就是加载current_user(设计用户)可以访问的所有产品。

    现在,您不必明确检查&lt;% if can? :manage ,@products%&gt;。 @products 将只有当前用户有权访问的产品。

    <h1>Products</h1>
    <%@products.present?%>
       <% @products.each do |product| %>
        <p><%= product.name %></p>
        <p><%= product.price %></p>
        <p><%= product.qty %></p>
      <%end%>
    <%else%>
      <p>There are no products to display.</p>
    <%end%>
    

    【讨论】:

    • 稍微更新了问题。请您改进您的答案让我有一个清晰的想法。
    • @TharinduThathsarana 希望更新的答案可以帮助你。
    • 非常感谢..对我帮助很大
    • 但是在 cancancan 文档中它说如果我们为每个用户实现一个角色是可能的。并且它说“确定用户在能力类中的角色非常简单。”可以 :manage, :all if user.role == "admin" 。 github.com/CanCanCommunity/cancancan/wiki/…
    • 你能解释一下吗?
    猜你喜欢
    • 1970-01-01
    • 2016-06-08
    • 2015-11-25
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    相关资源
    最近更新 更多