Skip to content

Commit

Permalink
Merge pull request #49 from modern-agile-team/feature/board-user
Browse files Browse the repository at this point in the history
Refactor(2swo/board-user) 유저 아이디 토큰값에서 받아오기
  • Loading branch information
2swo authored Oct 19, 2023
2 parents 2e89afb + a7fa0a8 commit 359c0f3
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 54 deletions.
64 changes: 50 additions & 14 deletions src/auth/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { AuthService } from '../services/auth.service';
import { BadRequestException, Controller, Delete, Get, Headers, Post, Query, Res } from '@nestjs/common';
import {
BadRequestException,
Controller,
Delete,
Get,
Headers,
Post,
Query,
Res,
} from '@nestjs/common';
import { S3Service } from 'src/common/s3/s3.service';
import { TokenService } from '../services/token.service';
import { ApiTags } from '@nestjs/swagger';
Expand All @@ -18,7 +27,7 @@ export class AuthController {
constructor(
private readonly authService: AuthService,
private tokenService: TokenService,
private s3Service: S3Service
private s3Service: S3Service,
) {}

@ApiNaverLogin()
Expand All @@ -27,12 +36,18 @@ export class AuthController {
if (!code) {
throw new BadRequestException('인가코드가 없습니다.');
}

const { userId, naverAccessToken, naverRefreshToken } = await this.authService.naverLogin(code);

const { userId, naverAccessToken, naverRefreshToken } =
await this.authService.naverLogin(code);
const accessToken = await this.tokenService.createAccessToken(userId);
const refreshToken = await this.tokenService.createRefreshToken(userId);

await this.tokenService.saveTokens(userId, refreshToken, naverAccessToken, naverRefreshToken);
await this.tokenService.saveTokens(
userId,
refreshToken,
naverAccessToken,
naverRefreshToken,
);

return res.json({ accessToken, refreshToken });
}
Expand All @@ -44,18 +59,27 @@ export class AuthController {
throw new BadRequestException('인가코드가 없습니다.');
}

const { userId, kakaoAccessToken, kakaoRefreshToken } = await this.authService.kakaoLogin(code);
const { userId, kakaoAccessToken, kakaoRefreshToken } =
await this.authService.kakaoLogin(code);
const accessToken = await this.tokenService.createAccessToken(userId);
const refreshToken = await this.tokenService.createRefreshToken(userId);

await this.tokenService.saveTokens(userId, refreshToken, kakaoAccessToken, kakaoRefreshToken);
await this.tokenService.saveTokens(
userId,
refreshToken,
kakaoAccessToken,
kakaoRefreshToken,
);

return res.json({ accessToken, refreshToken });
}

@ApiNewAccessToken()
@Get('new-access-token')
async newAccessToken(@Headers('refresh_token') refreshToken: string, @Res() res) {
async newAccessToken(
@Headers('refresh_token') refreshToken: string,
@Res() res,
) {
const userId = await this.tokenService.decodeToken(refreshToken);
const newAccessToken = await this.tokenService.createAccessToken(userId);
return res.json({ accessToken: newAccessToken });
Expand All @@ -65,18 +89,26 @@ export class AuthController {
@Post('kakao/logout')
async kakaoLogout(@Headers('access_token') accessToken: string) {
const userId = await this.tokenService.decodeToken(accessToken);
const { kakaoAccessToken, kakaoRefreshToken } = await this.tokenService.getUserTokens(userId)[0];
const { kakaoAccessToken, kakaoRefreshToken } =
await this.tokenService.getUserTokens(userId)[0];
await this.tokenService.deleteTokens(userId);
return await this.authService.kakaoLogout(kakaoAccessToken, kakaoRefreshToken);
return await this.authService.kakaoLogout(
kakaoAccessToken,
kakaoRefreshToken,
);
}

@ApiKakaoUnlink()
@Post('kakao/unlink')
async kakaoUnlink(@Headers('access_token') accessToken: string) {
const userId = await this.tokenService.decodeToken(accessToken);
const { kakaoAccessToken, kakaoRefreshToken } = await this.tokenService.getUserTokens(userId)[0];
const { kakaoAccessToken, kakaoRefreshToken } =
await this.tokenService.getUserTokens(userId)[0];
await this.tokenService.deleteTokens(userId);
return await this.authService.kakaoUnlink(kakaoAccessToken, kakaoRefreshToken);
return await this.authService.kakaoUnlink(
kakaoAccessToken,
kakaoRefreshToken,
);
}

@ApiNaverLogout()
Expand All @@ -90,9 +122,13 @@ export class AuthController {
@Post('naver/unlink')
async naverUnlink(@Headers('access_token') accessToken: string) {
const userId = await this.tokenService.decodeToken(accessToken);
const { naverAccessToken, naverRefreshToken } = await this.tokenService.getUserTokens(userId)[0];
const { naverAccessToken, naverRefreshToken } =
await this.tokenService.getUserTokens(userId)[0];
await this.tokenService.deleteTokens(userId);
return await this.authService.naverUnlink(naverAccessToken, naverRefreshToken);
return await this.authService.naverUnlink(
naverAccessToken,
naverRefreshToken,
);
}

@ApiDeleteAccount()
Expand Down
78 changes: 54 additions & 24 deletions src/auth/services/token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import axios from 'axios';

@Injectable()
export class TokenService {
constructor(
private readonly tokenRepository: TokenRepository,
) {}
constructor(private readonly tokenRepository: TokenRepository) {}

async getUserTokens(userId: number) {
const getUserTokens = await this.tokenRepository.getUserTokens(userId);
Expand All @@ -17,13 +15,28 @@ export class TokenService {
return getUserTokens;
}

async saveTokens(userId: number, refreshToken: string, socialAccessToken: string, socialRefreshToken: string) {
async saveTokens(
userId: number,
refreshToken: string,
socialAccessToken: string,
socialRefreshToken: string,
) {
const tokens = await this.tokenRepository.getUserTokens(userId);

if (tokens.length > 0) {
return await this.tokenRepository.updateTokens(userId, refreshToken, socialAccessToken, socialRefreshToken);
return await this.tokenRepository.updateTokens(
userId,
refreshToken,
socialAccessToken,
socialRefreshToken,
);
}
return await this.tokenRepository.saveTokens(userId, refreshToken, socialAccessToken, socialRefreshToken);
return await this.tokenRepository.saveTokens(
userId,
refreshToken,
socialAccessToken,
socialRefreshToken,
);
}

async checkValidKakaoToken(accessToken: string) {
Expand All @@ -38,7 +51,10 @@ export class TokenService {
return (await axios.get(kakaoUnlinkUrl, kakaoUnlinkHeader)).status;
} catch (error) {
console.error('카카오 토큰 유효성 검사 오류:', error);
throw new HttpException('카카오 토큰 유효성 검사 오류', HttpStatus.FORBIDDEN);
throw new HttpException(
'카카오 토큰 유효성 검사 오류',
HttpStatus.FORBIDDEN,
);
}
}

Expand All @@ -56,7 +72,8 @@ export class TokenService {
refresh_token: refreshToken,
};

return (await axios.post(kakaoTokenUrl, kakaoTokenData, kakaoTokenHeader)).data;
return (await axios.post(kakaoTokenUrl, kakaoTokenData, kakaoTokenHeader))
.data;
} catch (error) {
console.error('카카오 토큰 갱신 오류:', error);
return false;
Expand All @@ -72,9 +89,7 @@ export class TokenService {
},
};
return (await axios.get(naverUnlinkUrl, naverUnlinkHeader)).status;
} catch (error) {

}
} catch (error) {}
}

async getNewNaverToken(refreshToken: string) {
Expand All @@ -97,7 +112,7 @@ export class TokenService {
async deleteTokens(userId: number) {
try {
await this.tokenRepository.deleteTokens(userId);

return { message: '토큰 삭제 성공' };
} catch (error) {
throw new HttpException('토큰을 찾을 수 없습니다.', HttpStatus.NOT_FOUND);
Expand All @@ -113,19 +128,34 @@ export class TokenService {
const userToken = await this.tokenRepository.getUserTokens(userId);
const dbRefreshToken = userToken[0].refreshToken;
if (token !== dbRefreshToken) {
throw new HttpException('토큰을 찾을 수 없습니다.', HttpStatus.NOT_FOUND);
throw new HttpException(
'토큰을 찾을 수 없습니다.',
HttpStatus.NOT_FOUND,
);
}
}
return { message: "유효한 토큰입니다." };
return { message: '유효한 토큰입니다.' };
} catch (error) {
if (error.message == 'jwt expired') {
throw new HttpException('만료된 토큰입니다.', HttpStatus.FORBIDDEN);
} else if (error.message == 'invalid token' || error.message == 'invalid signature') {
throw new HttpException('유효하지 않은 토큰입니다.', HttpStatus.UNAUTHORIZED);
} else if (
error.message == 'invalid token' ||
error.message == 'invalid signature'
) {
throw new HttpException(
'유효하지 않은 토큰입니다.',
HttpStatus.UNAUTHORIZED,
);
} else if (error.message == 'jwt must be provided') {
throw new HttpException('토큰이 제공되지 않았습니다.', HttpStatus.LENGTH_REQUIRED);
throw new HttpException(
'토큰이 제공되지 않았습니다.',
HttpStatus.LENGTH_REQUIRED,
);
} else {
throw new HttpException('토큰 검증에 실패했습니다.', HttpStatus.BAD_REQUEST);
throw new HttpException(
'토큰 검증에 실패했습니다.',
HttpStatus.BAD_REQUEST,
);
}
}
}
Expand All @@ -140,9 +170,9 @@ export class TokenService {
async createAccessToken(userId: number) {
const jwtSecretKey = process.env.JWT_SECRET_KEY;
const payload = {
sub: "accessToken",
sub: 'accessToken',
userId,
exp: Math.floor(Date.now() / 1000) + (60 * 60), // 1시간
exp: Math.floor(Date.now() / 1000) + 60 * 60, // 1시간
};

const accessToken = jwt.sign(payload, jwtSecretKey);
Expand All @@ -153,9 +183,9 @@ export class TokenService {
async createRefreshToken(userId: number) {
const jwtSecretKey = process.env.JWT_SECRET_KEY;
const payload = {
sub: "refreshToken",
sub: 'refreshToken',
userId,
exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24 * 7), // 7일
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7, // 7일
};
const refreshToken = jwt.sign(payload, jwtSecretKey);

Expand All @@ -165,7 +195,7 @@ export class TokenService {
async newAccessToken(refreshToken: string) {
const jwtSecretKey = process.env.JWT_SECRET_KEY;
const payload = jwt.verify(refreshToken, jwtSecretKey);

const userId = payload['userId'];
const newAccessToken = await this.createAccessToken(userId);
return newAccessToken;
Expand Down
24 changes: 17 additions & 7 deletions src/boards/controllers/Boards.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
UploadedFile,
UseInterceptors,
Query,
Headers,
} from '@nestjs/common';
import { BoardsService } from '../services/Boards.service';
import { Board } from '../entities/board.entity';
Expand All @@ -17,17 +18,23 @@ import { BoardImagesService } from '../services/BoardImage.service';
import { FileInterceptor } from '@nestjs/platform-express';
import { BoardResponseDTO } from '../dto/boards.response.dto';
import { CreateBoardImageDto } from '../dto/create.board-image.dto';
import { TokenService } from 'src/auth/services/token.service';

@Controller('boards')
export class BoardsController {
constructor(
private readonly boardsService: BoardsService,
private readonly boardImagesService: BoardImagesService,
private tokenService: TokenService,
) {}

@Post()
async create(@Body() createBoardDto: CreateBoardDto): Promise<Board> {
return this.boardsService.create(createBoardDto);
async create(
@Headers('accessToken') accessToken: string,
@Body() createBoardDto: CreateBoardDto,
): Promise<Board> {
const userId = await this.tokenService.decodeToken(accessToken);
return await this.boardsService.create(createBoardDto, userId);
}

@Post(':boardId/images')
Expand All @@ -36,22 +43,22 @@ export class BoardsController {
@Param('boardId') boardId: number,
@UploadedFile() file: Express.Multer.File,
): Promise<CreateBoardImageDto> {
return this.boardImagesService.createBoardImages(boardId, file);
return await this.boardImagesService.createBoardImages(boardId, file);
}

@Get()
async findPageBoards(
@Query('page') page = 1,
@Query('limit') limit = 30,
): Promise<BoardResponseDTO[]> {
return this.boardsService.findPagedBoards(page, limit);
return await this.boardsService.findPagedBoards(page, limit);
}

@Get(':boardId')
async findOne(
@Param('boardId') boardId: string,
): Promise<BoardResponseDTO | undefined> {
return this.boardsService.findOneBoard(+boardId);
return await this.boardsService.findOneBoard(+boardId);
}

@Patch(':boardId')
Expand All @@ -67,8 +74,11 @@ export class BoardsController {
}

@Delete(':boardId')
async deleteBoard(@Param('boardId') boardId: number): Promise<void> {
const userId = 1; // 임시로 1 받아오는겁니다 (토큰 완성되면 수정예정)
async deleteBoard(
@Headers('accessToken') accessToken: string,
@Param('boardId') boardId: number,
) {
const userId = await this.tokenService.decodeToken(accessToken);
await this.boardsService.deleteBoard(boardId, userId);
}
}
18 changes: 12 additions & 6 deletions src/boards/repository/boards.repository.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { EntityManager } from 'typeorm';
import { Board } from '../entities/board.entity';
import { CreateBoardDto } from '../dto/create.board.dto';
import { User } from 'src/users/entities/user.entity';
// import { User } from 'src/users/entities/user.entity';
import { Injectable } from '@nestjs/common';

@Injectable()
export class BoardRepository {
constructor(private readonly entityManager: EntityManager) {}

async createBoard(boardData: CreateBoardDto): Promise<Board> {
const userId = 1; // 임시로 1 쓴거야, 준혁아 여기 수정하면 된다.
const user = new User();
user.id = userId;
async createBoard(boardData: CreateBoardDto, userId: number): Promise<Board> {
// const userId = 1; // 임시로 1 쓴거야, 준혁아 여기 수정하면 된다.
// const user = new User();
// user.id = userId;
const board = new Board();
board.head = boardData.head;
board.body = boardData.body;
Expand Down Expand Up @@ -50,7 +50,13 @@ export class BoardRepository {
return existingBoard;
}

async deleteBoard(board: Board): Promise<void> {
async deleteBoard(boardData: Board, userId: number): Promise<void> {
const board = new Board();
board.head = boardData.head;
board.body = boardData.body;
board.main_category = boardData.main_category;
board.sub_category = boardData.sub_category;
board.userId = userId;
await this.entityManager.remove(Board, board);
}
}
Loading

0 comments on commit 359c0f3

Please sign in to comment.