为什么我的CanCan Ability课程过于宽松? [英] why is my CanCan Ability class overly permissive?

查看:68
本文介绍了为什么我的CanCan Ability课程过于宽松?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我(最终)将CanCan / Ability连接到我的应用程序中,并且我首先编写了RSpec测试。但是他们失败了-我的能力似乎太宽容了,我不明白为什么。

I'm (finally) wiring CanCan / Ability into my app, and I've started by writing the RSpec tests. But they're failing — my Abilities appear to be overly permissive, and I don't understand why.

首先是Ability类。目的是非管理员用户只能自己管理。特别是,他们不能查看其他用户:

First, the Ability class. The intention is that non-admin users can manage only themselves. In particular, they cannot look at other users:

class Ability
include CanCan::Ability

  def initialize(user)
    user ||= User.new           # create guest user if needed
    if (user.has_role?(:admin))
      can(:manage, :all)
    else
      can(:manage, User, :id => user.id)
    end
  end
end

RSpec测试:

require 'spec_helper'
require 'cancan/matchers'

describe Ability do
  before(:each) do
    @user = User.create
  end

  describe 'guest user' do
    before(:each) do
      @guest = nil
      @ability = Ability.new(@guest)
    end

    it "should_not list other users" do
      @ability.should_not be_able_to(:read, User)
    end

    it "should_not show other user" do
      @ability.should_not be_able_to(:read, @user)
    end

    it "should_not create other user" do
      @ability.should_not be_able_to(:create, User)
    end

    it "should_not update other user" do
      @ability.should_not be_able_to(:update, @user)
    end

    it "should_not destroy other user" do
      @ability.should_not be_able_to(:destroy, @user)
    end
  end
end

所有这五个测试均失败。我已经阅读 Ryan的文档部分,他说:

All five of these tests fail. I've read the part of Ryan's documentation where he says:


重要提示:如果存在
条件的块或哈希,则在检查类时将忽略
,它将
返回true。

Important: If a block or hash of conditions exist they will be ignored when checking on a class, and it will return true.

...但最多只能解释这五个失败中的两个。显然,我缺少一些基本知识。

... but at most, that would only explain two of the five failures. So clearly I'm missing something fundamental.

推荐答案

我有回答我自己问题的这种坏习惯,但是我给@jpemberthy和@Austin Taylor为我指出正确方向的道具。首先(这是装饰性的),我将其添加到我的用户模型中:

I've got this bad habit of answering my own questions, but I give props to @jpemberthy and @Austin Taylor for pointing me in the right direction. First (and this is cosmetic), I added this to my User model:

class User
  ...
  def self.create_guest
    self.new
  end

  def guest?
    uninitialized?
  end
end

并相应地清理我的能力模型:

and cleaned up my Abilities model accordingly:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.create_guest
    if (user.admin?)
      <admin abilities here>
    elsif (user.guest?)
      <guest abilities here>
    else
      <regular user abilities here>
    end
  end
end

但是真正的解决方法是我的RSpec测试。由于用户对电子邮件和密码字段进行了验证,因此我的原始代码为:

But the real fix was in my RSpec tests. Since User has validations on email and password fields, my original code of:

before(:each) do
  @user = User.create
end

失败,因此创建了未初始化的 @用户。由于:id字段为nil,因此Ability子句:

was failing, thus creating an uninitialized @user. Since the :id field was nil, the Ability clause:

can(:manage, User, :id => user.id)

用来宾用户成功,因为nil == nil(如果有意义)。添加必需的字段来满足用户验证,使(几乎)所有工作都可以正常工作。

was succeeding with a guest user because nil == nil (if that makes sense). Adding the required fields to satisfy the User validations made (almost) everything work.

道德:就像@jpemberthy在他的代码中建议的那样,始终包括一个测试以确保您的用户对象具有应有的特权! (我还有另一个关于CanCan的问题,希望它的头脑比这个更少,出现在您附近的StackOverflow主题中...)

Moral: just as @jpemberthy suggested in his code, always include a test to make sure your user objects have the privileges that they are supposed to! (I still have another question regarding CanCan, hopefully less boneheaded than this one, appearing in a StackOverflow topic near you...)

这篇关于为什么我的CanCan Ability课程过于宽松?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆