zksu
/
API
forked from yoone/API
1
0
Fork 0
API/src/service/user.service.ts

122 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/service/user.service.ts
import { Body, httpError, Inject, Provide } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcryptjs';
import { JwtService } from '@midwayjs/jwt';
import { User } from '../entity/user.entity';
import { LoginResDTO } from '../dto/user.dto';
import { plainToInstance } from 'class-transformer';
import { MailService } from './mail.service';
import { AuthCodeService } from './authCode.service';
import { DeviceWhitelistService } from './deviceWhitelist.service';
@Provide()
export class UserService {
@InjectEntityModel(User)
userModel: Repository<User>;
@Inject()
jwtService: JwtService;
@Inject()
mailService: MailService;
@Inject()
authCodeService: AuthCodeService;
@Inject()
deviceWhitelistService: DeviceWhitelistService;
async requestAuthCode(deviceId: string) {
const code = await this.authCodeService.generateCode(deviceId);
await this.mailService.sendMail(
'info@canpouches.com',
'Your Login Authorization Code',
`Your authorization code is: ${code}, valid for 10 minutes.`
);
}
async login(@Body() body): Promise<LoginResDTO> {
const { username, password, deviceId, authCode } = body;
const user = await this.userModel.findOne({
where: { username, isActive: true },
});
if (!user || !(await bcrypt.compare(password, user.password))) {
throw new Error('用户名或者密码错误');
}
const isWhite = await this.deviceWhitelistService.isWhitelisted(deviceId);
if (!isWhite) {
if (!authCode) {
await this.requestAuthCode(deviceId);
const err = new httpError.BadRequestError('非白名单设备请填写验证码');
(err as any).code = 10001; // 添加业务错误码
throw err;
}
const valid = await this.authCodeService.verifyCode(deviceId, authCode);
if (!valid) {
throw new Error('验证码错误');
}
// 校验通过后,将设备加入白名单
await this.deviceWhitelistService.addToWhitelist(deviceId);
}
// 生成 JWT包含角色和权限信息
const token = await this.jwtService.sign({
id: user.id,
deviceId,
username: user.username,
});
return {
token, //role: user.role,
username: user.username,
userId: user.id,
permissions: user.permissions,
};
}
async addUser(username: string, password: string) {
const existingUser = await this.userModel.findOne({
where: { username },
});
if (existingUser) {
throw new Error('用户已存在');
}
const hashedPassword = await bcrypt.hash(password, 10);
const user = this.userModel.create({
username,
password: hashedPassword,
});
return this.userModel.save(user);
}
async listUsers(current: number, pageSize: number) {
const [items, total] = await this.userModel.findAndCount({
skip: (current - 1) * pageSize,
take: pageSize,
});
return { items, total, current, pageSize };
}
async toggleUserActive(userId: number, isActive: boolean) {
const user = await this.userModel.findOne({ where: { id: userId } });
if (!user) {
throw new Error('User not found');
}
user.isActive = isActive;
return this.userModel.save(user);
}
async getUser(userId: number) {
return plainToInstance(
User,
await this.userModel.findOne({ where: { id: userId } })
);
}
}