215 lines
5.2 KiB
TypeScript
215 lines
5.2 KiB
TypeScript
import {
|
|
HttpException,
|
|
HttpStatus,
|
|
Inject,
|
|
Injectable,
|
|
UnauthorizedException,
|
|
} from '@nestjs/common';
|
|
import { CreateUserDto } from './dto/create-user.dto';
|
|
import { UpdateUserDto } from './dto/update-user.dto';
|
|
import { Prisma, SysUser } from '@prisma/client';
|
|
import { PrismaService } from '@/prisma/prisma.service';
|
|
import { QueryListDto } from './dto/query-list.dto';
|
|
import * as bcrypt from 'bcryptjs';
|
|
import { UpdatePasswordDto } from './dto/update-password.dto';
|
|
import { SkipAuth } from '@/common/decorators/skip-auth.decorator';
|
|
import { RedisGroup } from '@/common/enum';
|
|
import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager';
|
|
|
|
@Injectable()
|
|
@SkipAuth()
|
|
export class UserService {
|
|
constructor(
|
|
private readonly prisma: PrismaService,
|
|
@Inject(CACHE_MANAGER) private cacheManager: Cache,
|
|
) {}
|
|
|
|
async findOne(
|
|
params: Prisma.SysUserWhereUniqueInput,
|
|
): Promise<SysUser | null> {
|
|
return this.prisma.sysUser.findUnique({
|
|
where: params,
|
|
});
|
|
}
|
|
|
|
async create(dto: CreateUserDto) {
|
|
const userExists = await this.findOne({ account: dto.account });
|
|
if (userExists)
|
|
throw new HttpException('账号已存在!', HttpStatus.UNPROCESSABLE_ENTITY);
|
|
|
|
const passwordSalt = await bcrypt.genSalt();
|
|
const password = await bcrypt.hash(dto.password, passwordSalt);
|
|
const data = {
|
|
...dto,
|
|
passwordSalt,
|
|
password,
|
|
};
|
|
|
|
await this.prisma.sysUser.create({ data });
|
|
}
|
|
|
|
async findAll(dto: QueryListDto): Promise<QueryListResult> {
|
|
const { page, pageSize, account, status, name } = dto;
|
|
const query: Prisma.SysUserFindManyArgs = {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
account: true,
|
|
status: true,
|
|
gender: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
avatar: {
|
|
select: {
|
|
id: true,
|
|
path: true,
|
|
},
|
|
},
|
|
userRole: {
|
|
select: { roleId: true },
|
|
},
|
|
},
|
|
skip: pageSize * (page - 1),
|
|
take: pageSize,
|
|
where: {
|
|
...(account && { account: { contains: account } }),
|
|
...(!isNaN(status) && { status }),
|
|
...(name && { name: { contains: name } }),
|
|
},
|
|
};
|
|
|
|
const [list, count] = await this.prisma.$transaction([
|
|
this.prisma.sysUser.findMany(query),
|
|
this.prisma.sysUser.count({ where: query.where }),
|
|
]);
|
|
|
|
return {
|
|
page,
|
|
pageSize,
|
|
count,
|
|
list,
|
|
};
|
|
}
|
|
|
|
async findOneById(id: number) {
|
|
return this.prisma.sysUser.findUnique({
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
account: true,
|
|
status: true,
|
|
gender: true,
|
|
avatar: {
|
|
select: {
|
|
id: true,
|
|
path: true,
|
|
},
|
|
},
|
|
},
|
|
where: {
|
|
id,
|
|
},
|
|
});
|
|
}
|
|
|
|
async getUserInfo(id: number, isAdmin: boolean) {
|
|
const user = await this.prisma.sysUser.findUnique({
|
|
select: {
|
|
name: true,
|
|
gender: true,
|
|
account: true,
|
|
avatar: {
|
|
select: {
|
|
path: true,
|
|
},
|
|
},
|
|
createdAt: true,
|
|
},
|
|
where: {
|
|
id,
|
|
status: 1,
|
|
},
|
|
});
|
|
|
|
const query: Prisma.SysMenuFindManyArgs = { where: {} };
|
|
|
|
if (!isAdmin) {
|
|
query.where = {
|
|
sysMenuPermission: {
|
|
some: {
|
|
permission: {
|
|
sysRolePermission: {
|
|
some: { role: { sysUserRole: { some: { userId: id } } } },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
const menus = await this.prisma.sysMenu.findMany(query);
|
|
return {
|
|
...user,
|
|
menus,
|
|
};
|
|
}
|
|
|
|
async update(id: number, data: UpdateUserDto) {
|
|
const user = await this.findOne({ id });
|
|
if (!user)
|
|
throw new HttpException('修改失败,用户不存在!', HttpStatus.NOT_FOUND);
|
|
|
|
await this.prisma.$transaction(async (prisma) => {
|
|
await prisma.sysUser.update({
|
|
data,
|
|
where: { id },
|
|
});
|
|
|
|
// 禁用用户 删除token
|
|
if (data.status === 0) {
|
|
if (data.status === 0) {
|
|
const keys = await this.cacheManager.store.keys(
|
|
`${RedisGroup.JwtJti}:${id}:*`,
|
|
);
|
|
await this.cacheManager.store.mdel(...keys);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
async updatePassword(
|
|
id: number,
|
|
{ password, newPassword }: UpdatePasswordDto,
|
|
) {
|
|
const user = await this.findOne({ id });
|
|
if (!user)
|
|
throw new HttpException('修改失败,用户不存在!', HttpStatus.NOT_FOUND);
|
|
// 同时存在密码和新密码
|
|
const data: Partial<SysUser> = {};
|
|
|
|
const comparePasswordSalt = user.passwordSalt;
|
|
const comparePassword = await bcrypt.hash(password, comparePasswordSalt);
|
|
|
|
if (comparePassword !== user.password) {
|
|
throw new UnauthorizedException('密码错误,修改失败!');
|
|
} else {
|
|
data.passwordSalt = await bcrypt.genSalt();
|
|
data.password = await bcrypt.hash(newPassword, data.passwordSalt);
|
|
}
|
|
|
|
await this.prisma.sysUser.update({
|
|
data,
|
|
where: { id },
|
|
});
|
|
}
|
|
|
|
async remove(id: number) {
|
|
const user = await this.findOne({ id });
|
|
|
|
if (!user)
|
|
throw new HttpException('删除失败,用户不存在!', HttpStatus.NOT_FOUND);
|
|
|
|
await this.prisma.sysUser.delete({ where: { id } });
|
|
}
|
|
}
|