0

我正在尝试将 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
4

0 回答 0