首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何访问CASL条件的嵌套属性

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

Stack Overflow用户
提问于 2021-03-05 16:42:14
回答 2查看 429关注 0票数 0

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

下面是我的代码:

代码语言:javascript
复制
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>
    });
  }

我用以下命令测试它:

代码语言:javascript
复制
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

我在某个地方看到我需要这样做:Comment.id,但当我这样做时,它说'Object can('delete', Article, { 'comment.id': user.comment.id})只能指定已知属性,而''comment.id'‘不存在于类型'string[]’中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-13 18:08:58

最终像这样解决了它:

代码语言:javascript
复制
export enum Action {
    Manage = 'manage',
    Create = 'create',
    Read   = 'read',
    Update = 'update',
    Delete = 'delete',
}

export type Subject = InferSubjects<typeof Article | 
                                     typeof Comment | 
                                     typeof User | 
                                     'all';

export type AppAbility = PureAbility<[Action, Subject]>;
export const AppAbility = Ability as AbilityClass<AppAbility>;

然后像这样定义规则:

代码语言:javascript
复制
createForUser(user: User) {
  const { can, cannot, build } = new AbilityBuilder(AppAbility);
  
  
  can(Action.Read, Article, { 'comment.id': 1 });

    
  return build({
    detectSubjectType: item => item.constructor as ExtractSubjectType<Subject>
  });
}
票数 0
EN

Stack Overflow用户

发布于 2021-03-12 04:30:16

您可以在https://casl.js.org/v5/en/advanced/typescript上找到“带点符号的嵌套字段”部分。简而言之,当您使用for notation与typescript一起定义条件时,您需要创建一个自定义类型:

代码语言:javascript
复制
type FlatArticle = Article & {
  'comment.id': Article['comment']['id']
};

can<FlatArticle>('read', Article, { 'comment.id': 1 });
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66489330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档