From ccfdfd1361c866dc014078d9eb8af82e902cba67 Mon Sep 17 00:00:00 2001 From: HOJUN Date: Mon, 30 Oct 2023 19:03:14 +0900 Subject: [PATCH 1/2] Style: to register-user.dto.ts --- src/auth/auth.controller.ts | 2 +- src/user/dto/{registerUserDto.ts => register-user.dto.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/user/dto/{registerUserDto.ts => register-user.dto.ts} (100%) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 4177ff8..a424e80 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -16,7 +16,7 @@ import { JwtAuthGuard } from './guards/jwt-auth.guard'; import { Response } from 'express'; import { GetUser } from './decorators/user.decorator'; import { User } from 'src/user/schema/user.schema'; -import { RegisterUserDto } from 'src/user/dto/registerUserDto'; +import { RegisterUserDto } from 'src/user/dto/register-user.dto'; @ApiTags('auth') @Controller('auth') diff --git a/src/user/dto/registerUserDto.ts b/src/user/dto/register-user.dto.ts similarity index 100% rename from src/user/dto/registerUserDto.ts rename to src/user/dto/register-user.dto.ts From 380989c1905e52c7bc04a5247a4cc90835ad9f43 Mon Sep 17 00:00:00 2001 From: HOJUN Date: Mon, 30 Oct 2023 20:41:08 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9D=B8=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to: #36 --- src/auth/auth.controller.ts | 31 +++++++++-------- src/auth/auth.service.ts | 54 ++++++++++++++++++++++++----- src/auth/types/verification.data.ts | 7 ++++ 3 files changed, 68 insertions(+), 24 deletions(-) create mode 100644 src/auth/types/verification.data.ts diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index a424e80..2613b16 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -109,20 +109,21 @@ export class AuthController { @Post('register') async Register( @Body(ValidationPipe) registerUserDto: RegisterUserDto, - @Res() res: Response, - ) { - try { - const createdUser = await this.authService.register(registerUserDto); - const token = await this.authService.login(createdUser); - res.status(HttpStatus.CREATED).json({ token }); - } catch (error) { - if (error.status === HttpStatus.CONFLICT) { - res.status(HttpStatus.CONFLICT).json({ message: error.message }); - } else { - res - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .json({ message: '서버 오류' }); - } - } + ): Promise { + await this.authService.register(registerUserDto); + } + + @Post('verify') + @ApiBody({ + schema: { + type: 'object', + properties: { + email: { type: 'string', example: 'example@example.com' }, + code: { type: 'string', example: '123456' }, + }, + }, + }) + async verify(@Body() body: { email: string; code: string }): Promise { + return this.authService.verify(body.email, body.code); } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index b684c8d..a59ee7e 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -4,17 +4,21 @@ import { Res, HttpStatus, UnauthorizedException, + NotFoundException, + BadRequestException, } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; -import { RegisterUserDto } from 'src/user/dto/registerUserDto'; import { User } from 'src/user/schema/user.schema'; import * as bcrypt from 'bcryptjs'; import { ConfigService } from '@nestjs/config'; +import { RegisterUserDto } from 'src/user/dto/register-user.dto'; +import { VerificationData } from './types/verification.data'; @Injectable() export class AuthService { + private verificationCodes: Map = new Map(); constructor( private jwtService: JwtService, private readonly configService: ConfigService, @@ -45,14 +49,16 @@ export class AuthService { async validateUser(email: string, pass: string): Promise { const user = await this.userModel.findOne({ email }); - if (user && user.password === pass) { - //const isMatch = await bcrypt.compare(pass, user.password);와 같은 비밀번호 검증 로직 추가 - return user; + if (user) { + const isMatch = await bcrypt.compare(pass, user.password); + if (!isMatch) { + return null; + } } - return null; + return user; } - async register(registerUserDto: RegisterUserDto): Promise { + async register(registerUserDto: RegisterUserDto): Promise { const { email, password, connectedServices } = registerUserDto; const existingUser = await this.userModel.findOne({ email }); if (existingUser) { @@ -60,13 +66,43 @@ export class AuthService { } const hash = await bcrypt.hash(password, 10); - const createdUser = new this.userModel({ + const verificationCode = Math.random().toString().slice(-6); + const expires = Date.now() + 5 * 60 * 1000; + + this.verificationCodes.set(email, { email, - hash, + password: hash, connectedServices, + code: verificationCode, + expires, + }); + + // 이메일로 전송하는 로직 추가 예정 + console.log(`Verification code for ${email}: ${verificationCode}`); + } + + async verify(email: string, code: string): Promise { + const storedData = this.verificationCodes.get(email); + if (!storedData) { + throw new NotFoundException('가입하지 않은 이메일입니다.'); + } + if (Date.now() > storedData.expires) { + throw new BadRequestException('인증번호가 만료되었습니다.'); + } + if (storedData.code !== code) { + throw new BadRequestException('인증번호가 일치하지 않습니다.'); + } + + const createdUser = new this.userModel({ + email: storedData.email, + password: storedData.password, + connectedServices: storedData.connectedServices, }); await createdUser.save(); - return createdUser; + + // 인증이 완료되었으므로 저장된 데이터 삭제 + this.verificationCodes.delete(email); + return; } /** diff --git a/src/auth/types/verification.data.ts b/src/auth/types/verification.data.ts new file mode 100644 index 0000000..f0e5780 --- /dev/null +++ b/src/auth/types/verification.data.ts @@ -0,0 +1,7 @@ +export interface VerificationData { + email: string; + password: string; + connectedServices: any[]; // 실제 타입에 맞게 변경해주세요. + code: string; + expires: number; +}