这里对于casl装饰器有点疑问

来源:12-17 权限控制:与casl集成并完成策略权限控制(作业与奖励)

宝慕林4472258

2023-01-20

这是log实体

import {
  Column,
  Entity,
  JoinColumn,
  ManyToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { User } from '../../users/entities/users.entity';
import { BaseEntity } from '../../../common/entities/base.entity';

@Entity()
export class Log extends BaseEntity {
  @Column()
  path: string;

  @Column()
  method: string;

  @Column()
  result: number;

  @Column()
  data: string;

  @ManyToOne(() => User, (user) => user.logs, {
    onDelete: 'CASCADE',
  })
  @JoinColumn()
  user: User;
}

controller

import { Controller, Delete, Get, UseGuards } from '@nestjs/common';
import { LogsService } from './logs.service';
import { Can, CheckPolicies } from '../../decorators/casl.decorator';
import { ActionEnum } from '../../common/enum/action.enum';
import { CaslGuard } from '../../guards/casl.guard';
import { JwtGuard } from '../../guards/jwt.guard';
import { Log } from './entities/logs.entity';

@Controller('logs')
@UseGuards(JwtGuard, CaslGuard)
export class LogsController {
  constructor(private readonly logsService: LogsService) {}

  @Delete()
  @CheckPolicies((ability) => ability.can(ActionEnum.READ, Log))
  getHello() {
    return this.logsService.findAll();
  }
}

casl.service

import { Injectable } from '@nestjs/common';
import { AbilityBuilder, createMongoAbility } from '@casl/ability';
import { ActionEnum } from '../../common/enum/action.enum';
import { Log } from '../logs/entities/logs.entity';
import { UsersService } from '../users/users.service';
import { User } from '../users/entities/users.entity';
import { Menu } from '../menu/entities/menu.entity';
import { Role } from '../roles/entities/roles.entity';

@Injectable()
export class CaslService {
  constructor(private readonly userService: UsersService) {}

  async forRoot(id: number) {
    const { build, can, cannot } = new AbilityBuilder(createMongoAbility);
    const permission = await this.userService.findUserPermissions(id);
    permission.forEach((item) => {
      const { action, controller } = item;
      const entity = this.getEntity(controller);
      if (entity) {
        can(action as ActionEnum, entity);
      }
    });
    return build({
      detectSubjectType: (object) => object.constructor,
    });
  }

  getEntity(key: string) {
    const map = {
      user: User,
      menu: Menu,
      role: Role,
      log: Log,
    };
    if (map[key]) {
      return map[key];
    }
    return null;
  }
}

例如我想在这里指定用户能够查询method为get的日志,或者进让用户修改自己日志的method字段,实际应用中condition参数提示我需要是一个字符串,有点不理解

写回答

1回答

Brian

2023-01-23

我没有看到你定义的casl的装饰器,应该是这样定义的:

export const Can = (
  action: Action,
  subject: InferSubjects<any>,
  conditions?: any, // 这里可以定义成any
)


然后再来说说你的逻辑:

1. 指定用户能够查询method为get的日志——@Can(Action.Read, User, { methed: 'get' })

2. 进让用户修改自己日志的method字段 ——这个可以参考AdminGuard


PS: 这里我有点搞不懂,日志模块在业务上原则上只允许管理员进行管理->一般是删除操作,其他用户可以分配查询权限。

0
0

NestJS 入门到实战 前端必学服务端新趋势

近几年快速发展的Node.js框架,掌握未来前端工程师后端开发能力

569 学习 · 238 问题

查看课程