// rbac.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { In, Not, QueryRunner, Repository, getConnection } from 'typeorm'; import { Role } from './entity/role.entity'; import { Permission } from './entity/permission.entity'; import { User } from './entity/user.entity'; import { minimatch } from 'minimatch'; interface PermissionItem { id: string; name: string; description?: string; resources: string[]; } @Injectable() export class RbacService { constructor( @InjectRepository(Permission) private permissionRepository: Repository, @InjectRepository(User) private userRepository: Repository, @InjectRepository(Role) private roleRepository: Repository, ) {} async initSuperAdminRole() { const exsit = await this.roleRepository.findOne({ where: { name: 'superadmin' }, }); if (!exsit) { await this.roleRepository.save({ name: 'superadmin', alias: '超级管理员', description: 'god', }); } } /** * 初始化超级管理的账户 */ async initSuperAdminAccount() { const superadminRole = await this.roleRepository.findOne({ where: { name: 'superadmin' }, }); if (!superadminRole) return await this.userRepository.save({ username: 'admin', password: 'admin', roles: [superadminRole], }); } async createRole(payload: Role) { const { name, alias, description } = payload; const exsit = await this.roleRepository.findOne({ where: { name } }); if (exsit) return { message: '用户已存在' }; const result = await this.roleRepository.save({ name, alias, description }); return result; } async findAllRole() { const roleWithPermissions = await this.roleRepository.find({ where: { name: Not('superadmin') }, relations: ['permissions'], }); const allPermissions = await this.permissionRepository.find({ select: ['id', 'name', 'description', 'resources'], }); // 查询角色下的用户 for (let i = 0; i < roleWithPermissions.length; i++) { const { id: roleId } = roleWithPermissions[i]; roleWithPermissions[i].users = await this.userRepository .createQueryBuilder('user') .select([ 'user.id', 'user.username', 'user.isEnabled', 'user.phoneNumber', 'user.createTime', ]) .innerJoinAndSelect('user.roles', 'role', 'role.id = :roleId', { roleId, }) .getMany(); } return { roleWithPermissions, allPermissions }; } /** * 初始化permission表 * 0. 清空role_perission关联标的相关信息 * 1. 清空旧的权限表信息 * 2. 更新最新的permissions */ async initPermission(permissions: PermissionItem[]) { const records = permissions.map((i) => ({ ...i, name: i.name, resources: i.resources.join(','), })); await this.permissionRepository.save(records); } async findRolePermission(roleId: number) { //查询粗roleId关联的permission return await this.roleRepository.findOne({ where: { id: roleId }, relations: ['permissions'], }); } async updateRolePermissions(payload: any) { const { roleId, permissionIds } = payload; const role = await this.roleRepository.findOne({ where: { id: roleId }, relations: ['permissions'], }); const newPermissions = await this.permissionRepository.find({ where: { id: In(permissionIds) }, }); role.permissions = newPermissions; return await this.roleRepository.save(role); } /** * 删除角色 * 1.删除用户有这个role的关联 * 2.删除role和permission的关联 * 3.删除这个role */ async removeRole(r: Role) { await this.roleRepository .createQueryBuilder() .delete() .from('user_roles_role') .where('roleId = :roleId', { roleId: r.id }) .execute(); const role = await this.roleRepository.findOne({ where: { id: r.id } }); if (role) return await this.roleRepository.remove(role); } async updateRole({ roleId, ...rest }) { await this.roleRepository.save({ id: roleId, ...rest }); const role = await this.roleRepository.findOne({ where: { id: roleId }, relations: { permissions: true }, }); role.permissions = rest.isEnabled ? role.permissions : []; return await this.roleRepository.save(role); } async findAllUser() { return await this.userRepository.find({ relations: { roles: true }, select: ['id', 'username', 'phoneNumber', 'createTime', 'isEnabled'], }); } async roleAuthorize(user, url) { // 查询角色对应的resource const raw = await this.userRepository .createQueryBuilder('user') .leftJoinAndSelect('user.roles', 'role') .leftJoinAndSelect('role.permissions', 'permission') .where('user.username = :username', { username: user.username }) .select('permission.resources') .getRawMany(); const permissions = raw.map((r) => r.permission_resources).filter(Boolean); console.log( `本次请求的用户: ${user.username},可访问资源: ${permissions.join(', ')}`, ); // 判断角色的permission的resource是否包含url const allow = permissions.some((path: string) => minimatch(url, path)); return allow; } }