我如何访问 CASL 条件的嵌套属性

use*_*604 2 node.js typescript casl

我似乎无法使用条件规则访问嵌套对象。我希望如果文章的评论与用户具有相同的 id,则用户有权删除该文章。这些只是一些要测试的编造课程......

这是我的代码:

import { defineAbility, AbilityBuilder } from '@casl/ability';

import { Ability, AbilityClass, ExtractSubjectType, InferSubjects } from '@casl/ability';

export class Article {
    static readonly modelName = "Article";
    static readonly __typename = "Article";
    constructor(  id: number,
        title: string,
        content: string,
        user: User,
        comment: Comment) {
            this.id = id
            this.title = title
            this.content = content
            this.user = user
            this.comment = comment
        }
  id: number
  title: string
  content: string
  user: User
  comment: Comment
}

export class User {
    static readonly modelName = "User"
    static readonly __typename = "User";
    constructor (id: number,
        name: string,
        comment: Comment) {
            this.id = id
            this.name = name
            this.comment = comment
        }
  id: number
  name: string
  comment: Comment
}

export class Comment {
    static readonly modelName = "Comment"
    static readonly __typename = "Comment";
  constructor(id: number,
    content: string,
    authorId: number) {
        this.id = id
        this.content = content
        this.authorId = authorId
    }
    id: number
  content: string
  authorId: number
}

type Action = 'create' | 'read' | 'update' | 'delete';
type Subjects = InferSubjects<typeof Article | typeof Comment| typeof User, true>;

export type AppAbility = Ability<[Action, Subjects]>;


export function createForUser(user: User) {
    const { can, cannot, build } = new AbilityBuilder<
      Ability<[Action, Subjects]>
    >(Ability as AbilityClass<AppAbility>);

    can('delete', Article, { comment: {id: user.comment.id}})

    return build({
      detectSubjectType: item => item.constructor as ExtractSubjectType<Subjects>
    });
  }
Run Code Online (Sandbox Code Playgroud)

我用以下方法测试它:

const comment = new Comment(0, 'a', 0)
const user = new User(1, 'sd', comment);
const article = new Article(2, 'sd', 'asd', user, comment)
const ability = createForUser(user);

console.log(ability.can('delete', article))// false
Run Code Online (Sandbox Code Playgroud)

我在某个地方看到我需要做这样的事情: can('delete', Article, { 'comment.id': user.comment.id}) 但是当我这样做时说“对象文字只能指定已知的属性,并且‘string[]’类型中不存在‘‘comment.id’’”

Ser*_*kyi 7

您可以在https://casl.js.org/v5/en/advanced/typescript上找到带有点符号 \xe2\x80\x9d 的 \xe2\x80\x9c 嵌套字段。简而言之,当您使用 for 表示法与 typescript 一起定义条件时,您需要创建一个自定义类型:

\n
type FlatArticle = Article & {\n  \'comment.id\': Article[\'comment\'][\'id\']\n};\n\ncan<FlatArticle>(\'read\', Article, { \'comment.id\': 1 });\n
Run Code Online (Sandbox Code Playgroud)\n