import { Inject, Injectable } from "@nestjs/common"; import { AccountRepo } from "./account.repo"; import * as DTO from './dto'; import { MailerService } from "src/util/mailer/mailer.service"; import { Generator } from "src/util/generator"; import Redis from "ioredis"; import { Converter } from "src/util/converter"; import { AuthService } from "src/middleware/auth/auth.service"; @Injectable() export class AccountService { constructor( private readonly accountRepo: AccountRepo , private readonly mailerService: MailerService , private readonly authService: AuthService , @Inject("REDIS") private readonly redis: Redis ) {} async checkDuplication(data: DTO.CheckDuplicationRequest): Promise { const { type, value } = data; const count = await this.accountRepo.checkIdExists(type, value); return { isDuplicated: count > 0, success: true }; } async sendVerificationCode(data: DTO.SendEmailVerificationCodeRequest): Promise { const { email } = data; const code = Generator.getVerificationCode(); const html = `

Your verification code is: ${code}

`; const result = await this.mailerService.sendMail(email, " 이메일 인증 코드", html); if (result.rejected.length > 0) { return { success: false, error: result.response } } else { await this.redis.set(`verify:${email}`, code, 'EX', 600); return { success: true, message: "이메일 발송 완료" }; } } async verifyCode(data: DTO.VerifyEmailVerificationCodeRequest): Promise { const { email, code } = data; const storedCode = await this.redis.get(`verify:${email}`); if (!storedCode) { return { verified: false, success: true, error: '잘못된 이메일이거나 코드가 만료되었습니다.'}; } if (storedCode !== code) { return { verified: false, success: true, error: "잘못된 코드입니다." }; } await this.redis.del(`verify:${email}`); return { verified: true, success: true, message: "이메일 인증이 완료되었습니다." }; } async signup(data: DTO.SignupRequest): Promise { const { accountId, name, nickname, email, password } = data; const hashedPassword = Converter.getHashedPassword(password); const result = await this.accountRepo.signup(accountId, name, nickname, email, hashedPassword); if (result.rowCount) { return { success: true, message: "회원가입이 완료되었습니다." }; } else { return { success: false, error: "회원가입에 실패하였습니다." }; } } async login(data: DTO.LoginRequest): Promise { const { type, id, password } = data; const queryResult = await this.accountRepo.login(type, id); const typeValue = type === 'email' ? '이메일' : '아이디'; console.log(queryResult); if (!queryResult || (queryResult.length < 1)) { return { success: false, message: `존재하지 않는 ${typeValue} 입니다.` }; } const hashedPassword = queryResult[0].password; const isPasswordMatch = Converter.comparePassword(password, hashedPassword); if (!isPasswordMatch) { return { success: false, message: `비밀번호가 맞지 않습니다.` }; } { const { id, accountId, status, isDeleted, birthday } = queryResult[0]; const payload = { id, accountId, status, isDeleted, birthday }; const { accessToken, refreshToken } = this.authService.generateTokens(payload); return { success: true, accessToken: accessToken, refreshToken: refreshToken }; } } async refreshAccessToken(id: string): Promise { const { accessToken, refreshToken } = this.authService.refreshTokens(id); return { accessToken: accessToken, refreshToken: refreshToken, success: true }; } async sendResetPasswordCode(data: DTO.SendResetPasswordCodeRequest): Promise { const { email } = data; const count = await this.accountRepo.checkIdExists('email', email); if (count === 0) { return { success: false, error: "찾을 수 없는 사용자" }; } const code = Generator.getResetPasswordCode(); const html = `

Your Password Reset Code is: ${code}

` + `

Please Enter this code in 5 minutes.

`; const result = await this.mailerService.sendMail(email, " 비밀번호 초기화 코드", html); if (result.rejected.length > 0) { return { success: false, error: result.response }; } await this.redis.set(`resetPassword:${email}`, code, 'EX', 300); return { success: true, message: "비밀번호 초기화 코드 발송 완료" }; } async verifyResetPasswordCode(data: DTO.VerifyResetPasswordCodeRequest): Promise { const { email, code } = data; const storedCode = await this.redis.get(`resetPassword:${email}`); if (!storedCode) { return { success: false, verified: false, error: "잘못된 이메일이거나 코드가 만료되었습니다." }; } if (storedCode !== code) { return { success: false, verified: false, error: "잘못된 코드입니다." }; } await this.redis.del(`resetPassword:${email}`); return { success: true, verified: true, message: "비밀번호 초기화 코드 인증 완료" }; } async resetPassword(data: DTO.ResetPasswordRequest): Promise { const { email, password } = data; const hashedPassword = Converter.getHashedPassword(password); const result = await this.accountRepo.updatePassword('email', email, hashedPassword); if (!result.rowCount || result.rowCount === 0) { return { success: false, error: "비밀번호 초기화 실패" }; } return { success: true, message: "비밀번호 초기화 성공" }; } }