首页 > 解决方案 > 使用 cancancan 的 3 类角色的授权问题

问题描述

我有用户表(由设计创建),我添加了一个角色列,可以是:管理员、经理和代理。在 user.rb 我放了一个像这样的枚举:

class User < ApplicationRecord
  enum role: { admin: 0, manager: 1, agent: 2 }
end

我正在使用 cancancan 并想做两件事:

1 - 如何根据注册用户的角色显示菜单或不同的按钮?在视图中,我是这样说的:

<% if current.present? && current_user.admin? %>
            <%= link_to 'Purchases (Admin access)', admin_purchases_path, class: 'nav-link mr-5 ' %>
          <% end %>

2 - 如何根据用户的角色显示特定页面?在我的 User.rb 我把这个:

def admin?
    self.role == 'admin'
  end

我在ability.rb上尝试它:

  user ||= User.new # guest user (not logged in)
  if admin?
    can :manage, :all
  else
    can :read, :all
  end

在控制器上,我放了:

 load_and_authorize_resource

但我收到一个错误:

NoMethodError in Home#index
undefined method `admin?' for nil:NilClass
<% if current_user.admin? %> <<< On this line here

标签: ruby-on-railsauthorizationruby-on-rails-6cancancanruby-on-rails-6.1

解决方案


您可以使用安全导航运算符来避免零错误:

<% if current_user&.admin? %>

然而,它仍然有点反模式。使用像 CanCanCan 这样的授权库的全部意义在于整合授权逻辑,而不是将其分散到您的控制器和视图中。

相反,您的视图应该询问 CanCanCan 用户是否有权执行链接所做的任何事情:

<% if can? :administrate, :purchases %>
  <%= link_to 'Purchases (Admin access)', admin_purchases_path, class: 'nav-link mr-5 ' %>
<% end %>

它不必知道用户是否是管理员或管理员是否可以管理购买。那是CanCanCans的工作。

user ||= User.new # guest user (not logged in)
if user.admin?
  can :manage, :all
  can :administrate, :all
else
  can :read, :all
end

在我的 User.rb 我把这个..

该代码是完全多余的。enum role: { admin: 0, manager: 1, agent: 2 }已经创建了集成方法admin?manager?并且agent?

您的问题ability.rb是您在if admin?没有实际指定收件人的情况下打电话。你应该打电话if user.admin?


推荐阅读