// 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; @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 { 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 } }) ); } }