import { Injectable, UnauthorizedException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import * as bcrypt from 'bcrypt'; import { User } from '../user/user.entity'; import { LoginDto } from './dto/login.dto'; import { JwtPayload } from './interfaces/jwt-payload.interface'; import { LoginResponse } from './interfaces/login-response.interface'; @Injectable() export class AuthService { constructor( @InjectRepository(User) private readonly userRepository: Repository, private readonly jwtService: JwtService, ) {} /** * 用户登录 */ async login(loginDto: LoginDto): Promise { // 根据用户名或邮箱查找用户 const user = await this.userRepository.findOne({ where: [ { username: loginDto.usernameOrEmail }, { email: loginDto.usernameOrEmail }, ], }); if (!user) { throw new UnauthorizedException('用户名或密码错误'); } // 检查用户状态 if (user.status !== 'active') { throw new UnauthorizedException('用户已被禁用'); } // 验证密码 const isPasswordValid = await bcrypt.compare( loginDto.password, user.passwordHash, ); if (!isPasswordValid) { throw new UnauthorizedException('用户名或密码错误'); } // 更新最后登录时间 user.lastLoginAt = new Date(); await this.userRepository.save(user); // 生成 JWT token const payload: JwtPayload = { sub: user.userId, username: user.username, email: user.email, role: user.role, }; const accessToken = this.jwtService.sign(payload); // 返回 token 和用户信息(排除密码) // eslint-disable-next-line @typescript-eslint/no-unused-vars const { passwordHash, ...userWithoutPassword } = user; return { accessToken, user: userWithoutPassword, }; } }