diff --git a/backend/package-lock.json b/backend/package-lock.json index 01c4f7d..2a61ef9 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -18,9 +18,11 @@ "@nestjs/platform-express": "^9.0.0", "@nestjs/typeorm": "^9.0.1", "@types/cookie-parser": "^1.4.3", + "@types/passport": "^1.0.11", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", "cookie-parser": "^1.4.6", + "passport": "^0.6.0", "passport-jwt": "^4.0.0", "pg": "^8.8.0", "reflect-metadata": "^0.1.13", @@ -2128,7 +2130,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.11.tgz", "integrity": "sha512-pz1cx9ptZvozyGKKKIPLcVDVHwae4hrH5d6g5J+DkMRRjR3cVETb4jMabhXAUbg3Ov7T22nFHEgaK2jj+5CBpw==", - "dev": true, "dependencies": { "@types/express": "*" } @@ -6915,7 +6916,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", - "peer": true, "dependencies": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -6995,8 +6995,7 @@ "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "peer": true + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "node_modules/pg": { "version": "8.8.0", @@ -10801,7 +10800,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.11.tgz", "integrity": "sha512-pz1cx9ptZvozyGKKKIPLcVDVHwae4hrH5d6g5J+DkMRRjR3cVETb4jMabhXAUbg3Ov7T22nFHEgaK2jj+5CBpw==", - "dev": true, "requires": { "@types/express": "*" } @@ -14403,7 +14401,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", - "peer": true, "requires": { "passport-strategy": "1.x.x", "pause": "0.0.1", @@ -14461,8 +14458,7 @@ "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==", - "peer": true + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "pg": { "version": "8.8.0", diff --git a/backend/package.json b/backend/package.json index b211211..e724bf6 100644 --- a/backend/package.json +++ b/backend/package.json @@ -30,9 +30,11 @@ "@nestjs/platform-express": "^9.0.0", "@nestjs/typeorm": "^9.0.1", "@types/cookie-parser": "^1.4.3", + "@types/passport": "^1.0.11", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", "cookie-parser": "^1.4.6", + "passport": "^0.6.0", "passport-jwt": "^4.0.0", "pg": "^8.8.0", "reflect-metadata": "^0.1.13", diff --git a/backend/src/auth/dto/user-data.dto.ts b/backend/src/auth/dto/user-data.dto.ts index bfea330..3874c41 100644 --- a/backend/src/auth/dto/user-data.dto.ts +++ b/backend/src/auth/dto/user-data.dto.ts @@ -15,6 +15,9 @@ export class UserDataDto { @IsNotEmpty() @IsString() social: socialPlatform; + + @IsString() + nickname: string; } export class UserDataFromSocialDto { diff --git a/backend/src/auth/jwt-auth.strategy.ts b/backend/src/auth/jwt-auth.strategy.ts index ab60f64..3dd6b05 100644 --- a/backend/src/auth/jwt-auth.strategy.ts +++ b/backend/src/auth/jwt-auth.strategy.ts @@ -1,13 +1,11 @@ import { ExtractJwt, Strategy } from 'passport-jwt'; import { PassportStrategy } from '@nestjs/passport'; import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { User } from './entity/user.entity'; -import { UserService } from './user.service'; import { UserDataDto } from './dto/user-data.dto'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy, 'criticalGuard') { - constructor(private userService: UserService) { + constructor() { super({ jwtFromRequest: ExtractJwt.fromExtractors([ request => { @@ -19,16 +17,15 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'criticalGuard') { }); } - // db 참조 하는 guard - async validate(payload: UserDataDto): Promise { - const user: User = await this.userService.findUser(payload); - - if (!user) { + // 빡빡한 가드 + async validate(payload: UserDataDto): Promise { + if (!payload.nickname) { throw new UnauthorizedException( '서버에 해당 유저가 존재하지 않습니다. 가입을 완료해주세요.' ); } - return true; + + return payload; } } @@ -46,7 +43,7 @@ export class JwtStrategy2 extends PassportStrategy(Strategy, 'looseGuard') { }); } - // db 참조 하지 않는 guard + // 느슨한 가드 async validate(payload: UserDataDto): Promise { return payload; } diff --git a/backend/src/auth/user.controller.ts b/backend/src/auth/user.controller.ts index 8f38cfa..c5b4b93 100644 --- a/backend/src/auth/user.controller.ts +++ b/backend/src/auth/user.controller.ts @@ -46,25 +46,27 @@ export class UserController { @Param('social') social: socialPlatform, @Res() res: Response ): Promise { + // 1단계 : 소셜에 유저 정보 받아오기 const accessToken = await this.authService.socialOauth(social, code); const userSocialProfile = await this.authService.socialProfileSearch( social, accessToken ); + // 우리 유저 인지 확인하기 const userData = await this.userService.findUser({ id: userSocialProfile.id, social: social, }); - // 탈퇴 감지 로직 - if (userData.deleted) { + if (userData && userData.deleted) { throw new UnauthorizedException('여길 어디 다시와.'); } const jwt = await this.authService.jwtTokenGenerator({ id: userSocialProfile.id, social, + nickname: userData?.nickname, }); res.cookie('accessToken', jwt.accessToken); @@ -79,20 +81,28 @@ export class UserController { @Post() @UseGuards(AuthGuard('looseGuard')) - signUp( + async signUp( @Body('signupData', ValidationPipe) signupData: signupDataDto, @Req() req: any, @Res() res: Response - ): void { + ) { const { id, social }: UserDataDto = req.user; // body안에 nickname, characterName FE에 전송 요청 - this.userService.createUser({ + await this.userService.createUser({ id, social, nickname: signupData['nickname'], characterName: signupData['characterName'], }); - res.redirect(process.env.CLIENT_URL); + + const jwt = await this.authService.jwtTokenGenerator({ + id, + social, + nickname: signupData['nickname'], + }); + console.log(jwt.accessToken); + res.cookie('accessToken', jwt.accessToken); + res.send(200); } @Get('/logout') @@ -100,15 +110,15 @@ export class UserController { res.cookie('accessToken', '', { maxAge: 0, }); - res.redirect(process.env.CLIENT_URL); + res.send(200); } @Delete() - @UseGuards(AuthGuard('looseGuard')) + @UseGuards(AuthGuard('criticalGuard')) deleteUser(@Req() req: any, @Res() res: Response) { - const { id, social }: UserDataDto = req.user; + const { id, social, nickname }: UserDataDto = req.user; - this.userService.deleteUser({ id, social }); - res.redirect(process.env.CLIENT_URL); + this.userService.deleteUser({ id, social, nickname }); + res.send(200); } } diff --git a/backend/src/auth/user.service.ts b/backend/src/auth/user.service.ts index e7b683f..9aa0419 100644 --- a/backend/src/auth/user.service.ts +++ b/backend/src/auth/user.service.ts @@ -1,4 +1,8 @@ -import { Injectable } from '@nestjs/common'; +import { + Injectable, + NotAcceptableException, + NotFoundException, +} from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { UserDataDto } from './dto/user-data.dto'; @@ -11,7 +15,11 @@ export class UserService { ) {} async createUser(signupData: any): Promise { - await this.userRepository.save(signupData); + try { + await this.userRepository.save(signupData); + } catch (e) { + throw new NotAcceptableException('닉네임이 중복됩니다.'); + } } async findUser(searchOptions: object): Promise { @@ -19,6 +27,12 @@ export class UserService { } async deleteUser(userDataToDelete: UserDataDto) { - await this.userRepository.update(userDataToDelete, { deleted: true }); + try { + await this.userRepository.update(userDataToDelete, { deleted: true }); + } catch (e) { + throw new NotFoundException( + '해당 유저를 찾을 수 없어 삭제할 수 없습니다.' + ); + } } }