From 537ab898471964bfc2b4757c6da27fc80f5fe680 Mon Sep 17 00:00:00 2001 From: twalla26 Date: Wed, 4 Dec 2024 02:03:35 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20status=20code=20401=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question-list/question-list.controller.ts | 220 +++++++++++++----- 1 file changed, 158 insertions(+), 62 deletions(-) diff --git a/backend/src/question-list/question-list.controller.ts b/backend/src/question-list/question-list.controller.ts index daf7da15..2f1014f0 100644 --- a/backend/src/question-list/question-list.controller.ts +++ b/backend/src/question-list/question-list.controller.ts @@ -3,11 +3,13 @@ import { Controller, Delete, Get, + HttpStatus, Param, Patch, Post, Query, Req, + Res, UseGuards, UsePipes, ValidationPipe, @@ -28,31 +30,43 @@ export class QuestionListController { constructor(private readonly questionListService: QuestionListService) {} @Get() + @UseGuards(AuthGuard("jwt")) @UsePipes(new ValidationPipe({ transform: true })) - async getAllQuestionLists(@Query() query: PaginateQueryDto) { + async getAllQuestionLists( + @Res() res, + @Query() query: PaginateQueryDto, + @JwtPayload() token: IJwtPayload + ) { try { + if (!token) { + // 로그인 안함 + // isScrap: false + } const { allQuestionLists, meta } = await this.questionListService.getAllQuestionLists(query); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "All question lists received successfully.", data: { allQuestionLists, meta, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to get all question lists.", error: error.message, - }; + }); } } @Post("category") + @UseGuards(AuthGuard("jwt")) @UsePipes(new ValidationPipe({ transform: true })) async getAllQuestionListsByCategoryName( + @Res() res, + @JwtPayload() token: IJwtPayload, @Query() query: PaginateQueryDto, @Body() body: { @@ -60,24 +74,28 @@ export class QuestionListController { } ) { try { + if (!token) { + // 로그인 안함 + // isScrap: false + } const { categoryName } = body; query.category = categoryName; const { allQuestionLists, meta } = await this.questionListService.getAllQuestionLists(query); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "All question lists received successfully.", data: { allQuestionLists, meta, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to get all question lists.", error: error.message, - }; + }); } } @@ -85,6 +103,7 @@ export class QuestionListController { @UseGuards(AuthGuard("jwt")) async createQuestionList( @JwtPayload() token: IJwtPayload, + @Res() res, @Req() req, @Body() body: { @@ -96,6 +115,11 @@ export class QuestionListController { ) { try { const { title, contents, categoryNames, isPublic } = body; + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); // 질문지 DTO 준비 const createQuestionListDto: CreateQuestionListDto = { @@ -109,26 +133,27 @@ export class QuestionListController { // 질문지 생성 const { createdQuestionList, createdQuestions } = await this.questionListService.createQuestionList(createQuestionListDto); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question list created successfully.", data: { createdQuestionList, createdQuestions, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to create question list.", error: error.message, - }; + }); } } @Post("contents") @UseGuards(AuthGuard("jwt")) async getQuestionListContents( + @Res() res, @JwtPayload() token: IJwtPayload, @Body() body: { @@ -136,62 +161,84 @@ export class QuestionListController { } ) { try { + if (!token) { + // 로그인 안함 + // isScrap: false + // 비공개 질문 접근 불가 처리 + } const userId = token.userId; const { questionListId } = body; const questionListContents: QuestionListContentsDto = await this.questionListService.getQuestionListContents(questionListId, userId); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question list contents received successfully.", data: { questionListContents, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to get question list contents.", error: error.message, - }; + }); } } @Get("my") @UseGuards(AuthGuard("jwt")) @UsePipes(new ValidationPipe({ transform: true })) - async getMyQuestionLists(@Query() query: PaginateQueryDto, @JwtPayload() token: IJwtPayload) { + async getMyQuestionLists( + @Res() res, + @Query() query: PaginateQueryDto, + @JwtPayload() token: IJwtPayload + ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { myQuestionLists, meta } = await this.questionListService.getMyQuestionLists( userId, query ); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "My question lists received successfully.", data: { myQuestionLists, meta, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to get my question lists.", error: error.message, - }; + }); } } @Patch("/:questionListId") @UseGuards(AuthGuard("jwt")) async updateQuestionList( + @Res() res, @JwtPayload() token: IJwtPayload, @Param("questionListId") questionListId: number, @Body() body: { title?: string; isPublic?: boolean; categoryNames?: string[] } ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { title, isPublic, categoryNames } = body; const updateQuestionListDto: UpdateQuestionListDto = { id: questionListId, @@ -203,64 +250,78 @@ export class QuestionListController { const updatedQuestionList = await this.questionListService.updateQuestionList(updateQuestionListDto); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question list is updated successfully.", data: { questionList: updatedQuestionList, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to update question list.", error: error.message, - }; + }); } } @Delete("/:questionListId") @UseGuards(AuthGuard("jwt")) async deleteQuestionList( + @Res() res, @JwtPayload() token: IJwtPayload, @Param("questionListId") questionListId: number ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const result = await this.questionListService.deleteQuestionList( questionListId, userId ); if (result.affected) { - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question list is deleted successfully.", - }; + }); } else { - return { - success: true, + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ + success: false, message: "Failed to delete question list.", - }; + }); } } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: true, message: "Failed to delete question list.", error: error.message, - }; + }); } } @Post("/:questionListId/question") @UseGuards(AuthGuard("jwt")) async addQuestion( + @Res() res, @JwtPayload() token: IJwtPayload, @Body() body: { content: string }, @Param("questionListId") questionListId: number ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { content } = body; const questionDto: QuestionDto = { content, @@ -270,31 +331,38 @@ export class QuestionListController { const result = await this.questionListService.addQuestion(questionDto); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "The new question is added to the list successfully.", data: { questionList: result, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to add the new question to the list.", error: error.message, - }; + }); } } @Patch("/:questionListId/question/:questionId") @UseGuards(AuthGuard("jwt")) async updateQuestion( + @Res() res, @JwtPayload() token: IJwtPayload, @Body() body: { content: string }, @Param() params: { questionListId: number; questionId: number } ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { content } = body; const { questionListId, questionId } = params; const questionDto: QuestionDto = { @@ -306,30 +374,37 @@ export class QuestionListController { const result = await this.questionListService.updateQuestion(questionDto); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question is updated successfully.", data: { questionList: result, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to update question.", error: error.message, - }; + }); } } @Delete("/:questionListId/question/:questionId") @UseGuards(AuthGuard("jwt")) async deleteQuestion( + @Res() res, @JwtPayload() token: IJwtPayload, @Param() params: { questionListId: number; questionId: number } ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { questionListId, questionId } = params; const deleteQuestionDto: DeleteQuestionDto = { id: questionId, @@ -338,22 +413,22 @@ export class QuestionListController { }; const result = await this.questionListService.deleteQuestion(deleteQuestionDto); if (result.affected) { - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question is deleted successfully.", - }; + }); } else { - return { - success: true, + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ + success: false, message: "Failed to delete question.", - }; + }); } } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to delete question.", error: error.message, - }; + }); } } @@ -361,90 +436,111 @@ export class QuestionListController { @UseGuards(AuthGuard("jwt")) @UsePipes(new ValidationPipe({ transform: true })) async getScrappedQuestionLists( + @Res() res, @Query() query: PaginateQueryDto, @JwtPayload() token: IJwtPayload ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { scrappedQuestionLists, meta } = await this.questionListService.getScrappedQuestionLists(userId, query); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Scrapped question lists received successfully.", data: { questionList: scrappedQuestionLists, meta, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to get scrapped question lists.", error: error.message, - }; + }); } } @Post("scrap") @UseGuards(AuthGuard("jwt")) async scrapQuestionList( + @Res() res, @JwtPayload() token: IJwtPayload, @Body() body: { questionListId: number } ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login required.", + }); const userId = token.userId; + const { questionListId } = body; const scrappedQuestionList = await this.questionListService.scrapQuestionList( questionListId, userId ); - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question list is scrapped successfully.", data: { questionList: scrappedQuestionList, }, - }; + }); } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to scrap question list.", error: error.message, - }; + }); } } @Delete("scrap/:questionListId") @UseGuards(AuthGuard("jwt")) async unscrapQuestionList( + @Res() res, @JwtPayload() token: IJwtPayload, @Param("questionListId") questionListId: number ) { try { + if (!token) + return res.status(HttpStatus.UNAUTHORIZED).json({ + success: false, + message: "Login is required to create question list.", + }); const userId = token.userId; + const unscrappedQuestionList = await this.questionListService.unscrapQuestionList( questionListId, userId ); if (unscrappedQuestionList.affected) { - return { + return res.status(HttpStatus.OK).json({ success: true, message: "Question list unscrapped successfully.", - }; + }); } else { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to unscrap question list.", - }; + }); } } catch (error) { - return { + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ success: false, message: "Failed to unscrap question list.", error: error.message, - }; + }); } } } From 4013cb19e30176edada75a6abbda6b394323291e Mon Sep 17 00:00:00 2001 From: twalla26 Date: Wed, 4 Dec 2024 02:48:51 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=9C=A0=EB=AC=B4=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=A7=88=EB=AC=B8=EC=A7=80,=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=EB=B3=84=20=EC=A7=88=EB=AC=B8=EC=A7=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=EC=97=90=20isScrap=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B0=98=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/get-all-question-list.dto.ts | 1 + .../question-list/question-list.controller.ts | 24 +++++++++---------- .../question-list/question-list.service.ts | 5 +++- .../repository/question-list.repository.ts | 10 ++++++++ 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/backend/src/question-list/dto/get-all-question-list.dto.ts b/backend/src/question-list/dto/get-all-question-list.dto.ts index 9d87dfad..d9653f41 100644 --- a/backend/src/question-list/dto/get-all-question-list.dto.ts +++ b/backend/src/question-list/dto/get-all-question-list.dto.ts @@ -4,4 +4,5 @@ export interface GetAllQuestionListDto { categoryNames: string[]; usage: number; questionCount: number; + isScrap: boolean; } diff --git a/backend/src/question-list/question-list.controller.ts b/backend/src/question-list/question-list.controller.ts index 2f1014f0..d2297d9d 100644 --- a/backend/src/question-list/question-list.controller.ts +++ b/backend/src/question-list/question-list.controller.ts @@ -38,12 +38,11 @@ export class QuestionListController { @JwtPayload() token: IJwtPayload ) { try { - if (!token) { - // 로그인 안함 - // isScrap: false - } - const { allQuestionLists, meta } = - await this.questionListService.getAllQuestionLists(query); + const userId = token ? token.userId : null; + const { allQuestionLists, meta } = await this.questionListService.getAllQuestionLists( + query, + userId + ); return res.status(HttpStatus.OK).json({ success: true, message: "All question lists received successfully.", @@ -74,14 +73,15 @@ export class QuestionListController { } ) { try { - if (!token) { - // 로그인 안함 - // isScrap: false - } + const userId = token ? token.userId : null; + const { categoryName } = body; query.category = categoryName; - const { allQuestionLists, meta } = - await this.questionListService.getAllQuestionLists(query); + + const { allQuestionLists, meta } = await this.questionListService.getAllQuestionLists( + query, + userId + ); return res.status(HttpStatus.OK).json({ success: true, message: "All question lists received successfully.", diff --git a/backend/src/question-list/question-list.service.ts b/backend/src/question-list/question-list.service.ts index 1834f64f..951bfd16 100644 --- a/backend/src/question-list/question-list.service.ts +++ b/backend/src/question-list/question-list.service.ts @@ -28,7 +28,7 @@ export class QuestionListService { private readonly categoryRepository: CategoryRepository ) {} - async getAllQuestionLists(query: PaginateQueryDto) { + async getAllQuestionLists(query: PaginateQueryDto, userId: number) { const allQuestionLists: GetAllQuestionListDto[] = []; let categoryId = null; @@ -53,12 +53,15 @@ export class QuestionListService { where: { questionListId: id }, }); + const isScrap = await this.questionListRepository.isQuestionListScrapped(id, userId); + const questionList: GetAllQuestionListDto = { id, title, categoryNames, usage, questionCount, + isScrap, }; allQuestionLists.push(questionList); } diff --git a/backend/src/question-list/repository/question-list.repository.ts b/backend/src/question-list/repository/question-list.repository.ts index ae16933e..c47e4106 100644 --- a/backend/src/question-list/repository/question-list.repository.ts +++ b/backend/src/question-list/repository/question-list.repository.ts @@ -58,6 +58,16 @@ export class QuestionListRepository extends Repository { .execute(); } + isQuestionListScrapped(questionListId: number, userId: number) { + return this.createQueryBuilder("question_list") + .innerJoin("question_list.scrappedByUsers", "user") + .where("question_list.id = :questionListId", { questionListId }) + .andWhere("user.id = :userId", { userId }) + .select("1") + .getRawOne() + .then((result) => !!result); + } + async paginate(paginateDto: PaginateDto) { const { queryBuilder, skip, take, field, direction } = paginateDto; return await queryBuilder From eab640f3f8dc55fd1443d52ec92479b9c731631e Mon Sep 17 00:00:00 2001 From: twalla26 Date: Wed, 4 Dec 2024 03:06:20 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20=EC=82=BC=ED=95=AD=20=EC=97=B0?= =?UTF-8?q?=EC=82=B0=EC=9E=90=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question-list/question-list.controller.ts | 57 ++++++++++++------- .../question-list/question-list.service.ts | 5 +- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/backend/src/question-list/question-list.controller.ts b/backend/src/question-list/question-list.controller.ts index d2297d9d..39eac654 100644 --- a/backend/src/question-list/question-list.controller.ts +++ b/backend/src/question-list/question-list.controller.ts @@ -115,7 +115,9 @@ export class QuestionListController { ) { try { const { title, contents, categoryNames, isPublic } = body; - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", @@ -127,7 +129,7 @@ export class QuestionListController { contents, categoryNames, isPublic, - userId: token.userId, + userId, }; // 질문지 생성 @@ -161,12 +163,14 @@ export class QuestionListController { } ) { try { - if (!token) { + const userId = token ? token.userId : null; + + if (!userId) { // 로그인 안함 // isScrap: false // 비공개 질문 접근 불가 처리 } - const userId = token.userId; + const { questionListId } = body; const questionListContents: QuestionListContentsDto = await this.questionListService.getQuestionListContents(questionListId, userId); @@ -195,12 +199,13 @@ export class QuestionListController { @JwtPayload() token: IJwtPayload ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { myQuestionLists, meta } = await this.questionListService.getMyQuestionLists( userId, @@ -232,12 +237,13 @@ export class QuestionListController { @Body() body: { title?: string; isPublic?: boolean; categoryNames?: string[] } ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { title, isPublic, categoryNames } = body; const updateQuestionListDto: UpdateQuestionListDto = { @@ -274,12 +280,13 @@ export class QuestionListController { @Param("questionListId") questionListId: number ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const result = await this.questionListService.deleteQuestionList( questionListId, @@ -315,12 +322,13 @@ export class QuestionListController { @Param("questionListId") questionListId: number ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { content } = body; const questionDto: QuestionDto = { @@ -356,12 +364,13 @@ export class QuestionListController { @Param() params: { questionListId: number; questionId: number } ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { content } = body; const { questionListId, questionId } = params; @@ -398,12 +407,13 @@ export class QuestionListController { @Param() params: { questionListId: number; questionId: number } ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { questionListId, questionId } = params; const deleteQuestionDto: DeleteQuestionDto = { @@ -441,12 +451,13 @@ export class QuestionListController { @JwtPayload() token: IJwtPayload ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { scrappedQuestionLists, meta } = await this.questionListService.getScrappedQuestionLists(userId, query); @@ -475,12 +486,13 @@ export class QuestionListController { @Body() body: { questionListId: number } ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login required.", }); - const userId = token.userId; const { questionListId } = body; const scrappedQuestionList = await this.questionListService.scrapQuestionList( @@ -512,12 +524,13 @@ export class QuestionListController { @Param("questionListId") questionListId: number ) { try { - if (!token) + const userId = token ? token.userId : null; + + if (!userId) return res.status(HttpStatus.UNAUTHORIZED).json({ success: false, message: "Login is required to create question list.", }); - const userId = token.userId; const unscrappedQuestionList = await this.questionListService.unscrapQuestionList( questionListId, diff --git a/backend/src/question-list/question-list.service.ts b/backend/src/question-list/question-list.service.ts index 951bfd16..c5c7930b 100644 --- a/backend/src/question-list/question-list.service.ts +++ b/backend/src/question-list/question-list.service.ts @@ -53,7 +53,9 @@ export class QuestionListService { where: { questionListId: id }, }); - const isScrap = await this.questionListRepository.isQuestionListScrapped(id, userId); + const isScrap = userId + ? await this.questionListRepository.isQuestionListScrapped(id, userId) + : false; const questionList: GetAllQuestionListDto = { id, @@ -128,6 +130,7 @@ export class QuestionListService { const user = await this.userRepository.getUserByUserId(userId); const username = user.username; + const questionListContents: QuestionListContentsDto = { id, title, From 50a59b9e70161eaf53b6885412f4a271f3757772 Mon Sep 17 00:00:00 2001 From: twalla26 Date: Wed, 4 Dec 2024 03:16:31 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=EC=A7=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20isS?= =?UTF-8?q?crap=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/question-list-contents.dto.ts | 1 + .../src/question-list/question-list.service.ts | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/backend/src/question-list/dto/question-list-contents.dto.ts b/backend/src/question-list/dto/question-list-contents.dto.ts index 3be38c9c..29a82043 100644 --- a/backend/src/question-list/dto/question-list-contents.dto.ts +++ b/backend/src/question-list/dto/question-list-contents.dto.ts @@ -7,4 +7,5 @@ export interface QuestionListContentsDto { contents: Question[]; usage: number; username: string; + isScrap: boolean; } diff --git a/backend/src/question-list/question-list.service.ts b/backend/src/question-list/question-list.service.ts index c5c7930b..90edf3f6 100644 --- a/backend/src/question-list/question-list.service.ts +++ b/backend/src/question-list/question-list.service.ts @@ -118,9 +118,14 @@ export class QuestionListService { const questionList = await this.questionListRepository.findOne({ where: { id: questionListId }, }); + const { id, title, usage, isPublic } = questionList; - if (!isPublic && questionList.userId !== userId) { - throw new Error("This is private question list."); + const authorId = questionList.userId; + + if (!isPublic) { + if (!userId || questionList.userId !== userId) { + throw new Error("This is a private question list."); + } } const contents = await this.questionRepository.getContentsByQuestionListId(questionListId); @@ -128,8 +133,12 @@ export class QuestionListService { const categoryNames = await this.categoryRepository.findCategoryNamesByQuestionListId(questionListId); - const user = await this.userRepository.getUserByUserId(userId); - const username = user.username; + const author = await this.userRepository.getUserByUserId(authorId); + const username = author.username; + + const isScrap = userId + ? await this.questionListRepository.isQuestionListScrapped(id, userId) + : false; const questionListContents: QuestionListContentsDto = { id, @@ -138,6 +147,7 @@ export class QuestionListService { categoryNames, usage, username, + isScrap, }; return questionListContents; From ff854b2e21ee3f4e32d7a80d64e6d1326eef5351 Mon Sep 17 00:00:00 2001 From: twalla26 Date: Wed, 4 Dec 2024 03:25:05 +0900 Subject: [PATCH 5/5] =?UTF-8?q?feat:=20=EC=A7=88=EB=AC=B8=EC=A7=80=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20scr?= =?UTF-8?q?apCount=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/question-list/dto/question-list-contents.dto.ts | 1 + backend/src/question-list/question-list.controller.ts | 6 ------ backend/src/question-list/question-list.service.ts | 3 +++ .../question-list/repository/question-list.repository.ts | 8 ++++++++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backend/src/question-list/dto/question-list-contents.dto.ts b/backend/src/question-list/dto/question-list-contents.dto.ts index 29a82043..ad4b37db 100644 --- a/backend/src/question-list/dto/question-list-contents.dto.ts +++ b/backend/src/question-list/dto/question-list-contents.dto.ts @@ -8,4 +8,5 @@ export interface QuestionListContentsDto { usage: number; username: string; isScrap: boolean; + scrapCount: number; } diff --git a/backend/src/question-list/question-list.controller.ts b/backend/src/question-list/question-list.controller.ts index 39eac654..c70d63a3 100644 --- a/backend/src/question-list/question-list.controller.ts +++ b/backend/src/question-list/question-list.controller.ts @@ -165,12 +165,6 @@ export class QuestionListController { try { const userId = token ? token.userId : null; - if (!userId) { - // 로그인 안함 - // isScrap: false - // 비공개 질문 접근 불가 처리 - } - const { questionListId } = body; const questionListContents: QuestionListContentsDto = await this.questionListService.getQuestionListContents(questionListId, userId); diff --git a/backend/src/question-list/question-list.service.ts b/backend/src/question-list/question-list.service.ts index 90edf3f6..d98388a7 100644 --- a/backend/src/question-list/question-list.service.ts +++ b/backend/src/question-list/question-list.service.ts @@ -140,6 +140,8 @@ export class QuestionListService { ? await this.questionListRepository.isQuestionListScrapped(id, userId) : false; + const scrapCount = await this.questionListRepository.getScrapCount(id); + const questionListContents: QuestionListContentsDto = { id, title, @@ -148,6 +150,7 @@ export class QuestionListService { usage, username, isScrap, + scrapCount: parseInt(scrapCount.count), }; return questionListContents; diff --git a/backend/src/question-list/repository/question-list.repository.ts b/backend/src/question-list/repository/question-list.repository.ts index c47e4106..1d4834da 100644 --- a/backend/src/question-list/repository/question-list.repository.ts +++ b/backend/src/question-list/repository/question-list.repository.ts @@ -68,6 +68,14 @@ export class QuestionListRepository extends Repository { .then((result) => !!result); } + getScrapCount(questionListId: number) { + return this.createQueryBuilder("question_list") + .innerJoin("question_list.scrappedByUsers", "user") + .where("question_list.id = :questionListId", { questionListId }) + .select("COUNT(user.id)", "count") + .getRawOne(); + } + async paginate(paginateDto: PaginateDto) { const { queryBuilder, skip, take, field, direction } = paginateDto; return await queryBuilder