monorepo-microservice-rbac/apps/services/cert/authorize/src/rbac/rbac.service.ts
2023-08-27 14:37:59 +08:00

178 lines
5.3 KiB
TypeScript

// 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<Permission>,
@InjectRepository(User) private userRepository: Repository<User>,
@InjectRepository(Role) private roleRepository: Repository<Role>,
) {}
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;
}
}