178 lines
5.3 KiB
TypeScript
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;
|
|
}
|
|
}
|