Skip to content

Commit

Permalink
Merge pull request #155 from modern-agile-team/feature/socket
Browse files Browse the repository at this point in the history
Feature/socket
  • Loading branch information
hobiJeong authored Dec 21, 2023
2 parents 7fe0202 + 0b32ab3 commit f84c2c3
Show file tree
Hide file tree
Showing 63 changed files with 2,621 additions and 423 deletions.
228 changes: 45 additions & 183 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 2 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,24 @@
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.1.1",
"@nestjs/mongoose": "^10.0.1",
"@nestjs/passport": "^10.0.2",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.2.5",
"@nestjs/schedule": "^4.0.0",
"@nestjs/swagger": "^7.1.10",
"@nestjs/typeorm": "^10.0.0",
"@nestjs/websockets": "^10.2.5",
"@types/passport-jwt": "^3.0.12",
"aws-sdk": "^2.1443.0",
"axios": "^1.5.1",
"chalk": "^5.3.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"config": "^3.3.9",
"cookie-parser": "^1.4.6",
"dotenv": "^16.3.1",
"mongoose": "^7.5.0",
"mysql2": "^3.6.0",
"nest-aws-sdk": "^3.0.1",
"nestjs-asyncapi": "^1.2.1",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0",
"passport-jwt": "^4.0.1",
"passport-kakao": "^1.0.1",
"passport-naver-v2": "^2.0.8",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"socket.io-client": "^4.7.2",
Expand All @@ -61,11 +55,11 @@
"@nestjs/schematics": "^10.0.2",
"@nestjs/testing": "^10.0.0",
"@types/config": "^3.3.2",
"@types/cookie-parser": "^1.4.6",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/multer": "^1.4.9",
"@types/node": "^20.3.1",
"@types/passport-naver": "^1.0.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { SearchModule } from './search/search.module';
UserModule,
TypeOrmModule.forRoot({
...TypeORMconfig, // TypeORM 설정 객체 확장
synchronize: true, // DB 동기화 여부 설정
synchronize: false, // DB 동기화 여부 설정
}),
// TypeOrmModule.forFeature([Image]),
ConfigModule.forRoot({
Expand Down
25 changes: 20 additions & 5 deletions src/auth/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@nestjs/common';
import { S3Service } from 'src/common/s3/s3.service';
import { TokenService } from '../services/token.service';
import { ApiTags } from '@nestjs/swagger';
import { ApiCookieAuth, ApiTags } from '@nestjs/swagger';
import { ApiNaverLogin } from '../swagger-decorators/naver-login.decorator';
import { ApiKakaoLogin } from '../swagger-decorators/kakao-login.decorator';
import { ApiNewAccessToken } from '../swagger-decorators/new-access-token.decorator';
Expand All @@ -29,8 +29,8 @@ import { GetUserId } from 'src/common/decorators/get-userId.decorator';
export class AuthController {
constructor(
private readonly authService: AuthService,
private tokenService: TokenService,
private s3Service: S3Service,
private readonly tokenService: TokenService,
private readonly s3Service: S3Service,
) {}

@ApiNaverLogin()
Expand All @@ -52,7 +52,14 @@ export class AuthController {
naverRefreshToken,
);

return res.json({ accessToken, refreshToken });
res.cookie('refresh_token', refreshToken, {
httpOnly: true,
sameSite: 'Lax',
domain: 'localhost',
maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
});

return res.json({ accessToken });
}

@ApiKakaoLogin()
Expand All @@ -74,9 +81,17 @@ export class AuthController {
kakaoRefreshToken,
);

return res.json({ accessToken, refreshToken });
res.cookie('refresh_Token', refreshToken, {
httpOnly: true,
sameSite: 'Lax',
domain: 'localhost',
maxAge: 1000 * 60 * 60 * 24 * 7, // 7일
});

return res.json({ accessToken });
}

@ApiCookieAuth('refresh-token')
@ApiNewAccessToken()
@UseGuards(JwtRefreshTokenGuard)
@Get('new-access-token')
Expand Down
2 changes: 1 addition & 1 deletion src/auth/swagger-decorators/kakao-login.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function ApiKakaoLogin() {
}),
ApiResponse({
status: 200,
description: '성공적으로 로그인 된 경우',
description: '성공적으로 로그인 된 경우 (refresh_token은 쿠키로 전달됨)',
content: {
JSON: {
example: {
Expand Down
10 changes: 7 additions & 3 deletions src/auth/swagger-decorators/naver-login.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { applyDecorators } from '@nestjs/common';
import { ApiOperation, ApiQuery, ApiResponse } from '@nestjs/swagger';
import {
ApiHeader,
ApiOperation,
ApiQuery,
ApiResponse,
} from '@nestjs/swagger';

export function ApiNaverLogin() {
return applyDecorators(
Expand All @@ -9,12 +14,11 @@ export function ApiNaverLogin() {
}),
ApiResponse({
status: 200,
description: '성공적으로 로그인 된 경우',
description: '성공적으로 로그인 된 경우 (refresh_token은 쿠키로 전달됨)',
content: {
JSON: {
example: {
accessToken: '여기에 액세스 토큰',
refreshToken: '여기에 리프레시 토큰',
},
},
},
Expand Down
10 changes: 1 addition & 9 deletions src/auth/swagger-decorators/new-access-token.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { applyDecorators } from '@nestjs/common';
import { ApiHeaders, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ApiOperation, ApiResponse } from '@nestjs/swagger';

export function ApiNewAccessToken() {
return applyDecorators(
Expand Down Expand Up @@ -49,13 +49,5 @@ export function ApiNewAccessToken() {
},
},
}),
ApiHeaders([
{
name: 'refresh_token',
description: '리프레시 토큰',
required: true,
example: '여기에 리프레시 토큰',
},
]),
);
}
34 changes: 17 additions & 17 deletions src/boards/controllers/Boards.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
Delete,
UseInterceptors,
Query,
Headers,
UploadedFiles,
UseGuards,
} from '@nestjs/common';
import { BoardsService } from '../services/Boards.service';
import { Board } from '../entities/board.entity';
Expand All @@ -17,7 +17,6 @@ import { BoardImagesService } from '../services/BoardImage.service';
import { FilesInterceptor } 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';
import { ApiUploadBoardImages } from '../swagger-decorators/upload-baord-images-decorator';
import { ApiAddBoard } from '../swagger-decorators/add-board-decorators';
import { ApiGetPageBoards } from '../swagger-decorators/get-page-boards-decorators';
Expand All @@ -26,37 +25,38 @@ import { ApiUpdateBoard } from '../swagger-decorators/patch-board-decorators';
import { ApiTags } from '@nestjs/swagger';
import { ApiDeleteBoard } from '../swagger-decorators/delete-board-decorators';
import { ApiUpdateBoardImage } from '../swagger-decorators/patch-board-images-decorators';
import { JwtAccessTokenGuard } from 'src/config/guards/jwt-access-token.guard';
import { GetUserId } from 'src/common/decorators/get-userId.decorator';
import { BoardOwnerGuard } from 'src/config/guards/board-owner.guard';
import { BoardOwner } from 'src/common/decorators/board-owner.decorator';

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

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

@Post('/images')
@UseGuards(JwtAccessTokenGuard)
@UseInterceptors(FilesInterceptor('files', 3))
@ApiUploadBoardImages()
async uploadImage(
@Headers('access_token') accesstoken: string,
@GetUserId() userId: number,
@Query('boardId') boardId: number,
@UploadedFiles() files: Express.Multer.File[],
): Promise<CreateBoardImageDto[]> {
const userId = await this.tokenService.decodeToken(accesstoken);
console.log(files);

return await this.boardImagesService.createBoardImages(
boardId,
files,
Expand All @@ -74,14 +74,14 @@ export class BoardsController {
}

@Get('/unit')
@UseGuards(BoardOwnerGuard)
@ApiGetOneBoard()
async findOne(
@Query('boardId') boardId: number,
@Headers('access_token') accesstoken: string,
@BoardOwner() unitOnwer: boolean,
@GetUserId() userId: number,
): Promise<BoardResponseDTO> {
``;
const userId = await this.tokenService.decodeToken(accesstoken);
return await this.boardsService.findOneBoard(boardId, userId);
return await this.boardsService.findOneBoard(boardId, userId, unitOnwer);
}

@Patch('')
Expand All @@ -94,15 +94,15 @@ export class BoardsController {
}

@Patch('/images')
@UseGuards(JwtAccessTokenGuard)
@ApiUpdateBoardImage()
@UseInterceptors(FilesInterceptor('files', 3))
async editBoardImages(
@Headers('access_token') accessToken: string,
@GetUserId() userId: number,
@Query('boardId') boardId: number,
@Query('deleteImageUrl') deleteImageUrl: string[],
@UploadedFiles() files: Express.Multer.File[],
) {
const userId = await this.tokenService.decodeToken(accessToken);
return await this.boardImagesService.updateBoardImages(
boardId,
files,
Expand All @@ -112,12 +112,12 @@ export class BoardsController {
}

@Delete('')
@UseGuards(JwtAccessTokenGuard)
@ApiDeleteBoard()
async deleteBoard(
@Query('boardId') boardId: number,
@Headers('access_token') accessToken: string,
@GetUserId() userId: number,
) {
const userId = await this.tokenService.decodeToken(accessToken);
await this.boardsService.deleteBoard(boardId, userId);
}
}
38 changes: 14 additions & 24 deletions src/boards/controllers/boards-like.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import {
UsePipes,
ValidationPipe,
Query,
Headers,
UseGuards,
} from '@nestjs/common';
import { BoardsLikeService } from '../services/boards-like.service';
import { ApiTags } from '@nestjs/swagger';
import { ApiAddBoardLike } from '../swagger-decorators/add-board-like.decorator';
import { ApiGetBoardLikeCount } from '../swagger-decorators/get-board-like-count.decorator';
import { ApiDeleteBoardLike } from '../swagger-decorators/delete-board-like.decorator';
import { TokenService } from 'src/auth/services/token.service';
import { GetUserId } from 'src/common/decorators/get-userId.decorator';
import { JwtAccessTokenGuard } from 'src/config/guards/jwt-access-token.guard';
import { JwtOptionalGuard } from 'src/config/guards/jwt-optional.guard';

@ApiTags('BOARDS-LIKE')
@UsePipes(ValidationPipe)
Expand All @@ -28,49 +31,36 @@ export class BoardsLikeController {

@ApiAddBoardLike()
@Post('like/:boardId')
@UseGuards(JwtAccessTokenGuard)
async addBoardLike(
@Headers('access_token') accessToken: string,
@GetUserId() userId: number,
@Param('boardId', ParseIntPipe) boardId: number,
) {
const userId = await this.tokenService.decodeToken(accessToken);
return this.boardsLikeService.addBoardLike(boardId, userId);
}

@ApiGetBoardLikeCount()
@Get('like')
@UseGuards(JwtOptionalGuard)
async getBoardsLike(
@Headers('access_token') accessToken: string,
@GetUserId() userId: number,
@Query('boardId', ParseIntPipe) boardId: number,
) {
try {
const userId = await this.tokenService.decodeToken(accessToken);

return this.boardsLikeService.getBoardLikesAndIsLike(boardId, userId);
} catch (error) {
if (
(error.status === 401 &&
error.message === '유효하지 않은 토큰입니다.') ||
(error.status === 403 && error.message === '만료된 토큰입니다.') ||
(error.status === 404 &&
error.message === '사용자를 찾을 수 없습니다.') ||
(error.status === 411 &&
error.message === '토큰이 제공되지 않았습니다.')
) {
return this.boardsLikeService.getBoardLikes(boardId);
}
console.error(error);
throw error;
if (userId === undefined) {
return this.boardsLikeService.getBoardLikes(boardId);
}

return this.boardsLikeService.getBoardLikesAndIsLike(boardId, userId);
}

@ApiDeleteBoardLike()
@Delete('like/:boardId')
@UseGuards(JwtAccessTokenGuard)
async deleteBoardLike(
@Headers('access_token') accessToken: string,
@GetUserId() userId: number,
@Param('boardId', ParseIntPipe)
boardId: number,
) {
const userId = await this.tokenService.decodeToken(accessToken);
return this.boardsLikeService.deleteBoardLike(boardId, userId);
}
}
4 changes: 3 additions & 1 deletion src/boards/entities/board-image.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export class BoardImage {
@PrimaryGeneratedColumn()
id: number;

@ManyToOne(() => Board, (board) => board.boardImages)
@ManyToOne(() => Board, (board) => board.boardImages, {
onDelete: 'CASCADE',
})
@JoinColumn({ name: 'board_id' })
board: Board;

Expand Down
Loading

0 comments on commit f84c2c3

Please sign in to comment.