Skip to content

Nest 初始化 和 权限分级

初始化

  • 上来赋值 3 个用户 3 个角色 3 个权限

新建一个 user.init.service.ts

  • 绑定到 model 上面
ts
import { Inject, Injectable } from "@nestjs/common";
// 引入数据库模块
import { PrismadbService } from "../../prisma/prisma.service";
// 引入redis模块
import { RedisService } from "../../redis/redis.service";
// 引入异常模块
import { GlobalCheckException } from "../../../common/globalcheck.exception";
// 引入md5
// 引入加密模块
import * as crypto from "crypto";

export class UserInitService {
  @Inject(RedisService)
  private readonly redisService: RedisService;

  @Inject(PrismadbService)
  private readonly prismaService: PrismadbService;

  md5(password) {
    const hash = crypto.createHash("md5");
    hash.update(password);
    const passwordhash = hash.digest("hex");
    return passwordhash;
  }

  // 初始化
  async init() {
    // 初始化数据
    const users = [
      {
        username: "admin",
        password: this.md5("123456"),
        email: "2993222085@qq.com",
        phone_number: "19000000001",
        nick_name: "超级管理员",
        head_pic: "https://file.jsopy.com/IMAGES/avatarsmoke.jpg",
        is_frozen: 1,
        is_admin: 2,
      },
      {
        username: "admin2",
        password: this.md5("123456"),
        email: "2993222086@qq.com",
        phone_number: "19000000002",
        nick_name: "频道管理员",
        head_pic: "https://file.jsopy.com/IMAGES/avatar.jpg",
        is_frozen: 1,
        is_admin: 1,
      },
      {
        username: "admin3",
        password: this.md5("123456"),
        email: "2993222087@qq.com",
        phone_number: "19000000003",
        nick_name: "游客",
        head_pic: "https://file.jsopy.com/IMAGES/avatarmoney.jpg",
        is_frozen: 1,
        is_admin: 1,
      },
    ];
    // 角色
    const roles = [
      {
        name: "超级管理员",
      },
      {
        name: "频道管理员",
      },
      {
        name: "游客",
      },
    ];
    // 权限
    const permissions = [
      {
        code: "*",
        description: "超级管理员",
      },
      {
        code: "user",
        description: "user管理员",
      },
      {
        code: "testproject",
        description: "testproject管理员",
      },
    ];
    // 测试先创建用户
    const userresult = await this.createUser(users);
    // 创建角色
    const rolesresult = await this.create_roles(roles);
    // 创建 权限
    const permissionresult = await this.create_permission(permissions);
    // 用户角色关系
    const userRolesResult = await this.createUserRoles();
    // 角色 和 权限关系
    const rolePermissionResult = await this.createRolePermissions();
    return true;
  }

  // 1. 创建用户
  async createUser(users: any) {
    //1 . 查询以前有没有用户
    const oldnum = await this.createUser_findold(users);
    if (oldnum == 0) {
      // 存入
      const result = await this.prismaService.users.createMany({
        data: users,
      });
      return result;
    } else {
      throw new GlobalCheckException("用户已存在");
    }
  }

  // 1.1 创建用户查询
  async createUser_findold(users: any): Promise<number> {
    // 查询有没有用户
    const result = await this.prismaService.users.findMany({
      where: {
        email: {
          in: users.map((item: any) => item.email),
        },
      },
    });
    // 返回结果
    if (result) {
      return result.length;
    } else {
      return 0;
    }
  }

  // 2 创建角色
  async create_roles(roles: any) {
    const result = await this.createRoles_findold(roles);
    if (result == 0) {
      const result = await this.prismaService.roles.createMany({
        data: roles,
      });
      return result;
    } else {
      return null;
    }
  }

  // 2.1 读取角色
  async createRoles_findold(roles: any) {
    const result = await this.prismaService.roles.findMany({
      where: {
        name: {
          in: roles.map((item: any) => item.name),
        },
      },
    });
    if (result) {
      return result.length;
    } else {
      return 0;
    }
  }

  // 3. 创建权限
  async create_permission(permissions: any) {
    const result = await this.create_permission_findold(permissions);
    if (result == 0) {
      const result = await this.prismaService.permissions.createMany({
        data: permissions,
      });
      return result;
    } else {
      return null;
    }
  }

  // 3.1 读取权限
  async create_permission_findold(permissions: any) {
    const result = await this.prismaService.permissions.findMany({
      where: {
        code: {
          in: permissions.map((item: any) => item.code),
        },
      },
    });
    if (result == permissions.length) {
      return result.length;
    } else {
      return 0;
    }
  }

  // 4. 创建用户角色
  async createUserRoles() {
    const users = await this.prismaService.users.findMany();
    const roles = await this.prismaService.roles.findMany();
    // 查询老的
    const result = await this.createUserRoles_findold(users);
    if (result) {
      const result = await this.prismaService.user_roles.createMany({
        data: users.map((item: any, index: number) => {
          return {
            user_id: item.id,
            role_id: roles[index].id,
          };
        }),
      });
      return true;
    } else {
      return null;
    }
  }

  // 4.1 查询一下 以前有没有

  async createUserRoles_findold(users: any) {
    const result = await this.prismaService.user_roles.findFirst({
      where: {
        user_id: {
          in: users.map((item: any) => item.id),
        },
      },
    });
    if (result) {
      return false;
    } else {
      return true;
    }
  }

  // 5. 角色权限
  async createRolePermissions() {
    const roles = await this.prismaService.roles.findMany();
    const permissions = await this.prismaService.permissions.findMany();
    const result = await this.createRolePermissions_findold(roles);
    if (result) {
      // 超级管理员
      await this.prismaService.role_permissions.createMany({
        data: roles.map((item: any, index: number) => {
          return {
            role_id: roles[0].id,
            permission_id: permissions[index].id,
          };
        }),
      });
      // 频道管理员
      await this.prismaService.role_permissions.create({
        data: {
          role_id: roles[1].id,
          permission_id: permissions[1].id,
        },
      });
      // 游客
      await this.prismaService.role_permissions.create({
        data: {
          role_id: roles[2].id,
          permission_id: permissions[2].id,
        },
      });
      return true;
    }
  }

  // 5.1 查询以下老的
  async createRolePermissions_findold(roles: any) {
    const result = await this.prismaService.role_permissions.findFirst({
      where: {
        role_id: {
          in: roles.map((item: any) => item.id),
        },
      },
    });
    if (result) {
      return false;
    } else {
      return true;
    }
  }
}

user.controller.ts

  • 新建 init 接口
ts
  // 初始化
  @Post('init')
  async init() {
    const result = await this.userInitService.init();
    if (result) {
      return {
        code: 200,
        message: '初始化成功',
      };
    } else {
      return {
        code: 403,
        message: '初始化失败',
      };
    }
  }

利用 RBAC 进行权限鉴别

新建一个权限守卫 roles.guard.ts

ts
import {
  Injectable,
  CanActivate,
  ExecutionContext,
  Inject,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { Reflector } from "@nestjs/core";
import { PrismadbService } from "../moduels/prisma/prisma.service";
import { RedisService } from "../moduels/redis/redis.service";
import { ConfigService } from "@nestjs/config";
// 抛出异常
import { GlobalGuardException } from "../common/globalguard.exception";
@Injectable()
export class RolesGuard implements CanActivate {
  @Inject()
  private readonly redisService: RedisService;
  @Inject()
  private readonly prismadbService: PrismadbService;
  @Inject(Reflector)
  private readonly reflector: Reflector;
  @Inject()
  private configService: ConfigService;
  async canActivate(context: ExecutionContext): Promise<any> {
    // 白名单就放行
    let isPublic = false;

    //权限验证
    const request = context.switchToHttp().getRequest();
    // 白名单
    const whiteList = this.configService.get("PERMISSION_WHITELIST");
    // 如果没有就放行
    if (whiteList == "" || whiteList.includes(request.url)) {
      isPublic = true;
    }
    if (isPublic) {
      return true;
    } else {
      // 获取到设定的权限
      const permissions = this.reflector.getAllAndOverride<string[]>(
        "permissions",
        [context.getHandler(), context.getClass()]
      );
      // 通过userId获取到用户角色
      // 权限验证 全局守卫会给你userId
      const request = context.switchToHttp().getRequest();
      // 1. 先去redis中查找 2. 找不到就走数据库 3. 数据库取出来存到redis中
      let userPermissionsName: any = await this.redisService.getlist(
        `userId_${request.userId}_roles`
      );
      if (!userPermissionsName || userPermissionsName.length === 0) {
        console.log("进数据库来了");
        // 1. 查出这个用户拥有的角色ID
        const RoleId: any = await this.prismadbService.user_roles.findMany({
          where: {
            user_id: request.userId,
          },
          select: {
            role_id: true,
          },
        });

        // 2. 查询出这个角色拥有的权限ID
        const userPermissionsId: any =
          await this.prismadbService.role_permissions.findMany({
            where: {
              role_id: {
                in: RoleId.map((item) => item.role_id),
              },
            },
            select: {
              permission_id: true,
            },
          });

        // 3. 查出这个权限ID对应的权限
        let userPermissions = await this.prismadbService.permissions.findMany({
          where: {
            id: {
              in: userPermissionsId.map((item) => item.permission_id),
            },
          },
          select: {
            code: true,
          },
        });
        userPermissionsName = userPermissions.map((item) => item.code);
        console.log("最后结果");
        console.log(userPermissionsName);
        // 3. 存到redis中
        this.redisService.setlist(
          `userId_${request.userId}_roles`,
          userPermissionsName,
          60 * 30
        ); // 过期时间30分钟
      }
      // 判断返回
      const result = permissions.some((item) => {
        return userPermissionsName.includes(item);
      });

      if (result) {
        return true;
      } else {
        throw new GlobalGuardException("权限不足");
      }
    }
  }
}

接口里面使用

  • 比如 user 模块下面 增加一个 权限守卫, 这个相当于只有权限是, *或者 user 能访问 到这个接口

  • testproject 访问不了这个模块

ts
import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  UseGuards,
  Req,
  SetMetadata,
} from "@nestjs/common";
import { UserRegisterService } from "./services/user.register.service";
import { UserSendEmailService } from "./services/user.sendEmail.service";
import { UserLoginService } from "./services/user.login.service";
import { UserInitService } from "./services/user.init.service";
import { RegisterUserDto } from "./dto/register-user.dto";
import { AuthGuard } from "@nestjs/passport";
import { RolesGuard } from "../../common/roles.guard";
@Controller("user")
@SetMetadata("permissions", ["*", "user"])
@UseGuards(RolesGuard)
export class UserController {
  constructor(
    private readonly userRegisterService: UserRegisterService,
    private readonly userSendEmailService: UserSendEmailService,
    private readonly userLoginService: UserLoginService,
    private readonly userInitService: UserInitService
  ) {}

  // 初始化
  @Post("init")
  async init() {
    const result = await this.userInitService.init();
    if (result) {
      return {
        code: 200,
        message: "初始化成功",
      };
    } else {
      return {
        code: 403,
        message: "初始化失败",
      };
    }
  }

  // 测试验证
  @Get("testroles")
  async testroles() {
    return {
      code: 200,
      message: "验证成功",
      data: "通过验证",
    };
  }
}