/** * 登录业务服务 * * 功能描述: * - 处理登录相关的业务逻辑和流程控制 * - 整合核心服务,提供完整的业务功能 * - 处理业务规则、数据格式化和错误处理 * * 职责分离: * - 专注于业务流程和规则实现 * - 调用核心服务完成具体功能 * - 为控制器层提供业务接口 * * @author moyin angjustinl * @version 1.0.0 * @since 2025-12-17 */ import { Injectable, Logger } from '@nestjs/common'; import { LoginCoreService, LoginRequest, RegisterRequest, GitHubOAuthRequest, PasswordResetRequest, AuthResult, VerificationCodeLoginRequest } from '../../../core/login_core/login_core.service'; import { Users } from '../../../core/db/users/users.entity'; /** * 登录响应数据接口 */ export interface LoginResponse { /** 用户信息 */ user: { id: string; username: string; nickname: string; email?: string; phone?: string; avatar_url?: string; role: number; created_at: Date; }; /** 访问令牌(实际应用中应生成JWT) */ access_token: string; /** 刷新令牌 */ refresh_token?: string; /** 是否为新用户 */ is_new_user?: boolean; /** 消息 */ message: string; } /** * 通用响应接口 */ export interface ApiResponse { /** 是否成功 */ success: boolean; /** 响应数据 */ data?: T; /** 消息 */ message: string; /** 错误代码 */ error_code?: string; } @Injectable() export class LoginService { private readonly logger = new Logger(LoginService.name); constructor( private readonly loginCoreService: LoginCoreService, ) {} /** * 用户登录 * * @param loginRequest 登录请求 * @returns 登录响应 */ async login(loginRequest: LoginRequest): Promise> { try { this.logger.log(`用户登录尝试: ${loginRequest.identifier}`); // 调用核心服务进行认证 const authResult = await this.loginCoreService.login(loginRequest); // 生成访问令牌(实际应用中应使用JWT) const accessToken = this.generateAccessToken(authResult.user); // 格式化响应数据 const response: LoginResponse = { user: this.formatUserInfo(authResult.user), access_token: accessToken, is_new_user: authResult.isNewUser, message: '登录成功' }; this.logger.log(`用户登录成功: ${authResult.user.username} (ID: ${authResult.user.id})`); return { success: true, data: response, message: '登录成功' }; } catch (error) { this.logger.error(`用户登录失败: ${loginRequest.identifier}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '登录失败', error_code: 'LOGIN_FAILED' }; } } /** * 用户注册 * * @param registerRequest 注册请求 * @returns 注册响应 */ async register(registerRequest: RegisterRequest): Promise> { try { this.logger.log(`用户注册尝试: ${registerRequest.username}`); // 调用核心服务进行注册 const authResult = await this.loginCoreService.register(registerRequest); // 生成访问令牌 const accessToken = this.generateAccessToken(authResult.user); // 格式化响应数据 const response: LoginResponse = { user: this.formatUserInfo(authResult.user), access_token: accessToken, is_new_user: true, message: '注册成功' }; this.logger.log(`用户注册成功: ${authResult.user.username} (ID: ${authResult.user.id})`); return { success: true, data: response, message: '注册成功' }; } catch (error) { this.logger.error(`用户注册失败: ${registerRequest.username}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '注册失败', error_code: 'REGISTER_FAILED' }; } } /** * GitHub OAuth登录 * * @param oauthRequest OAuth请求 * @returns 登录响应 */ async githubOAuth(oauthRequest: GitHubOAuthRequest): Promise> { try { this.logger.log(`GitHub OAuth登录尝试: ${oauthRequest.github_id}`); // 调用核心服务进行OAuth认证 const authResult = await this.loginCoreService.githubOAuth(oauthRequest); // 生成访问令牌 const accessToken = this.generateAccessToken(authResult.user); // 格式化响应数据 const response: LoginResponse = { user: this.formatUserInfo(authResult.user), access_token: accessToken, is_new_user: authResult.isNewUser, message: authResult.isNewUser ? 'GitHub账户绑定成功' : 'GitHub登录成功' }; this.logger.log(`GitHub OAuth成功: ${authResult.user.username} (ID: ${authResult.user.id})`); return { success: true, data: response, message: response.message }; } catch (error) { this.logger.error(`GitHub OAuth失败: ${oauthRequest.github_id}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : 'GitHub登录失败', error_code: 'GITHUB_OAUTH_FAILED' }; } } /** * 发送密码重置验证码 * * @param identifier 邮箱或手机号 * @returns 响应结果 */ async sendPasswordResetCode(identifier: string): Promise> { try { this.logger.log(`发送密码重置验证码: ${identifier}`); // 调用核心服务发送验证码 const result = await this.loginCoreService.sendPasswordResetCode(identifier); this.logger.log(`密码重置验证码已发送: ${identifier}`); // 根据是否为测试模式返回不同的状态和消息 by angjustinl 2025-12-17 if (result.isTestMode) { // 测试模式:验证码生成但未真实发送 return { success: false, // 测试模式下不算真正成功 data: { verification_code: result.code, is_test_mode: true }, message: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。', error_code: 'TEST_MODE_ONLY' }; } else { // 真实发送模式 return { success: true, data: { is_test_mode: false }, message: '验证码已发送,请查收' }; } } catch (error) { this.logger.error(`发送密码重置验证码失败: ${identifier}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '发送验证码失败', error_code: 'SEND_CODE_FAILED' }; } } /** * 重置密码 * * @param resetRequest 重置请求 * @returns 响应结果 */ async resetPassword(resetRequest: PasswordResetRequest): Promise { try { this.logger.log(`密码重置尝试: ${resetRequest.identifier}`); // 调用核心服务重置密码 await this.loginCoreService.resetPassword(resetRequest); this.logger.log(`密码重置成功: ${resetRequest.identifier}`); return { success: true, message: '密码重置成功' }; } catch (error) { this.logger.error(`密码重置失败: ${resetRequest.identifier}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '密码重置失败', error_code: 'RESET_PASSWORD_FAILED' }; } } /** * 修改密码 * * @param userId 用户ID * @param oldPassword 旧密码 * @param newPassword 新密码 * @returns 响应结果 */ async changePassword(userId: bigint, oldPassword: string, newPassword: string): Promise { try { this.logger.log(`修改密码尝试: 用户ID ${userId}`); // 调用核心服务修改密码 await this.loginCoreService.changePassword(userId, oldPassword, newPassword); this.logger.log(`修改密码成功: 用户ID ${userId}`); return { success: true, message: '密码修改成功' }; } catch (error) { this.logger.error(`修改密码失败: 用户ID ${userId}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '密码修改失败', error_code: 'CHANGE_PASSWORD_FAILED' }; } } /** * 发送邮箱验证码 * * @param email 邮箱地址 * @returns 响应结果 */ async sendEmailVerification(email: string): Promise> { try { this.logger.log(`发送邮箱验证码: ${email}`); // 调用核心服务发送验证码 const result = await this.loginCoreService.sendEmailVerification(email); this.logger.log(`邮箱验证码已发送: ${email}`); // 根据是否为测试模式返回不同的状态和消息 if (result.isTestMode) { // 测试模式:验证码生成但未真实发送 return { success: false, // 测试模式下不算真正成功 data: { verification_code: result.code, is_test_mode: true }, message: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。', error_code: 'TEST_MODE_ONLY' }; } else { // 真实发送模式 return { success: true, data: { is_test_mode: false }, message: '验证码已发送,请查收邮件' }; } } catch (error) { this.logger.error(`发送邮箱验证码失败: ${email}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '发送验证码失败', error_code: 'SEND_EMAIL_VERIFICATION_FAILED' }; } } /** * 验证邮箱验证码 * * @param email 邮箱地址 * @param code 验证码 * @returns 响应结果 */ async verifyEmailCode(email: string, code: string): Promise { try { this.logger.log(`验证邮箱验证码: ${email}`); // 调用核心服务验证验证码 const isValid = await this.loginCoreService.verifyEmailCode(email, code); if (isValid) { this.logger.log(`邮箱验证成功: ${email}`); return { success: true, message: '邮箱验证成功' }; } else { return { success: false, message: '验证码错误', error_code: 'INVALID_VERIFICATION_CODE' }; } } catch (error) { this.logger.error(`邮箱验证失败: ${email}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '邮箱验证失败', error_code: 'EMAIL_VERIFICATION_FAILED' }; } } /** * 重新发送邮箱验证码 * * @param email 邮箱地址 * @returns 响应结果 */ async resendEmailVerification(email: string): Promise> { try { this.logger.log(`重新发送邮箱验证码: ${email}`); // 调用核心服务重新发送验证码 const result = await this.loginCoreService.resendEmailVerification(email); this.logger.log(`邮箱验证码已重新发送: ${email}`); // 根据是否为测试模式返回不同的状态和消息 if (result.isTestMode) { // 测试模式:验证码生成但未真实发送 return { success: false, // 测试模式下不算真正成功 data: { verification_code: result.code, is_test_mode: true }, message: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。', error_code: 'TEST_MODE_ONLY' }; } else { // 真实发送模式 return { success: true, data: { is_test_mode: false }, message: '验证码已重新发送,请查收邮件' }; } } catch (error) { this.logger.error(`重新发送邮箱验证码失败: ${email}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '重新发送验证码失败', error_code: 'RESEND_EMAIL_VERIFICATION_FAILED' }; } } /** * 格式化用户信息 * * @param user 用户实体 * @returns 格式化的用户信息 */ private formatUserInfo(user: Users) { return { id: user.id.toString(), // 将bigint转换为字符串 username: user.username, nickname: user.nickname, email: user.email, phone: user.phone, avatar_url: user.avatar_url, role: user.role, created_at: user.created_at }; } /** * 生成访问令牌 * * @param user 用户信息 * @returns 访问令牌 */ private generateAccessToken(user: Users): string { // 实际应用中应使用JWT库生成真正的JWT令牌 // 这里仅用于演示,生成一个简单的令牌 const payload = { userId: user.id.toString(), username: user.username, role: user.role, timestamp: Date.now() }; // 简单的Base64编码(实际应用中应使用JWT) return Buffer.from(JSON.stringify(payload)).toString('base64'); } /** * 验证码登录 * * @param loginRequest 验证码登录请求 * @returns 登录响应 */ async verificationCodeLogin(loginRequest: VerificationCodeLoginRequest): Promise> { try { this.logger.log(`验证码登录尝试: ${loginRequest.identifier}`); // 调用核心服务进行验证码认证 const authResult = await this.loginCoreService.verificationCodeLogin(loginRequest); // 生成访问令牌 const accessToken = this.generateAccessToken(authResult.user); // 格式化响应数据 const response: LoginResponse = { user: this.formatUserInfo(authResult.user), access_token: accessToken, is_new_user: authResult.isNewUser, message: '验证码登录成功' }; this.logger.log(`验证码登录成功: ${authResult.user.username} (ID: ${authResult.user.id})`); return { success: true, data: response, message: '验证码登录成功' }; } catch (error) { this.logger.error(`验证码登录失败: ${loginRequest.identifier}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '验证码登录失败', error_code: 'VERIFICATION_CODE_LOGIN_FAILED' }; } } /** * 发送登录验证码 * * @param identifier 邮箱或手机号 * @returns 响应结果 */ async sendLoginVerificationCode(identifier: string): Promise> { try { this.logger.log(`发送登录验证码: ${identifier}`); // 调用核心服务发送验证码 const result = await this.loginCoreService.sendLoginVerificationCode(identifier); this.logger.log(`登录验证码已发送: ${identifier}`); // 根据是否为测试模式返回不同的状态和消息 if (result.isTestMode) { // 测试模式:验证码生成但未真实发送 return { success: false, // 测试模式下不算真正成功 data: { verification_code: result.code, is_test_mode: true }, message: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。', error_code: 'TEST_MODE_ONLY' }; } else { // 真实发送模式 return { success: true, data: { is_test_mode: false }, message: '验证码已发送,请查收' }; } } catch (error) { this.logger.error(`发送登录验证码失败: ${identifier}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '发送验证码失败', error_code: 'SEND_LOGIN_CODE_FAILED' }; } } /** * 调试验证码信息 * * @param email 邮箱地址 * @returns 调试信息 */ async debugVerificationCode(email: string): Promise { try { this.logger.log(`调试验证码信息: ${email}`); const debugInfo = await this.loginCoreService.debugVerificationCode(email); return { success: true, data: debugInfo, message: '调试信息获取成功' }; } catch (error) { this.logger.error(`获取验证码调试信息失败: ${email}`, error instanceof Error ? error.stack : String(error)); return { success: false, message: error instanceof Error ? error.message : '获取调试信息失败', error_code: 'DEBUG_VERIFICATION_CODE_FAILED' }; } } }