From ca6c9e9110c48278606703d7c3dec55783db7943 Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 11:57:00 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20readDiaryList=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20DTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - readDiaryList의 응답을 위한 readDiaryListResponseDto 생성 --- BE/src/diaries/diaries.dto.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/BE/src/diaries/diaries.dto.ts b/BE/src/diaries/diaries.dto.ts index 8cfc84c..9335a02 100644 --- a/BE/src/diaries/diaries.dto.ts +++ b/BE/src/diaries/diaries.dto.ts @@ -76,14 +76,15 @@ export class DiaryUuidDto { uuid: string; } -export class ReadDiaryResponseDto { +export class ReadDiaryListResponseDto { userId: string; + uuid: string; title: string; content: string; date: Date; tags: string[]; emotion: { - position: number; + positive: number; neutral: number; negative: number; sentiment: sentimentStatus; From 90cc432ba3720b12cbc3e76af727958ab163b97e Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 11:57:49 +0900 Subject: [PATCH 2/7] =?UTF-8?q?Feat:=20readDiaryList=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - diaries.controller, diaries.service, diaries.repository에 현재 유저의 일기 목록을 읽어오는 readDiaryList 구현 --- BE/src/diaries/diaries.controller.ts | 39 ++++++++++++++++++++++++++++ BE/src/diaries/diaries.repository.ts | 9 +++++++ BE/src/diaries/diaries.service.ts | 12 +++++++++ 3 files changed, 60 insertions(+) diff --git a/BE/src/diaries/diaries.controller.ts b/BE/src/diaries/diaries.controller.ts index b454c7a..0fd855b 100644 --- a/BE/src/diaries/diaries.controller.ts +++ b/BE/src/diaries/diaries.controller.ts @@ -15,11 +15,14 @@ import { DeleteDiaryDto, DiaryUuidDto, ReadDiaryDto, + ReadDiaryListResponseDto, UpdateDiaryDto, } from "./diaries.dto"; import { Diary } from "./diaries.entity"; import { AuthGuard } from "@nestjs/passport"; import { IdGuard } from "src/auth/auth.id-guard"; +import { GetUser } from "src/auth/get-user.decorator"; +import { User } from "src/users/users.entity"; @Controller("diaries") @UseGuards(AuthGuard()) @@ -65,6 +68,42 @@ export class DiariesController { return response; } + @Get() + async readDiaryList( + @GetUser() user: User, + ): Promise { + const diaryList = await this.diariesService.readDiaryList(user); + let readDiaryResponseDtoList: ReadDiaryListResponseDto[] = []; + diaryList.map((diary) => { + const coordinateArray = diary.point.split(","); + const response = { + userId: diary.user.userId, + uuid: diary.uuid, + title: diary.title, + content: diary.content, + date: diary.date, + tags: [], + emotion: { + positive: diary.positiveRatio, + neutral: diary.neutralRatio, + negative: diary.negativeRatio, + sentiment: diary.sentiment, + }, + coordinate: { + x: parseFloat(coordinateArray[0]), + y: parseFloat(coordinateArray[1]), + z: parseFloat(coordinateArray[2]), + }, + shape_uuid: diary.shape.uuid, + }; + + const readDiaryResponseDto: ReadDiaryListResponseDto = response; + readDiaryResponseDtoList.push(readDiaryResponseDto); + }); + + return readDiaryResponseDtoList; + } + @Put() @UseGuards(IdGuard) modifyDiary(@Body() updateDiaryDto: UpdateDiaryDto): Promise { diff --git a/BE/src/diaries/diaries.repository.ts b/BE/src/diaries/diaries.repository.ts index 5079e30..c268ad6 100644 --- a/BE/src/diaries/diaries.repository.ts +++ b/BE/src/diaries/diaries.repository.ts @@ -55,6 +55,15 @@ export class DiariesRepository { return diary; } + async readDiaryList(user): Promise { + const diaryList = await Diary.find({ + where: { user: user.id }, + relations: ["user", "shape"], + }); + + return diaryList; + } + async updateDiary( updateDiaryDto: UpdateDiaryDto, encodedContent: string, diff --git a/BE/src/diaries/diaries.service.ts b/BE/src/diaries/diaries.service.ts index 14534a4..307970d 100644 --- a/BE/src/diaries/diaries.service.ts +++ b/BE/src/diaries/diaries.service.ts @@ -47,6 +47,18 @@ export class DiariesService { return diary; } + async readDiaryList(user): Promise { + let diaryList: Diary[] = await this.diariesRepository.readDiaryList(user); + + diaryList.map((diary) => { + diary.content = atob(diary.content); + // Mysql DB에서 가져온 UST 날짜 데이터를 KST로 변경 + diary.date.setHours(diary.date.getHours() + 9); + }); + + return diaryList; + } + async modifyDiary(updateDiaryDto: UpdateDiaryDto): Promise { const encodedContent = btoa(updateDiaryDto.content); return this.diariesRepository.updateDiary(updateDiaryDto, encodedContent); From 2915cb0eabecc5db508aa9e3c36344045015da33 Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 11:59:44 +0900 Subject: [PATCH 3/7] =?UTF-8?q?Test:=20=EC=9D=BC=EA=B8=B0=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A0=95=EC=83=81=20=EC=9A=94=EC=B2=AD=20e2e=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - diaries.read-list.e2e-spec.ts 파일 생성 - 일기 목록 정상 요청 시 200 OK를 응답하는 e2e 테스트 작성 --- BE/test/diaries.read-list.e2e-spec.ts | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 BE/test/diaries.read-list.e2e-spec.ts diff --git a/BE/test/diaries.read-list.e2e-spec.ts b/BE/test/diaries.read-list.e2e-spec.ts new file mode 100644 index 0000000..50f7583 --- /dev/null +++ b/BE/test/diaries.read-list.e2e-spec.ts @@ -0,0 +1,49 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { INestApplication } from "@nestjs/common"; +import * as request from "supertest"; +import { AppModule } from "../src/app.module"; +import { ValidationPipe } from "@nestjs/common"; + +describe("AppController (e2e)", () => { + let app: INestApplication; + let accessToken: string; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + app.enableCors(); + app.useGlobalPipes(new ValidationPipe()); + + await app.init(); + + const signInPost = await request(app.getHttpServer()) + .post("/auth/signin") + .send({ + userId: "commonUser", + password: process.env.COMMON_USER_PASS, + }); + + accessToken = signInPost.body.accessToken; + }); + + afterEach(async () => { + await app.close(); + }); + + it("정상 요청 시 200 OK 응답", async () => { + const postResponse = await request(app.getHttpServer()) + .get("/diaries") + .set("Authorization", `Bearer ${accessToken}`) + .expect(200); + }); + + it("정상 요청 시 200 OK 응답", async () => { + const postResponse = await request(app.getHttpServer()) + .get("/diaries") + .set("Authorization", `Bearer ${accessToken}`) + .expect(200); + }); +}); From deb4004e96649e216d0f211a366739f470865218 Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 12:00:29 +0900 Subject: [PATCH 4/7] =?UTF-8?q?Test:=20=EC=9D=BC=EA=B8=B0=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=9A=94=EC=B2=AD=20=EC=8B=9C=20=EC=95=A1=EC=84=B8?= =?UTF-8?q?=EC=8A=A4=20=ED=86=A0=ED=81=B0=20=EC=97=86=EB=8A=94=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20e2e=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 일기 목록 요청에 대해 액세스 토큰 없이 요청 시 401 Unauthorized를 응답하는 e2e 테스트 작성 --- BE/test/diaries.read-list.e2e-spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/BE/test/diaries.read-list.e2e-spec.ts b/BE/test/diaries.read-list.e2e-spec.ts index 50f7583..31c24b8 100644 --- a/BE/test/diaries.read-list.e2e-spec.ts +++ b/BE/test/diaries.read-list.e2e-spec.ts @@ -46,4 +46,10 @@ describe("AppController (e2e)", () => { .set("Authorization", `Bearer ${accessToken}`) .expect(200); }); + + it("액세스 토큰 없이 요청 시 401 Unauthorized 응답", async () => { + const postResponse = await request(app.getHttpServer()) + .get("/diaries") + .expect(401); + }); }); From e7c9d2f9e1e654212722fac52cfcc5584763123c Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 13:22:36 +0900 Subject: [PATCH 5/7] =?UTF-8?q?style:=20readDiaryListResponseDto=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EA=B7=9C=EC=B9=99=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - readDiaryListResponse의 shape_uuid를 카멜 케이스로 수정 --- BE/src/diaries/diaries.controller.ts | 4 ++-- BE/src/diaries/diaries.dto.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BE/src/diaries/diaries.controller.ts b/BE/src/diaries/diaries.controller.ts index d8ecad1..89319df 100644 --- a/BE/src/diaries/diaries.controller.ts +++ b/BE/src/diaries/diaries.controller.ts @@ -62,7 +62,7 @@ export class DiariesController { y: parseFloat(coordinateArray[1]), z: parseFloat(coordinateArray[2]), }, - shape_uuid: diary.shape.uuid, + shapeUuid: diary.shape.uuid, }; return response; @@ -94,7 +94,7 @@ export class DiariesController { y: parseFloat(coordinateArray[1]), z: parseFloat(coordinateArray[2]), }, - shape_uuid: diary.shape.uuid, + shapeUuid: diary.shape.uuid, }; const readDiaryResponseDto: ReadDiaryListResponseDto = response; diff --git a/BE/src/diaries/diaries.dto.ts b/BE/src/diaries/diaries.dto.ts index 9335a02..996e774 100644 --- a/BE/src/diaries/diaries.dto.ts +++ b/BE/src/diaries/diaries.dto.ts @@ -94,5 +94,5 @@ export class ReadDiaryListResponseDto { y: number; z: number; }; - shape_uuid: string; + shapeUuid: string; } From 1f7b268b3a6c12468f093c2456f937683baeb6ec Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 13:23:20 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=EB=90=9C=20e?= =?UTF-8?q?ager=20loading=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 중복된 eager loading을 하는 relation 삭제 --- BE/src/diaries/diaries.repository.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/BE/src/diaries/diaries.repository.ts b/BE/src/diaries/diaries.repository.ts index c268ad6..1273375 100644 --- a/BE/src/diaries/diaries.repository.ts +++ b/BE/src/diaries/diaries.repository.ts @@ -58,7 +58,6 @@ export class DiariesRepository { async readDiaryList(user): Promise { const diaryList = await Diary.find({ where: { user: user.id }, - relations: ["user", "shape"], }); return diaryList; From 5909f95662ebff16fc286165b31ef7895efc7e19 Mon Sep 17 00:00:00 2001 From: JoonSoo-Kim Date: Wed, 22 Nov 2023 13:24:48 +0900 Subject: [PATCH 7/7] =?UTF-8?q?style:=20=EC=9D=BC=EA=B8=B0=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20API=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 일기 목록 API 메서드의 이름을 readDiaryList에서 readDiariesByUser로 더 명시적으로 변경 - 변경된 메서드 명에 맞게 DTO명 수정 --- BE/src/diaries/diaries.controller.ts | 12 ++++++------ BE/src/diaries/diaries.dto.ts | 2 +- BE/src/diaries/diaries.repository.ts | 2 +- BE/src/diaries/diaries.service.ts | 5 +++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/BE/src/diaries/diaries.controller.ts b/BE/src/diaries/diaries.controller.ts index 89319df..a1d37bd 100644 --- a/BE/src/diaries/diaries.controller.ts +++ b/BE/src/diaries/diaries.controller.ts @@ -15,7 +15,7 @@ import { DeleteDiaryDto, DiaryUuidDto, ReadDiaryDto, - ReadDiaryListResponseDto, + ReadDiariesResponseDto, UpdateDiaryDto, } from "./diaries.dto"; import { Diary } from "./diaries.entity"; @@ -69,11 +69,11 @@ export class DiariesController { } @Get() - async readDiaryList( + async readDiariesByUser( @GetUser() user: User, - ): Promise { - const diaryList = await this.diariesService.readDiaryList(user); - let readDiaryResponseDtoList: ReadDiaryListResponseDto[] = []; + ): Promise { + const diaryList = await this.diariesService.readDiariesByUser(user); + let readDiaryResponseDtoList: ReadDiariesResponseDto[] = []; diaryList.map((diary) => { const coordinateArray = diary.point.split(","); const response = { @@ -97,7 +97,7 @@ export class DiariesController { shapeUuid: diary.shape.uuid, }; - const readDiaryResponseDto: ReadDiaryListResponseDto = response; + const readDiaryResponseDto: ReadDiariesResponseDto = response; readDiaryResponseDtoList.push(readDiaryResponseDto); }); diff --git a/BE/src/diaries/diaries.dto.ts b/BE/src/diaries/diaries.dto.ts index 996e774..61ab18d 100644 --- a/BE/src/diaries/diaries.dto.ts +++ b/BE/src/diaries/diaries.dto.ts @@ -76,7 +76,7 @@ export class DiaryUuidDto { uuid: string; } -export class ReadDiaryListResponseDto { +export class ReadDiariesResponseDto { userId: string; uuid: string; title: string; diff --git a/BE/src/diaries/diaries.repository.ts b/BE/src/diaries/diaries.repository.ts index 1273375..290fe7c 100644 --- a/BE/src/diaries/diaries.repository.ts +++ b/BE/src/diaries/diaries.repository.ts @@ -55,7 +55,7 @@ export class DiariesRepository { return diary; } - async readDiaryList(user): Promise { + async readDiariesByUser(user): Promise { const diaryList = await Diary.find({ where: { user: user.id }, }); diff --git a/BE/src/diaries/diaries.service.ts b/BE/src/diaries/diaries.service.ts index 307970d..4924cc6 100644 --- a/BE/src/diaries/diaries.service.ts +++ b/BE/src/diaries/diaries.service.ts @@ -47,8 +47,9 @@ export class DiariesService { return diary; } - async readDiaryList(user): Promise { - let diaryList: Diary[] = await this.diariesRepository.readDiaryList(user); + async readDiariesByUser(user): Promise { + let diaryList: Diary[] = + await this.diariesRepository.readDiariesByUser(user); diaryList.map((diary) => { diary.content = atob(diary.content);