From f17fdbab864ced71fccbdaa5eef998536426ebe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=A0=EC=A0=95=EC=9A=A9?= Date: Mon, 20 Nov 2023 17:50:56 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20signupDto=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=ED=9B=84=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BackEnd/package-lock.json | 35 +++++++++++++++++++ BackEnd/package.json | 2 ++ BackEnd/src/auth/auth.controller.ts | 16 ++------- BackEnd/src/auth/auth.service.ts | 8 ++--- BackEnd/src/auth/dto/signup.dto.ts | 8 +++++ BackEnd/src/main.ts | 2 ++ .../src/profiles/entities/profiles.entity.ts | 10 ++++++ BackEnd/src/profiles/profiles.service.ts | 3 +- BackEnd/src/users/entities/users.entity.ts | 7 ++++ BackEnd/src/users/users.service.ts | 15 +++++--- 10 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 BackEnd/src/auth/dto/signup.dto.ts diff --git a/BackEnd/package-lock.json b/BackEnd/package-lock.json index 262d3bee..f99e978e 100755 --- a/BackEnd/package-lock.json +++ b/BackEnd/package-lock.json @@ -16,6 +16,8 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "mysql2": "^3.6.3", "nest-winston": "^1.9.4", "reflect-metadata": "^0.1.13", @@ -2244,6 +2246,11 @@ "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, + "node_modules/@types/validator": { + "version": "13.11.6", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.6.tgz", + "integrity": "sha512-HUgHujPhKuNzgNXBRZKYexwoG+gHKU+tnfPqjWXFghZAnn73JElicMkuSKJyLGr9JgyA8IgK7fj88IyA9rwYeQ==" + }, "node_modules/@types/yargs": { "version": "17.0.31", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", @@ -3345,6 +3352,21 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "node_modules/class-validator": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", + "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "dependencies": { + "@types/validator": "^13.7.10", + "libphonenumber-js": "^1.10.14", + "validator": "^13.7.0" + } + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -6532,6 +6554,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.10.49", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.49.tgz", + "integrity": "sha512-gvLtyC3tIuqfPzjvYLH9BmVdqzGDiSi4VjtWe2fAgSdBf0yt8yPmbNnRIHNbR5IdtVkm0ayGuzwQKTWmU0hdjQ==" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -9373,6 +9400,14 @@ "node": ">=10.12.0" } }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/BackEnd/package.json b/BackEnd/package.json index 6c7fdb97..e989e453 100755 --- a/BackEnd/package.json +++ b/BackEnd/package.json @@ -27,6 +27,8 @@ "@nestjs/platform-express": "^10.0.0", "@nestjs/swagger": "^7.1.16", "@nestjs/typeorm": "^10.0.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "mysql2": "^3.6.3", "nest-winston": "^1.9.4", "reflect-metadata": "^0.1.13", diff --git a/BackEnd/src/auth/auth.controller.ts b/BackEnd/src/auth/auth.controller.ts index ae6ff8f2..01f0eeba 100644 --- a/BackEnd/src/auth/auth.controller.ts +++ b/BackEnd/src/auth/auth.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, Headers, Post, UseGuards } from '@nestjs/common'; import { AuthService } from './auth.service'; import { RefreshTokenGuard } from './guard/bearerToken.guard'; +import { SignupDto } from './dto/signup.dto'; @Controller('auth') export class AuthController { @@ -8,20 +9,9 @@ export class AuthController { @Post('signup') signup( - @Body('userId') userId: string, - @Body('provider') provider: string, - @Body('nickname') nickname: string, - @Body('gender') gender: string, - @Body('birthdate') birthdate: Date, + @Body() body: SignupDto, ) { - return this.authService.registerWithUserIdAndProvider({ - userId, - provider - }, { - nickname, - gender, - birthdate, - }); + return this.authService.registerWithUserIdAndProvider(body); } @Post('token/access') diff --git a/BackEnd/src/auth/auth.service.ts b/BackEnd/src/auth/auth.service.ts index a58f5e30..a2172c39 100644 --- a/BackEnd/src/auth/auth.service.ts +++ b/BackEnd/src/auth/auth.service.ts @@ -4,6 +4,7 @@ import { ProfileModel } from 'src/profiles/entities/profiles.entity'; import { ProfilesService } from 'src/profiles/profiles.service'; import { UserModel } from 'src/users/entities/users.entity'; import { UsersService } from 'src/users/users.service'; +import { SignupDto } from './dto/signup.dto'; @Injectable() export class AuthService { @@ -43,11 +44,11 @@ export class AuthService { return existingUser } - async registerWithUserIdAndProvider(user: Pick, profile: Pick) { - if(await this.profilesService.existByNickname(profile.nickname)) { + async registerWithUserIdAndProvider(signupInfo: SignupDto) { + if(await this.profilesService.existByNickname(signupInfo.nickname)) { throw new BadRequestException("중복된 nickname 입니다.") } - const newUser = await this.usersService.createUser(user, profile); + const newUser = await this.usersService.createUser(signupInfo); return this.loginUser(newUser.profile.publicId); } @@ -74,7 +75,6 @@ export class AuthService { rotateToken(token: string, isRefreshToken: boolean) { const decoded = this.verifyToken(token); - if(decoded.type !== 'refresh') { throw new UnauthorizedException('토큰 재발급은 Refresh 토큰으로만 가능합니다.!'); } diff --git a/BackEnd/src/auth/dto/signup.dto.ts b/BackEnd/src/auth/dto/signup.dto.ts new file mode 100644 index 00000000..70b9ddac --- /dev/null +++ b/BackEnd/src/auth/dto/signup.dto.ts @@ -0,0 +1,8 @@ +import { IntersectionType, PickType } from "@nestjs/swagger"; +import { ProfileModel } from "src/profiles/entities/profiles.entity"; +import { UserModel } from "src/users/entities/users.entity"; + +class UserDto extends PickType(UserModel, ['userId', 'provider']) {} +class ProfileDto extends PickType(ProfileModel, ['nickname', 'gender', 'birthdate']) {} + +export class SignupDto extends IntersectionType(UserDto, ProfileDto) {} \ No newline at end of file diff --git a/BackEnd/src/main.ts b/BackEnd/src/main.ts index 55f91c27..39e38972 100755 --- a/BackEnd/src/main.ts +++ b/BackEnd/src/main.ts @@ -2,11 +2,13 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { SwaggerSetting } from './config/swagger.config'; import { winstonLogger } from './config/winston.config'; +import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: winstonLogger, }); + app.useGlobalPipes(new ValidationPipe); SwaggerSetting(app); await app.listen(3000); } diff --git a/BackEnd/src/profiles/entities/profiles.entity.ts b/BackEnd/src/profiles/entities/profiles.entity.ts index 0a788aa5..03b4f836 100644 --- a/BackEnd/src/profiles/entities/profiles.entity.ts +++ b/BackEnd/src/profiles/entities/profiles.entity.ts @@ -1,3 +1,4 @@ +import { IsDate, IsString } from 'class-validator'; import { PostModel } from 'src/posts/entities/posts.entity'; import { RecordModel } from 'src/records/entities/records.entity'; import { UserModel } from 'src/users/entities/users.entity'; @@ -18,12 +19,21 @@ export class ProfileModel { id: number; @Column({ unique: true }) + @IsString({ + message: 'nickname은 string 타입으로 입력해야합니다.', + }) nickname: string; @Column({ nullable: false }) + @IsString({ + message: 'gender는 string 타입으로 입력해야합니다.', + }) gender: string; @Column({ nullable: false }) + @IsDate({ + message: 'birthdate date 타입으로 입력해야합니다.', + }) birthdate: Date; @CreateDateColumn() diff --git a/BackEnd/src/profiles/profiles.service.ts b/BackEnd/src/profiles/profiles.service.ts index 3a0c5e58..07dbb6b4 100644 --- a/BackEnd/src/profiles/profiles.service.ts +++ b/BackEnd/src/profiles/profiles.service.ts @@ -16,7 +16,7 @@ export class ProfilesService { publicId, } }); - + return profile; } @@ -26,7 +26,6 @@ export class ProfilesService { nickname, } }); - if(nicknameExists) { return true; } diff --git a/BackEnd/src/users/entities/users.entity.ts b/BackEnd/src/users/entities/users.entity.ts index 1cc00a63..5eec9b76 100644 --- a/BackEnd/src/users/entities/users.entity.ts +++ b/BackEnd/src/users/entities/users.entity.ts @@ -6,15 +6,22 @@ import { JoinColumn, } from 'typeorm'; import { ProfileModel } from 'src/profiles/entities/profiles.entity'; +import { IsString } from 'class-validator'; @Entity() export class UserModel { @PrimaryGeneratedColumn() id: number; @Column() + @IsString({ + message: 'userId는 string 타입을 입력해야합니다.' + }) userId: string; @Column() + @IsString({ + message: 'provider는 string 타입을 입력해야합니다.' + }) provider: string; @OneToOne(() => ProfileModel, (profile) => profile.user, { diff --git a/BackEnd/src/users/users.service.ts b/BackEnd/src/users/users.service.ts index bfd1701d..cfdaa130 100644 --- a/BackEnd/src/users/users.service.ts +++ b/BackEnd/src/users/users.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { UserModel } from './entities/users.entity'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; -import { ProfileModel } from 'src/profiles/entities/profiles.entity'; +import { SignupDto } from 'src/auth/dto/signup.dto'; @Injectable() export class UsersService { @@ -11,11 +11,16 @@ export class UsersService { private readonly usersRepository: Repository ){} - async createUser(user: Pick, profile: Pick) { + async createUser(singupInfo: SignupDto) { + const profile = { + nickname: singupInfo.nickname, + gender: singupInfo.gender, + birthdate: singupInfo.birthdate, + } const userObj = this.usersRepository.create({ - userId: user.userId, - provider: user.provider, - profile, + userId: singupInfo.userId, + provider: singupInfo.provider, + profile }) const newUesr = await this.usersRepository.save(userObj);