我正在尝试将 CASL 与 NestJS 和 Knex 一起使用。我想限制用户只更新和删除他们自己的类别。但是,该能力似乎对我不起作用。
我使用这个类来创造能力:
type Subjects = InferSubjects<typeof Category | typeof User> | 'all';
export type AppAbility = Ability<[Action, Subjects]>;
@Injectable()
export class CaslAbilityFactory {
createForUser(user: User) {
const {
can: allow,
cannot: forbid,
build,
} = new AbilityBuilder<Ability<[Action, Subjects]>>(Ability as AbilityClass<AppAbility>);
allow([Action.Update, Action.Delete], Category, { id_user: user.id });
return build({
// Read https://casl.js.org/v5/en/guide/subject-type-detection#use-classes-as-subject-types for details
detectSubjectType: (item) => item.constructor as ExtractSubjectType<Subjects>,
});
}
}
export class Category {
id: string;
name: string;
description: string;
id_user: string; // using uuids
public: boolean;
created_at: string;
updated_at: string;
}
在服务内部,我使用 knex 查询一个类别,然后尝试检查该类别的能力,但是当第一个if
评估为false
第二个if
语句时,总是评估为true
,因此抛出异常。
public async update(id: string, req: any, request: UpdateCategoryRequest) {
const category: Category = await this.knex<Category>('categories')
.where({ id: id })
.first();
const ability = this.casl.createForUser(req.user);
console.log(`Ability.Can: ${ability.can(Action.Update, category)}`);
console.log(`Ability.Cannot: ${ability.cannot(Action.Update, category)}`);
if (ability.can(Action.Update, category)) {
console.log('I can update this.');
}
if (!ability.can(Action.Update, category)) {
console.log('Cannot update this resource.');
throw new HttpException('You can not update this resource.', HttpStatus.FORBIDDEN);
}
return this.knex('categories').where({ id: id }).update(request, ['*']);
}
我试图检查从 knex 返回的类型,使用category instanceof Category
. 这评估为假,所以我猜ability.can(Action.Update, category)
它不起作用,因为category
它不是 class 的实例Category
。如果我尝试使用类构造函数创建一个新类别,它工作正常。
let cat: Category = new Category();
cat.id_user = '7dc75a42-c74c-4cae-9d46-42e590de99b0';
ability.can(Action.Update, cat); // true