为什么我的CanCan Ability课程过于宽松? [英] why is my CanCan Ability class overly permissive?
问题描述
我(最终)将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屋!