From f6e8546720180792ad0c17ebce72733c64e80a01 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 5 Aug 2024 14:13:17 +0900 Subject: [PATCH 01/76] =?UTF-8?q?feat:=20Hello,=20world=20=EB=AC=B8?= =?UTF-8?q?=EA=B5=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/kakaoteck/golagola/GolagolaApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java b/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java index b202f04..6415cf7 100644 --- a/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java +++ b/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java @@ -8,6 +8,7 @@ public class GolagolaApplication { public static void main(String[] args) { SpringApplication.run(GolagolaApplication.class, args); + System.out.println("hello, world!"); } } From 8488bb39aae9ee13874b5d2594e662eedb71ae20 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 5 Aug 2024 14:15:00 +0900 Subject: [PATCH 02/76] =?UTF-8?q?SCRUM-10=20feat:=20Goodbye=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/kakaoteck/golagola/GolagolaApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java b/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java index 6415cf7..b9b350a 100644 --- a/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java +++ b/src/main/java/com/kakaoteck/golagola/GolagolaApplication.java @@ -9,6 +9,7 @@ public class GolagolaApplication { public static void main(String[] args) { SpringApplication.run(GolagolaApplication.class, args); System.out.println("hello, world!"); + System.out.println("GoodBye"); } } From 89a42cf77f278a0e20e4c3e6b74502581c57c032 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop <61226778+yeopyeop-82@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:23:43 +0900 Subject: [PATCH 03/76] Create issue-form.yml --- .github/workflows/issue-form.yml | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/issue-form.yml diff --git a/.github/workflows/issue-form.yml b/.github/workflows/issue-form.yml new file mode 100644 index 0000000..b99b442 --- /dev/null +++ b/.github/workflows/issue-form.yml @@ -0,0 +1,52 @@ +name: 'SSDA Front 이슈 생성' +description: 'SSDA Front Repo에 이슈를 생성하며, 생성된 이슈는 Jira와 연동됩니다.' +labels: [order] +title: '이슈 이름을 작성해주세요' +body: + - type: input + id: parentKey + attributes: + label: '상위 작업 Ticket Number' + description: '상위 작업의 Ticket Number를 기입해주세요' + placeholder: 'DIAR-00' + validations: + required: true + + - type: input + id: description + attributes: + label: '이슈 내용(Description)' + description: '이슈에 대해서 간략히 설명해주세요' + validations: + required: true + + - type: textarea + id: details + attributes: + label: '상세 내용(Details)' + description: '이슈에 대해서 자세히 설명해주세요' + value: | + - About Details + validations: + required: true + + - type: textarea + id: tasks + attributes: + label: '체크리스트(Tasks)' + description: '해당 이슈에 대해 필요한 작업목록을 작성해주세요' + value: | + - [ ] Task1 + - [ ] Task2 + validations: + required: true + + - type: textarea + id: references + attributes: + label: '참조(References)' + description: '해당 이슈과 관련된 레퍼런스를 참조해주세요' + value: | + - Reference1 + validations: + required: false From c503922774bf1c1158071a0fb84f98b9cd7c6a47 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop <61226778+yeopyeop-82@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:25:45 +0900 Subject: [PATCH 04/76] Create create-jira-issue.yml --- .github/workflows/create-jira-issue.yml | 77 +++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 .github/workflows/create-jira-issue.yml diff --git a/.github/workflows/create-jira-issue.yml b/.github/workflows/create-jira-issue.yml new file mode 100644 index 0000000..d12a675 --- /dev/null +++ b/.github/workflows/create-jira-issue.yml @@ -0,0 +1,77 @@ +name: Create Jira issue +on: + issues: + types: + - opened +jobs: + create-issue: + name: Create Jira issue + runs-on: ubuntu-latest + steps: + - name: Login + uses: atlassian/gajira-login@v3 + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + + - name: Checkout main code + uses: actions/checkout@v4 + with: + ref: main + + - name: Issue Parser + uses: stefanbuck/github-issue-praser@v3 + id: issue-parser + with: + template-path: .github/ISSUE_TEMPLATE/issue_form.yml + + - name: Log Issue Parser + run: | + echo '${{ steps.issue-parser.outputs.jsonString }}' + + - name: Convert markdown to Jira Syntax + uses: peter-evans/jira2md@v1 + id: md2jira + with: + input-text: | + ### Github Issue Link + - ${{ github.event.issue.html_url }} + + ${{ github.event.issue.body }} + mode: md2jira + + - name: Create Issue + id: create + uses: atlassian/gajira-create@v3 + with: + project: DIAR + issuetype: Subtask + summary: "${{ github.event.issue.title }}" + description: "${{ steps.md2jira.outputs.output-text }}" + fields: | + { + "parent": { + "key": "${{ steps.issue-parser.outputs.issueparser_parentKey }}" + } + } + + - name: Log created issue + run: echo "Jira Issue ${{ steps.issue-parser.outputs.parentKey }}/${{ steps.create.outputs.issue }} was created" + + - name: Checkout develop code + uses: actions/checkout@v4 + with: + ref: develop + + - name: Create branch with Ticket number + run: | + git checkout -b ${{ steps.create.outputs.issue }} + git push origin ${{ steps.create.outputs.issue }} + + - name: Update issue title + uses: actions-cool/issues-helper@v3 + with: + actions: "update-issue" + token: ${{ secrets.GITHUB_TOKEN }} + title: "${{ steps.create.outputs.issue }} ${{ github.event.issue.title }}" From 4d5ef388369b2ace33482e9bfad36407b88249e2 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop <61226778+yeopyeop-82@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:33:41 +0900 Subject: [PATCH 05/76] Update create-jira-issue.yml From 042031e369888150d7c698280d8cdccfef351031 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop <61226778+yeopyeop-82@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:34:57 +0900 Subject: [PATCH 06/76] Update issue-form.yml --- .github/workflows/issue-form.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/issue-form.yml b/.github/workflows/issue-form.yml index b99b442..ad8c369 100644 --- a/.github/workflows/issue-form.yml +++ b/.github/workflows/issue-form.yml @@ -2,6 +2,7 @@ name: 'SSDA Front 이슈 생성' description: 'SSDA Front Repo에 이슈를 생성하며, 생성된 이슈는 Jira와 연동됩니다.' labels: [order] title: '이슈 이름을 작성해주세요' +on: push body: - type: input id: parentKey From 5c1678a6201c7b38ab1c79c7441ecd602870f2f9 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop <61226778+yeopyeop-82@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:36:25 +0900 Subject: [PATCH 07/76] Update create-jira-issue.yml --- .github/workflows/create-jira-issue.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-jira-issue.yml b/.github/workflows/create-jira-issue.yml index d12a675..ab2fbc3 100644 --- a/.github/workflows/create-jira-issue.yml +++ b/.github/workflows/create-jira-issue.yml @@ -24,7 +24,7 @@ jobs: uses: stefanbuck/github-issue-praser@v3 id: issue-parser with: - template-path: .github/ISSUE_TEMPLATE/issue_form.yml + template-path: .github/workflows/issue_form.yml - name: Log Issue Parser run: | From b769097a7306946603e52c4981466c68ac89c9d9 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 14:08:36 +0900 Subject: [PATCH 08/76] =?UTF-8?q?SCRUM-10=20feat:=20gitignore=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 61 ++++++++++++++----- build.gradle | 16 +++++ settings.gradle | 2 + .../common/code/status/ErrorStatus.java | 4 ++ .../common/code/status/SuccessStatus.java | 4 ++ 5 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java diff --git a/.gitignore b/.gitignore index c2065bc..4301a55 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,14 @@ HELP.md .gradle build/ !gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ +!/src/main//build/ +!/src/test//build/ +*.pem +*.p12 +*.b64 + +### Qclass ### +/src/main/generated/ ### STS ### .apt_generated @@ -14,8 +20,8 @@ build/ .springBeans .sts4-cache bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ +!/src/main//bin/ +!/src/test//bin/ ### IntelliJ IDEA ### .idea @@ -23,15 +29,38 @@ bin/ *.iml *.ipr out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ +!/src/main//out/ +!/src/test//out/ + +# yml +*.yml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +# mac +.DS_Store +._.DS_Store +**/.DS_Store +**/._.DS_Store \ No newline at end of file diff --git a/build.gradle b/build.gradle index db428cd..b25e3d4 100644 --- a/build.gradle +++ b/build.gradle @@ -37,3 +37,19 @@ dependencies { tasks.named('test') { useJUnitPlatform() } + +tasks.withType(JavaCompile).configureEach { + javaCompiler.set(javaToolchains.compilerFor { + languageVersion.set(JavaLanguageVersion.of(17)) + }) +} + +// Ensure toolchains can be downloaded if not available locally +javaToolchains { + repositories { + mavenCentral() + maven { + url = uri("https://download.java.net/java/GA/jdk17/latest/binaries/") + } + } +} diff --git a/settings.gradle b/settings.gradle index 407007e..aed20aa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,3 @@ rootProject.name = 'golagola' + + diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java new file mode 100644 index 0000000..5702d22 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.code.status; + +public enum ErrorStatus { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java new file mode 100644 index 0000000..45bbfbb --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.code.status; + +public enum SuccessStatus { +} From 5f31ad9b25caa023903b4352da17f780667603b8 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 15:42:46 +0900 Subject: [PATCH 09/76] =?UTF-8?q?SCRUM-13=20fix:=20gitignore=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 58 +++++++++++++++--------------------------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 4301a55..fd5c9d8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,9 @@ HELP.md .gradle build/ !gradle/wrapper/gradle-wrapper.jar -!/src/main//build/ -!/src/test//build/ -*.pem -*.p12 -*.b64 - -### Qclass ### -/src/main/generated/ +!**/src/main/**/build/ +!**/src/test/**/build/ +src/main/resources/ ### STS ### .apt_generated @@ -20,8 +15,8 @@ build/ .springBeans .sts4-cache bin/ -!/src/main//bin/ -!/src/test//bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ ### IntelliJ IDEA ### .idea @@ -29,38 +24,17 @@ bin/ *.iml *.ipr out/ -!/src/main//out/ -!/src/test//out/ - -# yml -*.yml - -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ +!**/src/main/**/out/ +!**/src/test/**/out/ -# Package Files # -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* +### VS Code ### +.vscode/ -# mac -.DS_Store -._.DS_Store -**/.DS_Store -**/._.DS_Store \ No newline at end of file +*.xml \ No newline at end of file From 97b141096ffd07b79690558b5d677218cc5e8f49 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 15:46:02 +0900 Subject: [PATCH 10/76] =?UTF-8?q?SCRUM-13=20fix:=20build.gradle=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ src/main/resources/application.properties | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b25e3d4..1bb0af6 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,9 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'mysql:mysql-connector-java:8.0.33' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + } tasks.named('test') { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4d9ab0b..044a88c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ -spring.application.name=golagola +spring.datasource.url=jdbc:mysql://localhost:3306/golagola +spring.datasource.username=root +spring.datasource.password=8253 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file From de9f846aafe2fd2658d3f82d22775c25280baea4 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 15:47:47 +0900 Subject: [PATCH 11/76] =?UTF-8?q?SCRUM-13=20add:=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakaoteck/golagola/global/common/code/BaseCode.java | 4 ++++ .../kakaoteck/golagola/global/common/code/BaseErrorCode.java | 4 ++++ .../kakaoteck/golagola/global/common/code/ErrorReasonDTO.java | 4 ++++ .../com/kakaoteck/golagola/global/common/code/ReasonDTO.java | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java new file mode 100644 index 0000000..01fc4f4 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.code; + +public interface BaseCode { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java new file mode 100644 index 0000000..7407635 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.code; + +public interface BaseErrorCode { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java b/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java new file mode 100644 index 0000000..c112aa6 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.code; + +public record ErrorReasonDTO() { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java b/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java new file mode 100644 index 0000000..5666885 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.code; + +public record ReasonDTO() { +} From a3fa35e6dc0bb6ad218b26cfccc32d72539bff69 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 15:52:35 +0900 Subject: [PATCH 12/76] =?UTF-8?q?SCRUM-13=20feat:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/global/common/code/BaseCode.java | 2 + .../global/common/code/BaseErrorCode.java | 3 ++ .../global/common/code/ErrorReasonDTO.java | 11 +++++- .../global/common/code/ReasonDTO.java | 11 +++++- .../common/code/status/ErrorStatus.java | 39 ++++++++++++++++++- 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java index 01fc4f4..080d3a9 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseCode.java @@ -1,4 +1,6 @@ package com.kakaoteck.golagola.global.common.code; public interface BaseCode { + public ReasonDTO getReason(); + public ReasonDTO getReasonHttpStatus(); } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java index 7407635..58a5c1a 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/BaseErrorCode.java @@ -1,4 +1,7 @@ package com.kakaoteck.golagola.global.common.code; public interface BaseErrorCode { + public ErrorReasonDTO getReason(); + + public ErrorReasonDTO getReasonHttpStatus(); } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java b/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java index c112aa6..aeb94f0 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/ErrorReasonDTO.java @@ -1,4 +1,13 @@ package com.kakaoteck.golagola.global.common.code; -public record ErrorReasonDTO() { +import lombok.Builder; +import org.springframework.http.HttpStatus; + +@Builder +public record ErrorReasonDTO( + HttpStatus httpStatus, + String code, + String message, + boolean isSuccess +) { } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java b/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java index 5666885..f8d3a06 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/ReasonDTO.java @@ -1,4 +1,13 @@ package com.kakaoteck.golagola.global.common.code; -public record ReasonDTO() { +import lombok.Builder; +import org.springframework.http.HttpStatus; + +@Builder +public record ReasonDTO( + HttpStatus httpStatus, + boolean isSuccess, + String code, + String message +) { } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index 5702d22..3d830b8 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -1,4 +1,41 @@ package com.kakaoteck.golagola.global.common.code.status; -public enum ErrorStatus { +import com.kakaoteck.golagola.global.common.code.BaseErrorCode; +import com.kakaoteck.golagola.global.common.code.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ErrorStatus implements BaseErrorCode { + // 기본 에러 + _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), + _BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON400", "잘못된 요청입니다."), + _UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "COMMON401", "인증이 필요합니다."), + _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), + + // User 에러 + _NOT_FOUND_USER(HttpStatus.NOT_FOUND, "USER400", "사용자가 존재하지 않습니다."), + _INVALID_USER(HttpStatus.BAD_REQUEST, "USER401" , "아이디 또는 비밀번호가 틀렸습니다."); + + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ErrorReasonDTO getReason() { + return ErrorReasonDTO.builder().message(message).code(code).isSuccess(false).build(); + } + + @Override + public ErrorReasonDTO getReasonHttpStatus() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .httpStatus(httpStatus) + .build(); + } } From fe4136133e419952d88c082ac4c2caa23696e1ac Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 15:54:28 +0900 Subject: [PATCH 13/76] =?UTF-8?q?SCRUM-13=20feat:=20=EC=84=B1=EA=B3=B5=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/code/status/ErrorStatus.java | 13 ++++++- .../common/code/status/SuccessStatus.java | 38 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index 3d830b8..dc9c95d 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -17,7 +17,18 @@ public enum ErrorStatus implements BaseErrorCode { // User 에러 _NOT_FOUND_USER(HttpStatus.NOT_FOUND, "USER400", "사용자가 존재하지 않습니다."), - _INVALID_USER(HttpStatus.BAD_REQUEST, "USER401" , "아이디 또는 비밀번호가 틀렸습니다."); + _INVALID_USER(HttpStatus.BAD_REQUEST, "USER401" , "아이디 또는 비밀번호가 틀렸습니다."), + + // Security 에러 + INVALID_TOKEN(HttpStatus.BAD_REQUEST, "SEC4001", "잘못된 형식의 토큰입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "SEC4010", "인증이 필요합니다."), + TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED, "SEC4011", "토큰이 만료되었습니다."), + TOKEN_SIGNATURE_ERROR(HttpStatus.UNAUTHORIZED, "SEC4012", "토큰이 위조되었거나 손상되었습니다."), + FORBIDDEN(HttpStatus.FORBIDDEN, "SEC4030", "권한이 없습니다."), + TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "SEC4041", "토큰이 존재하지 않습니다."), + TOKEN_ORGANIZATION_NOT_FOND(HttpStatus.UNAUTHORIZED, "SEC4042", "존재하지 않는 단체입니다."), + INTERNAL_SECURITY_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "SEC5000", "인증 처리 중 서버 에러가 발생했습니다."), + INTERNAL_TOKEN_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "SEC5001", "토큰 처리 중 서버 에러가 발생했습니다."); private final HttpStatus httpStatus; diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java index 45bbfbb..b43c012 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/SuccessStatus.java @@ -1,4 +1,40 @@ package com.kakaoteck.golagola.global.common.code.status; -public enum SuccessStatus { +import com.kakaoteck.golagola.global.common.code.BaseCode; +import com.kakaoteck.golagola.global.common.code.ReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum SuccessStatus implements BaseCode { + + _OK(HttpStatus.OK, "COMMON200", "성공입니다."), + _CREATED(HttpStatus.CREATED, "COMMON201", "요청 성공 및 리소스 생성됨"), + _NO_CONTENT(HttpStatus.NO_CONTENT, "COMMON204", "삭제되었습니다."); + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + + @Override + public ReasonDTO getReason() { + return ReasonDTO.builder(). + message(message). + code(code). + isSuccess(true). + build(); + } + + @Override + public ReasonDTO getReasonHttpStatus() { + return ReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(true) + .httpStatus(httpStatus) + .build(); + } } From 6040988eb891228491bc77fcc1b17e2b96a118c1 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 15:56:27 +0900 Subject: [PATCH 14/76] =?UTF-8?q?SCRUM-13=20feat:=20exception=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/global/common/exception/ExceptionAdvice.java | 4 ++++ .../golagola/global/common/exception/GeneralException.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java diff --git a/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java b/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java new file mode 100644 index 0000000..a94d413 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.exception; + +public class ExceptionAdvice { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java b/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java new file mode 100644 index 0000000..c9f68d0 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.exception; + +public class GeneralException { +} From d28946e29a40313f7ce0d5c1058e3689ae2dc8f8 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 17:58:27 +0900 Subject: [PATCH 15/76] =?UTF-8?q?SCRUM-13=20feat:=20exception=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 27 ++++ .../global/annotation/CheckMonth.java | 17 +++ .../validator/CheckMonthValidator.java | 24 ++++ .../golagola/global/common/ApiResponse.java | 62 +++++++++ .../golagola/global/common/BaseEntity.java | 23 ++++ .../common/exception/ExceptionAdvice.java | 130 +++++++++++++++++- .../common/exception/GeneralException.java | 24 +++- 7 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/kakaoteck/golagola/global/annotation/CheckMonth.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/annotation/validator/CheckMonthValidator.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/ApiResponse.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/BaseEntity.java diff --git a/build.gradle b/build.gradle index 1bb0af6..5eb743f 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,33 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'mysql:mysql-connector-java:8.0.33' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation group: 'org.qlrm', name: 'qlrm', version: '4.0.1' + + // Mail + implementation 'org.springframework.boot:spring-boot-starter-mail' + + // Swagger + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.4' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.0.4' + + // Mysql + runtimeOnly('com.mysql:mysql-connector-j') + + // Jwt + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' + implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' + implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' + implementation 'commons-codec:commons-codec:1.13' + implementation 'com.auth0:java-jwt:3.13.0' + + // Redis + implementation 'org.springframework.boot:spring-boot-starter-data-redis' + + // Querydsl + implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' + annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" } diff --git a/src/main/java/com/kakaoteck/golagola/global/annotation/CheckMonth.java b/src/main/java/com/kakaoteck/golagola/global/annotation/CheckMonth.java new file mode 100644 index 0000000..47c07cb --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/annotation/CheckMonth.java @@ -0,0 +1,17 @@ +package com.kakaoteck.golagola.global.annotation; + +import com.kakaoteck.golagola.global.annotation.validator.CheckMonthValidator; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +@Documented +@Constraint(validatedBy = CheckMonthValidator.class) +@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface CheckMonth { + String message() default "월은 1 이상 12 이하 이어야 합니다."; + Class[] groups() default {}; + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/com/kakaoteck/golagola/global/annotation/validator/CheckMonthValidator.java b/src/main/java/com/kakaoteck/golagola/global/annotation/validator/CheckMonthValidator.java new file mode 100644 index 0000000..8ad66bb --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/annotation/validator/CheckMonthValidator.java @@ -0,0 +1,24 @@ +package com.kakaoteck.golagola.global.annotation.validator; + +import com.kakaoteck.golagola.global.annotation.CheckMonth; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +public class CheckMonthValidator implements ConstraintValidator { + + @Override + public void initialize(CheckMonth constraintAnnotation) { + ConstraintValidator.super.initialize(constraintAnnotation); + } + + @Override + public boolean isValid(Integer month, ConstraintValidatorContext context) { + if (month == null || month < 1 || month > 12) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate("월은 1 이상 12 이하 이어야 합니다.") + .addConstraintViolation(); + return false; + } + return true; + } +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/ApiResponse.java b/src/main/java/com/kakaoteck/golagola/global/common/ApiResponse.java new file mode 100644 index 0000000..f43a3be --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/ApiResponse.java @@ -0,0 +1,62 @@ +package com.kakaoteck.golagola.global.common; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.kakaoteck.golagola.global.common.code.BaseCode; +import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; +import com.kakaoteck.golagola.global.common.code.status.SuccessStatus; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"isSuccess", "code", "message", "result"}) +public class ApiResponse { + + @JsonProperty("isSuccess") + private final Boolean isSuccess; + private final String code; + private final String message; + @JsonInclude(JsonInclude.Include.NON_NULL) + private T result; + + // 성공한 경우 응답 생성 + public static ApiResponse onSuccess(T result) { + return new ApiResponse<>(true, SuccessStatus._OK.getCode() , + SuccessStatus._OK.getMessage(), result); + } + + public static ApiResponse of(BaseCode code, T result) { + return new ApiResponse<>(true, code.getReasonHttpStatus().code() , + code.getReasonHttpStatus().message(), result); + } + + // 실패한 경우 응답 생성 + public static ApiResponse onFailure(String code, String message, T data) { + return new ApiResponse<>(false, code, message, data); + } + + // 데이터 없이 실패한 경우 응답 생성 + public static ApiResponse onFailure(String code, String message) { + return new ApiResponse<>(false, code, message, null); + } + + // 기본 실패 응답 생성 + public static ApiResponse onFailure(T result) { + return new ApiResponse<>(false, ErrorStatus._BAD_REQUEST.getCode(), + ErrorStatus._BAD_REQUEST.getMessage(), result); + } + + // 게시된 경우 응답 생성 + public static ApiResponse created(T result) { + return new ApiResponse<>(true, SuccessStatus._CREATED.getCode(), + SuccessStatus._CREATED.getMessage(), result); + } + + // 삭제된 경우 응답 생성 + public static ApiResponse noContent() { + return new ApiResponse<>(true, SuccessStatus._NO_CONTENT.getCode(), + SuccessStatus._NO_CONTENT.getMessage(), null); + } +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/BaseEntity.java b/src/main/java/com/kakaoteck/golagola/global/common/BaseEntity.java new file mode 100644 index 0000000..87b6c79 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/BaseEntity.java @@ -0,0 +1,23 @@ +package com.kakaoteck.golagola.global.common; + +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public class BaseEntity { + + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime modifiedAt; + +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java b/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java index a94d413..3e60c95 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java @@ -1,4 +1,132 @@ package com.kakaoteck.golagola.global.common.exception; -public class ExceptionAdvice { +import com.kakaoteck.golagola.global.common.ApiResponse; +import com.kakaoteck.golagola.global.common.code.ErrorReasonDTO; +import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ExceptionAdvice extends ResponseEntityExceptionHandler { + + + @org.springframework.web.bind.annotation.ExceptionHandler + public ResponseEntity validation(ConstraintViolationException e, WebRequest request) { + String errorMessage = e.getConstraintViolations().stream() + .map(constraintViolation -> constraintViolation.getMessage()) + .findFirst() + .orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생")); + + return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY, request); + } + + + @Override + public ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException e, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request) { + + Map errors = new LinkedHashMap<>(); + + e.getBindingResult().getFieldErrors().stream() + .forEach( + fieldError -> { + String fieldName = fieldError.getField(); + String errorMessage = + Optional.ofNullable(fieldError.getDefaultMessage()).orElse(""); + errors.merge( + fieldName, + errorMessage, + (existingErrorMessage, newErrorMessage) -> + existingErrorMessage + ", " + newErrorMessage); + }); + + return handleExceptionInternalArgs( + e, HttpHeaders.EMPTY, ErrorStatus.valueOf("_BAD_REQUEST"), request, errors); + } + + @org.springframework.web.bind.annotation.ExceptionHandler + public ResponseEntity exception(Exception e, WebRequest request) { + e.printStackTrace(); + + return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(), request, e.getMessage()); + } + + @ExceptionHandler(value = com.example.alcohol_free_day.global.common.exception.GeneralException.class) + public ResponseEntity onThrowException(com.example.alcohol_free_day.global.common.exception.GeneralException generalException, HttpServletRequest request) { + ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus(); + return handleExceptionInternal(generalException, errorReasonHttpStatus, null, request); + } + + private ResponseEntity handleExceptionInternal(Exception e, ErrorReasonDTO reason, + HttpHeaders headers, HttpServletRequest request) { + + ApiResponse body = ApiResponse.onFailure(reason.code(), reason.message(), null); +// e.printStackTrace(); + + WebRequest webRequest = new ServletWebRequest(request); + return super.handleExceptionInternal( + e, + body, + headers, + reason.httpStatus(), + webRequest + ); + } + + private ResponseEntity handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorPoint); + return super.handleExceptionInternal( + e, + body, + headers, + status, + request + ); + } + + private ResponseEntity handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus, + WebRequest request, Map errorArgs) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorArgs); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } + + private ResponseEntity handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, WebRequest request) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java b/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java index c9f68d0..c918300 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java @@ -1,4 +1,22 @@ -package com.kakaoteck.golagola.global.common.exception; +package com.example.alcohol_free_day.global.common.exception; -public class GeneralException { -} +import com.kakaoteck.golagola.global.common.code.BaseErrorCode; +import com.kakaoteck.golagola.global.common.code.ErrorReasonDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GeneralException extends RuntimeException { + + private BaseErrorCode code; + + public ErrorReasonDTO getErrorReason() { + return this.code.getReason(); + } + + public ErrorReasonDTO getErrorReasonHttpStatus() { + return this.code.getReasonHttpStatus(); + } + +} \ No newline at end of file From ee8e7c3da74f4039df5a72d2947e0f4ff939481c Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Thu, 8 Aug 2024 18:00:04 +0900 Subject: [PATCH 16/76] SCRUM-13 fix: GeneralException --- .../golagola/global/common/exception/GeneralException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java b/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java index c918300..803ca68 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/exception/GeneralException.java @@ -1,4 +1,4 @@ -package com.example.alcohol_free_day.global.common.exception; +package com.kakaoteck.golagola.global.common.exception; import com.kakaoteck.golagola.global.common.code.BaseErrorCode; import com.kakaoteck.golagola.global.common.code.ErrorReasonDTO; From 050f40900fcd98625dfbdd767d91c6505e297aff Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 14:08:04 +0900 Subject: [PATCH 17/76] =?UTF-8?q?SCRUM-34=20feat:=20Domain=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/global/common/exception/ExceptionAdvice.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java b/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java index 3e60c95..b737a20 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/exception/ExceptionAdvice.java @@ -72,8 +72,8 @@ public ResponseEntity exception(Exception e, WebRequest request) { return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(), request, e.getMessage()); } - @ExceptionHandler(value = com.example.alcohol_free_day.global.common.exception.GeneralException.class) - public ResponseEntity onThrowException(com.example.alcohol_free_day.global.common.exception.GeneralException generalException, HttpServletRequest request) { + @ExceptionHandler(value = com.kakaoteck.golagola.global.common.exception.GeneralException.class) + public ResponseEntity onThrowException(com.kakaoteck.golagola.global.common.exception.GeneralException generalException, HttpServletRequest request) { ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus(); return handleExceptionInternal(generalException, errorReasonHttpStatus, null, request); } From 3980fc7165fa5a936d134d15dce52a3357961e2a Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 14:29:35 +0900 Subject: [PATCH 18/76] =?UTF-8?q?SCRUM-35=20feat:=20Buyer=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EA=B5=AC=EC=84=B1=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 76 +++++++++++++++++++ .../domain/buyer/entity/enums/Gender.java | 5 ++ .../domain/buyer/entity/enums/Role.java | 5 ++ 3 files changed, 86 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java new file mode 100644 index 0000000..fc5a08a --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -0,0 +1,76 @@ +package com.kakaoteck.golagola.domain.buyer.entity; + +import com.kakaoteck.golagola.domain.buyer.entity.enums.Gender; +import com.kakaoteck.golagola.domain.buyer.entity.enums.Role; +import com.kakaoteck.golagola.global.common.BaseEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Collection; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class Buyer extends BaseEntity implements UserDetails { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long BuyerId; + + private String nickname; + private String realName; + private Gender gender; + private String email; + private String address; + private String phoneNum; + private Role role; + private LocalDate registerDate; + + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return null; + } + + @Override + public boolean isAccountNonExpired() { + return UserDetails.super.isAccountNonExpired(); + } + + @Override + public boolean isAccountNonLocked() { + return UserDetails.super.isAccountNonLocked(); + } + + @Override + public boolean isCredentialsNonExpired() { + return UserDetails.super.isCredentialsNonExpired(); + } + + @Override + public boolean isEnabled() { + return UserDetails.super.isEnabled(); + } +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java new file mode 100644 index 0000000..6d963d5 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java @@ -0,0 +1,5 @@ +package com.kakaoteck.golagola.domain.buyer.entity.enums; + +public enum Gender { + MALE, FEMALE +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java new file mode 100644 index 0000000..1ac2206 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java @@ -0,0 +1,5 @@ +package com.kakaoteck.golagola.domain.buyer.entity.enums; + +public enum Role { + BUYER, SELLER +} From 7255d3b9275d140d2658082b8e20c2ff990eca51 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 14:31:36 +0900 Subject: [PATCH 19/76] =?UTF-8?q?SCRUM-35=20feat:=20Buyer=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=84=B1=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/buyer/repository/BuyerRepository.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/repository/BuyerRepository.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/repository/BuyerRepository.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/repository/BuyerRepository.java new file mode 100644 index 0000000..c21a78f --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/repository/BuyerRepository.java @@ -0,0 +1,13 @@ +package com.kakaoteck.golagola.domain.buyer.repository; + +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface BuyerRepository extends JpaRepository { + Optional findByEmail(String email); + boolean existsByEmail(String email); +} From 41200ef09743be85831b01e617eb84f7900dc1ff Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 14:52:49 +0900 Subject: [PATCH 20/76] =?UTF-8?q?SCRUM-36=20feat:=20Seller=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 5 +- .../domain/buyer/entity/enums/Gender.java | 5 -- .../domain/buyer/entity/enums/Role.java | 5 -- .../golagola/domain/seller/entity/Seller.java | 75 +++++++++++++++++++ .../golagola/global/common/enums/Gender.java | 5 ++ .../golagola/global/common/enums/Role.java | 5 ++ 6 files changed, 87 insertions(+), 13 deletions(-) delete mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java delete mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/enums/Gender.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/enums/Role.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index fc5a08a..e1e54bf 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -1,7 +1,7 @@ package com.kakaoteck.golagola.domain.buyer.entity; -import com.kakaoteck.golagola.domain.buyer.entity.enums.Gender; -import com.kakaoteck.golagola.domain.buyer.entity.enums.Role; +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; import com.kakaoteck.golagola.global.common.BaseEntity; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -15,7 +15,6 @@ import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; -import java.time.LocalDateTime; import java.util.Collection; @Entity diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java deleted file mode 100644 index 6d963d5..0000000 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Gender.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.kakaoteck.golagola.domain.buyer.entity.enums; - -public enum Gender { - MALE, FEMALE -} diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java deleted file mode 100644 index 1ac2206..0000000 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/enums/Role.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.kakaoteck.golagola.domain.buyer.entity.enums; - -public enum Role { - BUYER, SELLER -} diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java new file mode 100644 index 0000000..98b7223 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -0,0 +1,75 @@ +package com.kakaoteck.golagola.domain.seller.entity; + +import com.fasterxml.jackson.databind.ser.Serializers; +import com.kakaoteck.golagola.global.common.BaseEntity; +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.time.LocalDate; +import java.util.Collection; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class Seller extends BaseEntity implements UserDetails { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long sellerId; + + private String nickname; + private Gender gender; + private String email; + private String address; + private String phoneNum; + private Role role; + private String realName; + private LocalDate registerDate; + + @Override + public Collection getAuthorities() { + return null; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return null; + } + + @Override + public boolean isAccountNonExpired() { + return UserDetails.super.isAccountNonExpired(); + } + + @Override + public boolean isAccountNonLocked() { + return UserDetails.super.isAccountNonLocked(); + } + + @Override + public boolean isCredentialsNonExpired() { + return UserDetails.super.isCredentialsNonExpired(); + } + + @Override + public boolean isEnabled() { + return UserDetails.super.isEnabled(); + } +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/Gender.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/Gender.java new file mode 100644 index 0000000..4c22039 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/Gender.java @@ -0,0 +1,5 @@ +package com.kakaoteck.golagola.global.common.enums; + +public enum Gender { + MALE, FEMALE +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/Role.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/Role.java new file mode 100644 index 0000000..855b444 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/Role.java @@ -0,0 +1,5 @@ +package com.kakaoteck.golagola.global.common.enums; + +public enum Role { + BUYER, SELLER +} From e5cc426010f163f95bf88da26199d0fb9a397390 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 14:54:57 +0900 Subject: [PATCH 21/76] =?UTF-8?q?SCRUM-36=20feat:=20Seller=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/seller/repository/SellerRepository.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java b/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java new file mode 100644 index 0000000..fa676f0 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java @@ -0,0 +1,11 @@ +package com.kakaoteck.golagola.domain.seller.repository; + +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface SellerRepository extends JpaRepository { + Optional findByEmail(String email); + boolean existsByEmail(String email); +} From 487e1021b42fd439254e72ecc5946e004c3a221a Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 15:02:33 +0900 Subject: [PATCH 22/76] =?UTF-8?q?SCRUM-37=20feat:=20Review=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/review/entity/Review.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java new file mode 100644 index 0000000..e54b55c --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -0,0 +1,33 @@ +package com.kakaoteck.golagola.domain.review.entity; + +import com.kakaoteck.golagola.global.common.BaseEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class Review extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long reviewId; + + private String reviewTitle; + private Long reviewStar; + private String reviewContent; + private LocalDate reviewCreateTime; + private LocalDate reviewUpdateTime; + + +} From ac91ae7a18807d0576f759fca64dcf390687e4f0 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 15:04:37 +0900 Subject: [PATCH 23/76] =?UTF-8?q?SCRUM-37=20feat:=20Review=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/review/repository/ReviewRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java b/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java new file mode 100644 index 0000000..2e1401a --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java @@ -0,0 +1,8 @@ +package com.kakaoteck.golagola.domain.review.repository; + +import com.kakaoteck.golagola.domain.review.entity.Review; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReviewRepository extends JpaRepository { + +} From fa41bc22872b1e504105df0bdba4507430ed406f Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 15:54:53 +0900 Subject: [PATCH 24/76] =?UTF-8?q?SCRUM-38=20feat:=20Order=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/order/entity/Order.java | 35 +++++++++++++++++++ .../order/repository/OrderRepository.java | 7 ++++ .../global/common/enums/OrderStatus.java | 5 +++ 3 files changed, 47 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/enums/OrderStatus.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java new file mode 100644 index 0000000..27ac129 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -0,0 +1,35 @@ +package com.kakaoteck.golagola.domain.order.entity; + +import com.kakaoteck.golagola.global.common.BaseEntity; +import com.kakaoteck.golagola.global.common.enums.OrderStatus; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class Order extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long orderId; + + private boolean isPay; + private LocalDate paymentDate; + private String orderAddress; + private String orderNotes; + private LocalDate orderArrival; + private LocalDate orderExpectation; + private OrderStatus orderStatus; + private LocalDate orderDate; +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java b/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java new file mode 100644 index 0000000..128aac7 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java @@ -0,0 +1,7 @@ +package com.kakaoteck.golagola.domain.order.repository; + +import com.kakaoteck.golagola.domain.order.entity.Order; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface OrderRepository extends JpaRepository { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/OrderStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/OrderStatus.java new file mode 100644 index 0000000..d65c43a --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/OrderStatus.java @@ -0,0 +1,5 @@ +package com.kakaoteck.golagola.global.common.enums; + +public enum OrderStatus { + READY, DELIVERY, COMPLETE, CALCEL +} From ff5ff52f70c87356a6016b0ee3cea554994df09e Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:03:57 +0900 Subject: [PATCH 25/76] =?UTF-8?q?SCRUM-39=20feat:=20Product=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/product/entity/Product.java | 44 +++++++++++++++++++ .../global/common/enums/Category.java | 4 ++ .../global/common/enums/DetailCategory.java | 4 ++ 3 files changed, 52 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java create mode 100644 src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java new file mode 100644 index 0000000..922eb8a --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -0,0 +1,44 @@ +package com.kakaoteck.golagola.domain.product.entity; + +import com.kakaoteck.golagola.domain.review.entity.Review; +import com.kakaoteck.golagola.global.common.BaseEntity; +import com.kakaoteck.golagola.global.common.enums.Category; +import com.kakaoteck.golagola.global.common.enums.DetailCategory; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalTime; +import java.util.List; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class Product extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long productId; + + private String productName; + private String productExplanation; + private String productImage; + private Long productPrice; + private Long productInventory; + private Category category; + private DetailCategory detailCategory; + private Long discount; + private LocalTime createTime; + private LocalTime updateTime; + private Long productQuantity; + private Float predictReviewStar; + private Float productStar; + +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java new file mode 100644 index 0000000..ca4112e --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.enums; + +public enum Category { +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java new file mode 100644 index 0000000..158d06d --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.global.common.enums; + +public enum DetailCategory { +} From c2b465a6118d6865a2c1ed7050ae94cd2308482d Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:04:58 +0900 Subject: [PATCH 26/76] =?UTF-8?q?SCRUM-39=20feat:=20Product=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/product/repository/ProductRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java b/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java new file mode 100644 index 0000000..a88a30a --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java @@ -0,0 +1,8 @@ +package com.kakaoteck.golagola.domain.product.repository; + +import com.kakaoteck.golagola.domain.product.entity.Product; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProductRepository extends JpaRepository { + +} From 0aa43e27d3cefb38c7bf308ba8928296ac69647b Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:23:35 +0900 Subject: [PATCH 27/76] =?UTF-8?q?SCRUM-45=20fix:=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakaoteck/golagola/domain/buyer/entity/Buyer.java | 6 ++---- .../com/kakaoteck/golagola/domain/order/entity/Order.java | 6 ++---- .../kakaoteck/golagola/domain/product/entity/Product.java | 6 ++---- .../com/kakaoteck/golagola/domain/review/entity/Review.java | 6 ++---- .../com/kakaoteck/golagola/domain/seller/entity/Seller.java | 6 ++---- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index e1e54bf..0dea722 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -3,10 +3,7 @@ import com.kakaoteck.golagola.global.common.enums.Gender; import com.kakaoteck.golagola.global.common.enums.Role; import com.kakaoteck.golagola.global.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -22,6 +19,7 @@ @AllArgsConstructor @Builder @Getter +@Table(name = "buyer_table") public class Buyer extends BaseEntity implements UserDetails { @Id diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java index 27ac129..0c9058f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -2,10 +2,7 @@ import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.OrderStatus; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -18,6 +15,7 @@ @AllArgsConstructor @Getter @Builder +@Table(name = "order_table") // order가 mySQL 예약어임 이슈 ! public class Order extends BaseEntity { @Id diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index 922eb8a..6c70cdb 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -4,10 +4,7 @@ import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.Category; import com.kakaoteck.golagola.global.common.enums.DetailCategory; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -21,6 +18,7 @@ @AllArgsConstructor @Getter @Builder +@Table(name = "product_table") public class Product extends BaseEntity { @Id diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java index e54b55c..fdecc2d 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -1,10 +1,7 @@ package com.kakaoteck.golagola.domain.review.entity; import com.kakaoteck.golagola.global.common.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -17,6 +14,7 @@ @AllArgsConstructor @Builder @Getter +@Table(name = "review_table") public class Review extends BaseEntity { @Id diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 98b7223..54d31ac 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -4,10 +4,7 @@ import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.Gender; import com.kakaoteck.golagola.global.common.enums.Role; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -23,6 +20,7 @@ @AllArgsConstructor @Builder @Getter +@Table(name = "seller_table") public class Seller extends BaseEntity implements UserDetails { @Id From 0e74b2f305c8bfa2af8c2d2d1f46f5a82dd2425c Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:30:53 +0900 Subject: [PATCH 28/76] =?UTF-8?q?SCRUM-45=20feat:=20cart=20table=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/cart/entity/Cart.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java new file mode 100644 index 0000000..2677ca1 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -0,0 +1,23 @@ +package com.kakaoteck.golagola.domain.cart.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class Cart { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long cartId; + +} From d4ab7142b604b7e6faeff284f2eb7a8956de8627 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:34:59 +0900 Subject: [PATCH 29/76] =?UTF-8?q?SCRUM-45=20feat:=20orderProduct=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/cart/entity/Cart.java | 6 ++--- .../cart/repository/CartRepository.java | 9 ++++++++ .../order/repository/OrderRepository.java | 2 ++ .../orderProduct/entity/OrderProduct.java | 23 +++++++++++++++++++ .../repository/OrderProductRepository.java | 10 ++++++++ .../product/repository/ProductRepository.java | 2 ++ .../review/repository/ReviewRepository.java | 2 ++ .../seller/repository/SellerRepository.java | 2 ++ 8 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartRepository.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/orderProduct/repository/OrderProductRepository.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index 2677ca1..8ca012f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -1,9 +1,6 @@ package com.kakaoteck.golagola.domain.cart.entity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -14,6 +11,7 @@ @AllArgsConstructor @Getter @Builder +@Table(name = "cart_table") public class Cart { @Id diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartRepository.java b/src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartRepository.java new file mode 100644 index 0000000..75a5e9e --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartRepository.java @@ -0,0 +1,9 @@ +package com.kakaoteck.golagola.domain.cart.repository; + +import com.kakaoteck.golagola.domain.cart.entity.Cart; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CartRepository extends JpaRepository { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java b/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java index 128aac7..cee1bbe 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/repository/OrderRepository.java @@ -2,6 +2,8 @@ import com.kakaoteck.golagola.domain.order.entity.Order; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface OrderRepository extends JpaRepository { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java new file mode 100644 index 0000000..6f944d5 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java @@ -0,0 +1,23 @@ +package com.kakaoteck.golagola.domain.orderProduct.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +@Table(name = "order_product_table") +public class OrderProduct { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long orderProductId; + + private Long quantity; + private Long orderPrice; +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/repository/OrderProductRepository.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/repository/OrderProductRepository.java new file mode 100644 index 0000000..8162330 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/repository/OrderProductRepository.java @@ -0,0 +1,10 @@ +package com.kakaoteck.golagola.domain.orderProduct.repository; + +import com.kakaoteck.golagola.domain.orderProduct.entity.OrderProduct; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface OrderProductRepository extends JpaRepository { + +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java b/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java index a88a30a..bb1937e 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/repository/ProductRepository.java @@ -2,7 +2,9 @@ import com.kakaoteck.golagola.domain.product.entity.Product; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface ProductRepository extends JpaRepository { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java b/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java index 2e1401a..9694052 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/repository/ReviewRepository.java @@ -2,7 +2,9 @@ import com.kakaoteck.golagola.domain.review.entity.Review; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface ReviewRepository extends JpaRepository { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java b/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java index fa676f0..f4ea8c4 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/repository/SellerRepository.java @@ -2,9 +2,11 @@ import com.kakaoteck.golagola.domain.seller.entity.Seller; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.Optional; +@Repository public interface SellerRepository extends JpaRepository { Optional findByEmail(String email); boolean existsByEmail(String email); From 064825d3e8982655640eb5d619c7a3a41b16761e Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:43:17 +0900 Subject: [PATCH 30/76] =?UTF-8?q?SCRUM-45=20feat:=20Seller=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakaoteck/golagola/domain/order/entity/Order.java | 5 +++++ .../golagola/domain/product/entity/Product.java | 5 +++++ .../golagola/domain/seller/entity/Seller.java | 10 ++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java index 0c9058f..a0324ef 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.order.entity; +import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.OrderStatus; import jakarta.persistence.*; @@ -22,6 +23,10 @@ public class Order extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long orderId; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "seller_id") + private Seller seller; + private boolean isPay; private LocalDate paymentDate; private String orderAddress; diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index 6c70cdb..44bb917 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.product.entity; import com.kakaoteck.golagola.domain.review.entity.Review; +import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.Category; import com.kakaoteck.golagola.global.common.enums.DetailCategory; @@ -25,6 +26,10 @@ public class Product extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long productId; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "seller_id") + private Seller seller; + private String productName; private String productExplanation; private String productImage; diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 54d31ac..7f943d2 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -1,6 +1,8 @@ package com.kakaoteck.golagola.domain.seller.entity; import com.fasterxml.jackson.databind.ser.Serializers; +import com.kakaoteck.golagola.domain.order.entity.Order; +import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.Gender; import com.kakaoteck.golagola.global.common.enums.Role; @@ -13,7 +15,9 @@ import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; @Entity @NoArgsConstructor @@ -36,6 +40,12 @@ public class Seller extends BaseEntity implements UserDetails { private String realName; private LocalDate registerDate; + @OneToMany(mappedBy = "seller", cascade = CascadeType.ALL) + private List productList = new ArrayList<>(); + + @OneToMany(mappedBy = "seller", cascade = CascadeType.ALL) + private List orderList = new ArrayList<>(); + @Override public Collection getAuthorities() { return null; From 2adefce8b9f0b5b13c7e26a4e05cde55bdcce586 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 16:59:58 +0900 Subject: [PATCH 31/76] =?UTF-8?q?SCRUM-45=20feat:=20Buyer=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 13 +++++++++++++ .../kakaoteck/golagola/domain/cart/entity/Cart.java | 5 +++++ .../golagola/domain/order/entity/Order.java | 5 +++++ .../golagola/domain/review/entity/Review.java | 5 +++++ 4 files changed, 28 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index 0dea722..98f25a2 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -1,5 +1,8 @@ package com.kakaoteck.golagola.domain.buyer.entity; +import com.kakaoteck.golagola.domain.cart.entity.Cart; +import com.kakaoteck.golagola.domain.order.entity.Order; +import com.kakaoteck.golagola.domain.review.entity.Review; import com.kakaoteck.golagola.global.common.enums.Gender; import com.kakaoteck.golagola.global.common.enums.Role; import com.kakaoteck.golagola.global.common.BaseEntity; @@ -13,6 +16,7 @@ import java.time.LocalDate; import java.util.Collection; +import java.util.List; @Entity @NoArgsConstructor @@ -35,6 +39,15 @@ public class Buyer extends BaseEntity implements UserDetails { private Role role; private LocalDate registerDate; + @OneToOne(mappedBy = "buyer", cascade = CascadeType.ALL) + private Cart cart; + + @OneToMany(mappedBy = "buyer", cascade = CascadeType.ALL) + private List reviewList; + + @OneToMany(mappedBy = "buyer", cascade = CascadeType.ALL) + private List orderList; + @Override public Collection getAuthorities() { diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index 8ca012f..df3f0ae 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.cart.entity; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -14,6 +15,10 @@ @Table(name = "cart_table") public class Cart { + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "buyer_id") + private Buyer buyer; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long cartId; diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java index a0324ef..55fafb4 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.order.entity; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.OrderStatus; @@ -27,6 +28,10 @@ public class Order extends BaseEntity { @JoinColumn(name = "seller_id") private Seller seller; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "buyer_id") + private Buyer buyer; + private boolean isPay; private LocalDate paymentDate; private String orderAddress; diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java index fdecc2d..618580f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.review.entity; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; import com.kakaoteck.golagola.global.common.BaseEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -17,6 +18,10 @@ @Table(name = "review_table") public class Review extends BaseEntity { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "buyer_id") + private Buyer buyer; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long reviewId; From 5f3523a645a97e7b4fae0f8745dc8a98228006aa Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:02:05 +0900 Subject: [PATCH 32/76] =?UTF-8?q?SCRUM-45=20feat:=20cart=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakaoteck/golagola/domain/cart/entity/Cart.java | 6 ++++++ .../kakaoteck/golagola/domain/product/entity/Product.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index df3f0ae..cc0898f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -1,12 +1,15 @@ package com.kakaoteck.golagola.domain.cart.entity; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.product.entity.Product; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.List; + @Entity @NoArgsConstructor @AllArgsConstructor @@ -19,6 +22,9 @@ public class Cart { @JoinColumn(name = "buyer_id") private Buyer buyer; + @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL) + private List productList; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long cartId; diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index 44bb917..d68c695 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.product.entity; +import com.kakaoteck.golagola.domain.cart.entity.Cart; import com.kakaoteck.golagola.domain.review.entity.Review; import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.global.common.BaseEntity; @@ -30,6 +31,10 @@ public class Product extends BaseEntity { @JoinColumn(name = "seller_id") private Seller seller; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "cart_id") + private Cart cart; + private String productName; private String productExplanation; private String productImage; From 01ecbb004bd529f89174550a3cb2ce7e9501b923 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:07:05 +0900 Subject: [PATCH 33/76] =?UTF-8?q?SCRUM-45=20feat:=20product=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/orderProduct/entity/OrderProduct.java | 5 +++++ .../kakaoteck/golagola/domain/product/entity/Product.java | 7 +++++++ .../kakaoteck/golagola/domain/review/entity/Review.java | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java index 6f944d5..84db05c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.orderProduct.entity; +import com.kakaoteck.golagola.domain.product.entity.Product; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -18,6 +19,10 @@ public class OrderProduct { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long orderProductId; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "product_id") + private Product product; + private Long quantity; private Long orderPrice; } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index d68c695..dc3b873 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.product.entity; import com.kakaoteck.golagola.domain.cart.entity.Cart; +import com.kakaoteck.golagola.domain.orderProduct.entity.OrderProduct; import com.kakaoteck.golagola.domain.review.entity.Review; import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.global.common.BaseEntity; @@ -35,6 +36,12 @@ public class Product extends BaseEntity { @JoinColumn(name = "cart_id") private Cart cart; + @OneToMany(mappedBy = "product", cascade = CascadeType.ALL) + private List reviewList; + + @OneToMany(mappedBy = "product", cascade = CascadeType.ALL) + private List orderProductList; + private String productName; private String productExplanation; private String productImage; diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java index 618580f..ea03af1 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.review.entity; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.global.common.BaseEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -22,6 +23,10 @@ public class Review extends BaseEntity { @JoinColumn(name = "buyer_id") private Buyer buyer; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "product_id") + private Product product; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long reviewId; From 03a2db9291991bd2226709d5e8a7274a8384cecb Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:10:08 +0900 Subject: [PATCH 34/76] =?UTF-8?q?SCRUM-45=20feat:=20OrderProduct=20?= =?UTF-8?q?=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/orderProduct/entity/OrderProduct.java | 4 ++++ .../com/kakaoteck/golagola/domain/review/entity/Review.java | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java index 84db05c..0efa3f1 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.orderProduct.entity; import com.kakaoteck.golagola.domain.product.entity.Product; +import com.kakaoteck.golagola.domain.review.entity.Review; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -23,6 +24,9 @@ public class OrderProduct { @JoinColumn(name = "product_id") private Product product; + @OneToOne(mappedBy = "orderProduct", cascade = CascadeType.ALL) + private Review review; + private Long quantity; private Long orderPrice; } diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java index ea03af1..b93ff5c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.review.entity; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.orderProduct.entity.OrderProduct; import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.global.common.BaseEntity; import jakarta.persistence.*; @@ -27,6 +28,10 @@ public class Review extends BaseEntity { @JoinColumn(name = "product_id") private Product product; + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "order_product_id") + private OrderProduct orderProduct; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long reviewId; From 7bd2acccf778b424bb706c6d3a050ddc23330a70 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:11:52 +0900 Subject: [PATCH 35/76] =?UTF-8?q?SCRUM-45=20feat:=20order=20=EC=97=B0?= =?UTF-8?q?=EA=B4=80=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kakaoteck/golagola/domain/order/entity/Order.java | 5 +++++ .../golagola/domain/orderProduct/entity/OrderProduct.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java index 55fafb4..1a5b297 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.order.entity; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.orderProduct.entity.OrderProduct; import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.OrderStatus; @@ -11,6 +12,7 @@ import lombok.NoArgsConstructor; import java.time.LocalDate; +import java.util.List; @Entity @NoArgsConstructor @@ -32,6 +34,9 @@ public class Order extends BaseEntity { @JoinColumn(name = "buyer_id") private Buyer buyer; + @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) + private List orderProductList; + private boolean isPay; private LocalDate paymentDate; private String orderAddress; diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java index 0efa3f1..43591b6 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.orderProduct.entity; +import com.kakaoteck.golagola.domain.order.entity.Order; import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.domain.review.entity.Review; import jakarta.persistence.*; @@ -24,6 +25,10 @@ public class OrderProduct { @JoinColumn(name = "product_id") private Product product; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "order_id") + private Order order; + @OneToOne(mappedBy = "orderProduct", cascade = CascadeType.ALL) private Review review; From 149c0f87c2bed05b53067e0e0791725ae58de4b9 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:21:17 +0900 Subject: [PATCH 36/76] =?UTF-8?q?SCRUM-47=20feat:=20Buyer=20Column=20?= =?UTF-8?q?=EB=B3=84=20Nullable=20=EC=84=A4=EC=A0=95=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index 98f25a2..402f042 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -30,13 +30,28 @@ public class Buyer extends BaseEntity implements UserDetails { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long BuyerId; + @Column(nullable = false) private String nickname; + + @Column(nullable = false) private String realName; + + @Column(nullable = false) private Gender gender; + + @Column(nullable = false) private String email; + + @Column(nullable = false) private String address; + + @Column(nullable = false) private String phoneNum; + + @Column(nullable = false) private Role role; + + @Column(nullable = false) private LocalDate registerDate; @OneToOne(mappedBy = "buyer", cascade = CascadeType.ALL) @@ -48,7 +63,6 @@ public class Buyer extends BaseEntity implements UserDetails { @OneToMany(mappedBy = "buyer", cascade = CascadeType.ALL) private List orderList; - @Override public Collection getAuthorities() { return null; @@ -83,4 +97,6 @@ public boolean isCredentialsNonExpired() { public boolean isEnabled() { return UserDetails.super.isEnabled(); } + + } From 9b0c6882ad649555adcc501e3437f6fa0144dc5b Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:24:03 +0900 Subject: [PATCH 37/76] =?UTF-8?q?SCRUM-47=20feat:=20Buyer=20from=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index 402f042..c927b7d 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -28,7 +28,7 @@ public class Buyer extends BaseEntity implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long BuyerId; + private Long buyerId; @Column(nullable = false) private String nickname; @@ -98,5 +98,19 @@ public boolean isEnabled() { return UserDetails.super.isEnabled(); } + public static Buyer from(Long buyerId, String nickname, String realName, Gender gender, String email, + String address, String phoneNum, Role role, LocalDate registerDate) { + return Buyer.builder() + .buyerId(buyerId) + .nickname(nickname) + .realName(realName) + .gender(gender) + .email(email) + .address(address) + .phoneNum(phoneNum) + .role(role) + .registerDate(registerDate) + .build(); + } } From b68a24b674d0b7b3a48d3ccc6ade0c8d414f7c2c Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:27:28 +0900 Subject: [PATCH 38/76] =?UTF-8?q?SCRUM-47=20feat:=20order=20Column=20?= =?UTF-8?q?=EB=B3=84=20Nullable=20=EC=84=A4=EC=A0=95=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 2 ++ .../golagola/domain/order/entity/Order.java | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index c927b7d..064acc2 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -36,6 +36,7 @@ public class Buyer extends BaseEntity implements UserDetails { @Column(nullable = false) private String realName; + @Enumerated(EnumType.STRING) @Column(nullable = false) private Gender gender; @@ -48,6 +49,7 @@ public class Buyer extends BaseEntity implements UserDetails { @Column(nullable = false) private String phoneNum; + @Enumerated(EnumType.STRING) @Column(nullable = false) private Role role; diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java index 1a5b297..ad1a170 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -37,12 +37,48 @@ public class Order extends BaseEntity { @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List orderProductList; + @Column(nullable = false) private boolean isPay; + + @Column(nullable = false) private LocalDate paymentDate; + + @Column(nullable = false) private String orderAddress; + + @Column(nullable = true) private String orderNotes; + + @Column(nullable = false) private LocalDate orderArrival; + + @Column(nullable = false) private LocalDate orderExpectation; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) private OrderStatus orderStatus; + + @Column(nullable = false) private LocalDate orderDate; + + public static Order from(Long orderId, Seller seller, Buyer buyer, List orderProductList, + boolean isPay, LocalDate paymentDate, String orderAddress, + String orderNotes, LocalDate orderArrival, LocalDate orderExpectation, + OrderStatus orderStatus, LocalDate orderDate) { + return Order.builder() + .orderId(orderId) + .seller(seller) + .buyer(buyer) + .orderProductList(orderProductList) + .isPay(isPay) + .paymentDate(paymentDate) + .orderAddress(orderAddress) + .orderNotes(orderNotes) + .orderArrival(orderArrival) + .orderExpectation(orderExpectation) + .orderStatus(orderStatus) + .orderDate(orderDate) + .build(); + } } From 64f194925bbc4b9d9e818e79e115158403fa59c5 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:30:05 +0900 Subject: [PATCH 39/76] =?UTF-8?q?SCRUM-47=20feat:=20orderProduct=20Column?= =?UTF-8?q?=20=EB=B3=84=20Nullable=20=EC=84=A4=EC=A0=95=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/cart/entity/Cart.java | 2 +- .../golagola/domain/order/entity/Order.java | 4 ++-- .../domain/orderProduct/entity/OrderProduct.java | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index cc0898f..df96b58 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -19,7 +19,7 @@ public class Cart { @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "buyer_id") + @JoinColumn(name = "buyer_id", nullable = false) private Buyer buyer; @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL) diff --git a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java index ad1a170..6ba8ed5 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java +++ b/src/main/java/com/kakaoteck/golagola/domain/order/entity/Order.java @@ -27,11 +27,11 @@ public class Order extends BaseEntity { private Long orderId; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "seller_id") + @JoinColumn(name = "seller_id", nullable = false) private Seller seller; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "buyer_id") + @JoinColumn(name = "buyer_id", nullable = false) private Buyer buyer; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java index 43591b6..e21a9c7 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java @@ -22,16 +22,26 @@ public class OrderProduct { private Long orderProductId; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "product_id") + @JoinColumn(name = "product_id", nullable = false) private Product product; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "order_id") + @JoinColumn(name = "order_id"m nullable = false) private Order order; @OneToOne(mappedBy = "orderProduct", cascade = CascadeType.ALL) private Review review; + @Column(nullable = false) private Long quantity; + + @Column(nullable = false) private Long orderPrice; + + public static OrderProduct from(Long quantity, Long orderPrice) { + return OrderProduct.builder() + .quantity(quantity) + .orderPrice(orderPrice) + .build(); + } } From 97b7dc2443116e9d04f29211a8cdb6f83a883722 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:32:30 +0900 Subject: [PATCH 40/76] =?UTF-8?q?SCRUM-47=20feat:=20Product=20Column=20?= =?UTF-8?q?=EB=B3=84=20Nullable=20=EC=84=A4=EC=A0=95=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/product/entity/Product.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index dc3b873..3031f8f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -42,18 +42,73 @@ public class Product extends BaseEntity { @OneToMany(mappedBy = "product", cascade = CascadeType.ALL) private List orderProductList; + @Column(nullable = false) private String productName; + + @Column(nullable = false) private String productExplanation; + + @Column(nullable = false) private String productImage; + + @Column(nullable = false) private Long productPrice; + + @Column(nullable = false) private Long productInventory; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) private Category category; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) private DetailCategory detailCategory; + + @Column(nullable = false) private Long discount; + + @Column(nullable = false) private LocalTime createTime; + + @Column(nullable = false) private LocalTime updateTime; + + @Column(nullable = false) private Long productQuantity; + + @Column(nullable = false) private Float predictReviewStar; + + @Column(nullable = false) private Float productStar; + public static Product from(Long productId, Seller seller, Cart cart, List reviewList, + List orderProductList, String productName, + String productExplanation, String productImage, Long productPrice, + Long productInventory, Category category, DetailCategory detailCategory, + Long discount, LocalTime createTime, LocalTime updateTime, + Long productQuantity, Float predictReviewStar, Float productStar) { + return Product.builder() + .productId(productId) + .seller(seller) + .cart(cart) + .reviewList(reviewList) + .orderProductList(orderProductList) + .productName(productName) + .productExplanation(productExplanation) + .productImage(productImage) + .productPrice(productPrice) + .productInventory(productInventory) + .category(category) + .detailCategory(detailCategory) + .discount(discount) + .createTime(createTime) + .updateTime(updateTime) + .productQuantity(productQuantity) + .predictReviewStar(predictReviewStar) + .productStar(productStar) + .build(); + } + } From 3ab8a173b0d777ca818f3b10955145c07b798974 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:33:51 +0900 Subject: [PATCH 41/76] =?UTF-8?q?SCRUM-47=20feat:=20Review=20Column=20?= =?UTF-8?q?=EB=B3=84=20Nullable=20=EC=84=A4=EC=A0=95=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../orderProduct/entity/OrderProduct.java | 2 +- .../golagola/domain/review/entity/Review.java | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java index e21a9c7..5ccf9e6 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java +++ b/src/main/java/com/kakaoteck/golagola/domain/orderProduct/entity/OrderProduct.java @@ -26,7 +26,7 @@ public class OrderProduct { private Product product; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "order_id"m nullable = false) + @JoinColumn(name = "order_id", nullable = false) private Order order; @OneToOne(mappedBy = "orderProduct", cascade = CascadeType.ALL) diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java index b93ff5c..921c665 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -36,11 +36,34 @@ public class Review extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long reviewId; + @Column(nullable = false) private String reviewTitle; + + @Column(nullable = false) private Long reviewStar; + + @Column(nullable = false) private String reviewContent; + + @Column(nullable = false) private LocalDate reviewCreateTime; - private LocalDate reviewUpdateTime; + @Column(nullable = false) + private LocalDate reviewUpdateTime; + public static Review from(Long reviewId, Buyer buyer, Product product, OrderProduct orderProduct, + String reviewTitle, Long reviewStar, String reviewContent, + LocalDate reviewCreateTime, LocalDate reviewUpdateTime) { + return Review.builder() + .reviewId(reviewId) + .buyer(buyer) + .product(product) + .orderProduct(orderProduct) + .reviewTitle(reviewTitle) + .reviewStar(reviewStar) + .reviewContent(reviewContent) + .reviewCreateTime(reviewCreateTime) + .reviewUpdateTime(reviewUpdateTime) + .build(); + } } From 2603f9503fd23e173c133e2432499e328855ab81 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 17:35:40 +0900 Subject: [PATCH 42/76] =?UTF-8?q?SCRUM-47=20feat:=20Seller=20Column=20?= =?UTF-8?q?=EB=B3=84=20Nullable=20=EC=84=A4=EC=A0=95=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/review/entity/Review.java | 4 +-- .../golagola/domain/seller/entity/Seller.java | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java index 921c665..c568087 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java +++ b/src/main/java/com/kakaoteck/golagola/domain/review/entity/Review.java @@ -21,11 +21,11 @@ public class Review extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "buyer_id") + @JoinColumn(name = "buyer_id", nullable = false) private Buyer buyer; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "product_id") + @JoinColumn(name = "product_id", nullable = false) private Product product; @OneToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 7f943d2..8694429 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -31,13 +31,30 @@ public class Seller extends BaseEntity implements UserDetails { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long sellerId; + @Column(nullable = false) private String nickname; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) private Gender gender; + + @Column(nullable = false) private String email; + + @Column(nullable = false) private String address; + + @Column(nullable = false) private String phoneNum; + + @Column(nullable = false) private Role role; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) private String realName; + + @Column(nullable = false) private LocalDate registerDate; @OneToMany(mappedBy = "seller", cascade = CascadeType.ALL) @@ -80,4 +97,22 @@ public boolean isCredentialsNonExpired() { public boolean isEnabled() { return UserDetails.super.isEnabled(); } + + public static Seller from(Long sellerId, String nickname, Gender gender, String email, + String address, String phoneNum, Role role, String realName, + LocalDate registerDate, List productList, List orderList) { + return Seller.builder() + .sellerId(sellerId) + .nickname(nickname) + .gender(gender) + .email(email) + .address(address) + .phoneNum(phoneNum) + .role(role) + .realName(realName) + .registerDate(registerDate) + .productList(productList) + .orderList(orderList) + .build(); + } } From 18cd809a148133a13935ab251a5199959f9917e7 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:18:51 +0900 Subject: [PATCH 43/76] =?UTF-8?q?SCRUM-40=20feat:=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=88=98=EC=A0=95/=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../buyer/controller/BuyerController.java | 37 ++++++++++++++ .../domain/buyer/dto/BuyerRequest.java | 25 ++++++++++ .../domain/buyer/dto/BuyerResponse.java | 20 ++++++++ .../golagola/domain/buyer/entity/Buyer.java | 7 +++ .../domain/buyer/service/BuyerService.java | 48 +++++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/controller/BuyerController.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerRequest.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerResponse.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/buyer/service/BuyerService.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/controller/BuyerController.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/controller/BuyerController.java new file mode 100644 index 0000000..5531ec0 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/controller/BuyerController.java @@ -0,0 +1,37 @@ +package com.kakaoteck.golagola.domain.buyer.controller; + +import com.kakaoteck.golagola.domain.buyer.dto.BuyerRequest; +import com.kakaoteck.golagola.domain.buyer.dto.BuyerResponse; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.buyer.service.BuyerService; +import com.kakaoteck.golagola.global.common.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/buyer") +public class BuyerController { + + private final BuyerService buyerService; + + @Operation(summary = "구매자 마이페이지 조회", description = "구매자의 정보를 조회합니다.") + @GetMapping("/mypage") + public ApiResponse getMyPage( + @AuthenticationPrincipal Buyer buyer + ) { + return ApiResponse.onSuccess(BuyerService.getMyPage(buyer)); + } + + @Operation(summary = "구매자 마이페이지 수정", description = "구매자의 정보를 수정합니다.") + @PutMapping("/mypage") + public ApiResponse updateProfile( + @AuthenticationPrincipal Buyer buyer, + @RequestBody BuyerRequest.MyPagePutDto request + ) { + return ApiResponse.onSuccess(buyerService.updateMyPage(buyer, request)); + } + +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerRequest.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerRequest.java new file mode 100644 index 0000000..21c20f3 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerRequest.java @@ -0,0 +1,25 @@ +package com.kakaoteck.golagola.domain.buyer.dto; + +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; +import lombok.Builder; + +import java.time.LocalDate; + +public record BuyerRequest( + String nickname, + String realName, + Gender gender, + String email, + String address, + String phoneNum, + Role role, + LocalDate registerDate) { + + @Builder + public record MyPagePutDto( + String nickname, + String address, + String phoneNum + ) {} +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerResponse.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerResponse.java new file mode 100644 index 0000000..44a9505 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/dto/BuyerResponse.java @@ -0,0 +1,20 @@ +package com.kakaoteck.golagola.domain.buyer.dto; + +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; +import lombok.Builder; + +import java.time.LocalDate; + +@Builder +public record BuyerResponse( + String nickname, + String realName, + Gender gender, + String email, + String address, + String phoneNum, + Role role, + LocalDate registerDate +) { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index 064acc2..ba8a7c4 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.buyer.entity; +import com.kakaoteck.golagola.domain.buyer.dto.BuyerRequest; import com.kakaoteck.golagola.domain.cart.entity.Cart; import com.kakaoteck.golagola.domain.order.entity.Order; import com.kakaoteck.golagola.domain.review.entity.Review; @@ -100,6 +101,12 @@ public boolean isEnabled() { return UserDetails.super.isEnabled(); } + public void updateProfile(BuyerRequest.MyPagePutDto request) { + this.nickname = request.nickname(); + this.address = request.address(); + this.phoneNum = request.phoneNum(); + } + public static Buyer from(Long buyerId, String nickname, String realName, Gender gender, String email, String address, String phoneNum, Role role, LocalDate registerDate) { return Buyer.builder() diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/service/BuyerService.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/service/BuyerService.java new file mode 100644 index 0000000..50407b2 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/service/BuyerService.java @@ -0,0 +1,48 @@ +package com.kakaoteck.golagola.domain.buyer.service; + +import com.kakaoteck.golagola.domain.buyer.dto.BuyerRequest; +import com.kakaoteck.golagola.domain.buyer.dto.BuyerResponse; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.buyer.repository.BuyerRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +@Slf4j +public class BuyerService { + + private final BuyerRepository buyerRepository; + + public static BuyerResponse getMyPage(Buyer buyer) { + return BuyerResponse.builder() + .email(buyer.getEmail()) + .role(buyer.getRole()) + .address(buyer.getAddress()) + .registerDate(buyer.getRegisterDate()) + .realName(buyer.getRealName()) + .gender(buyer.getGender()) + .phoneNum(buyer.getPhoneNum()) + .nickname(buyer.getNickname()) + .build(); + } + + public BuyerResponse updateMyPage(Buyer buyer, BuyerRequest.MyPagePutDto request) { + buyer.updateProfile(request); + Buyer savedBuyer = buyerRepository.save(buyer); + return BuyerResponse.builder() + .email(savedBuyer.getEmail()) + .role(savedBuyer.getRole()) + .address(savedBuyer.getAddress()) + .registerDate(savedBuyer.getRegisterDate()) + .realName(savedBuyer.getRealName()) + .gender(savedBuyer.getGender()) + .phoneNum(savedBuyer.getPhoneNum()) + .nickname(savedBuyer.getNickname()) + .build(); + + } +} From cd34b3d5415a30848c189551aa87a4c7ff277e84 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:27:07 +0900 Subject: [PATCH 44/76] SCRUM-48 feat: Spring Security init --- .../com/kakaoteck/golagola/config/util/ApplicationConfig.java | 4 ++++ .../com/kakaoteck/golagola/config/util/SecurityConfig.java | 4 ++++ .../golagola/security/filter/JwtAuthenticationFilter.java | 4 ++++ .../com/kakaoteck/golagola/security/service/JwtService.java | 4 ++++ .../kakaoteck/golagola/security/service/LogoutService.java | 4 ++++ .../java/com/kakaoteck/golagola/security/token/Token.java | 4 ++++ .../com/kakaoteck/golagola/security/token/TokenBlackList.java | 4 ++++ .../golagola/security/token/TokenBlackListRepository.java | 4 ++++ .../kakaoteck/golagola/security/token/TokenRepository.java | 4 ++++ .../kakaoteck/golagola/security/token/enums/TokenType.java | 4 ++++ 10 files changed, 40 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java create mode 100644 src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/service/JwtService.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/token/Token.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java create mode 100644 src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java diff --git a/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java b/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java new file mode 100644 index 0000000..3d3be1c --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.config.util; + +public class ApplicationConfig { +} diff --git a/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java b/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java new file mode 100644 index 0000000..7353458 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.config.util; + +public class SecurityConfig { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java b/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java new file mode 100644 index 0000000..b8b880a --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.filter; + +public class JwtAuthenticationFilter { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java b/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java new file mode 100644 index 0000000..fce3914 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.service; + +public class JwtService { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java b/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java new file mode 100644 index 0000000..1a4baa0 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.service; + +public class LogoutService { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/token/Token.java b/src/main/java/com/kakaoteck/golagola/security/token/Token.java new file mode 100644 index 0000000..eb72be8 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/token/Token.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.token; + +public class Token { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java new file mode 100644 index 0000000..667281d --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.token; + +public class TokenBlackList { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java new file mode 100644 index 0000000..b6732f3 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.token; + +public interface TokenBlackListRepository { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java new file mode 100644 index 0000000..f3f5ac2 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.token; + +public interface TokenRepository { +} diff --git a/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java b/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java new file mode 100644 index 0000000..ed36d5b --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.security.token.enums; + +public enum TokenType { +} From 896f5dad214fd3367592a1bd18a77a13998c9408 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:28:13 +0900 Subject: [PATCH 45/76] SCRUM-48 feat: JwtService --- .../golagola/security/service/JwtService.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java b/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java index fce3914..304af1d 100644 --- a/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java +++ b/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java @@ -1,4 +1,91 @@ package com.kakaoteck.golagola.security.service; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cglib.core.internal.Function; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; + +import java.security.Key; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Service public class JwtService { + + @Value("${spring.jwt.secret}") + private String secretKey; + @Value("${spring.jwt.token.access-expiration-time}") + private long jwtExpiration; + @Value("${spring.jwt.token.refresh-expiration-time}") + private long refreshExpiration; + + public String extractUserName(String token) { + return extractClaim(token, Claims::getSubject); + } + + public T extractClaim(String token, Function claimsResolver) { + final Claims claims = extractAllClaims(token); + return claimsResolver.apply(claims); + } + + public String generateToken(UserDetails userDetails) { + return generateToken(new HashMap<>(), userDetails); + } + + public String generateToken(Map extraClaims, UserDetails userDetails) { + return buildToken(extraClaims, userDetails, jwtExpiration); + } + + public boolean isTokenValid(String token, UserDetails userDetails) { + final String username = extractUserName(token); + return (username.equals(userDetails.getUsername())) && !isTokenExpired(token); + } + + private boolean isTokenExpired(String token) { + return extractExpiration(token).before(new Date()); + } + + public String generateRefreshToken(UserDetails userDetails) { + return buildToken(new HashMap<>(), userDetails, refreshExpiration); + } + + private String buildToken( + Map extraClaims, + UserDetails userDetails, + long expiration + ) { + return Jwts + .builder() + .setClaims(extraClaims) + .setSubject(userDetails.getUsername()) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + expiration)) + .signWith(getSignInKey(), SignatureAlgorithm.HS256) + .compact(); + } + + private Date extractExpiration(String token) { + return extractClaim(token, Claims::getExpiration); + } + + private Claims extractAllClaims(String token) { + return Jwts + .parserBuilder() + .setSigningKey(getSignInKey()) + .build() + .parseClaimsJws(token) + .getBody(); + } + + private Key getSignInKey() { + byte[] keyBytes = Decoders.BASE64.decode(secretKey); + return Keys.hmacShaKeyFor(keyBytes); + } + } From 8d481c3b3f0ccadf11df369ece6783fde7b32ef8 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:29:16 +0900 Subject: [PATCH 46/76] SCRUM-48 feat: TokenRepository --- .../security/token/TokenRepository.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java index f3f5ac2..b2a6094 100644 --- a/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java @@ -1,4 +1,19 @@ package com.kakaoteck.golagola.security.token; -public interface TokenRepository { +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Optional; + +public interface TokenRepository extends JpaRepository { + + @Query(value = """ + select t from Token t inner join User u on t.user.userId = u.userId + where u.userId = :id and (t.expired = false or t.revoked = false) + """) + List findAllValidTokenByUser(@Param("id") Long id); + + Optional findByToken(String token); } From 75693fbf547ae5685bea5be1802092c6d2d2123a Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:29:35 +0900 Subject: [PATCH 47/76] SCRUM-48 feat: TokenType --- .../com/kakaoteck/golagola/security/token/enums/TokenType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java b/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java index ed36d5b..1cfccda 100644 --- a/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java +++ b/src/main/java/com/kakaoteck/golagola/security/token/enums/TokenType.java @@ -1,4 +1,5 @@ package com.kakaoteck.golagola.security.token.enums; public enum TokenType { + BEARER } From 44cba9d44cc5c46a4279aa5eca7b154eeb1b04fc Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:30:48 +0900 Subject: [PATCH 48/76] =?UTF-8?q?SCRUM-48=20feat:=20Token=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/security/token/Token.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/security/token/Token.java b/src/main/java/com/kakaoteck/golagola/security/token/Token.java index eb72be8..95a817a 100644 --- a/src/main/java/com/kakaoteck/golagola/security/token/Token.java +++ b/src/main/java/com/kakaoteck/golagola/security/token/Token.java @@ -1,4 +1,44 @@ package com.kakaoteck.golagola.security.token; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.security.token.enums.TokenType; +import jakarta.persistence.*; +import lombok.*; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "token") public class Token { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String token; + + @Enumerated(EnumType.STRING) + private TokenType tokenType = TokenType.BEARER; + + private boolean revoked; + + private boolean expired; + + @JsonIgnore + @ToString.Exclude + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "buyer_id") + private Buyer buyer; + + @JsonIgnore + @ToString.Exclude + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "seller_id") + private Seller seller; + } From ee57f646ff9de7e03c9feeeb3ad458a458f6679a Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:31:28 +0900 Subject: [PATCH 49/76] SCRUM-48 feat: TokenBlackListRepository --- .../golagola/security/token/TokenBlackListRepository.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java index b6732f3..474449b 100644 --- a/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackListRepository.java @@ -1,4 +1,8 @@ package com.kakaoteck.golagola.security.token; -public interface TokenBlackListRepository { +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TokenBlackListRepository extends JpaRepository { + + boolean existsByToken(String token); } From bec4068fddcbb79c3cb84bc4dce58a8a0aa6af69 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:31:57 +0900 Subject: [PATCH 50/76] =?UTF-8?q?SCRUM-48=20feat:=20TokenBlackList=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/token/TokenBlackList.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java index 667281d..e1aac0a 100644 --- a/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenBlackList.java @@ -1,4 +1,21 @@ package com.kakaoteck.golagola.security.token; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "token_blacklist") public class TokenBlackList { -} + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String token; + +} \ No newline at end of file From e017a9c088ac038df06f18852104539657f8ef9f Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:33:32 +0900 Subject: [PATCH 51/76] SCRUM-48 fix: TokenRepository --- .../golagola/security/token/TokenRepository.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java b/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java index b2a6094..6e9ad38 100644 --- a/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java +++ b/src/main/java/com/kakaoteck/golagola/security/token/TokenRepository.java @@ -10,10 +10,16 @@ public interface TokenRepository extends JpaRepository { @Query(value = """ - select t from Token t inner join User u on t.user.userId = u.userId - where u.userId = :id and (t.expired = false or t.revoked = false) + select t from Token t inner join Buyer u on t.buyer.buyerId = u.buyerId + where u.buyerId = :id and (t.expired = false or t.revoked = false) """) - List findAllValidTokenByUser(@Param("id") Long id); + List findAllValidTokenByBuyer(@Param("id") Long id); + + @Query(value = """ + select t from Token t inner join Seller u on t.seller.sellerId = u.sellerId + where u.sellerId = :id and (t.expired = false or t.revoked = false) + """) + List findAllValidTokenBySeller(@Param("id") Long id); Optional findByToken(String token); } From 0be13189833bf947330dbd29e63b67115367aa52 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:36:16 +0900 Subject: [PATCH 52/76] =?UTF-8?q?SCRUM-48=20feat:=20filter=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 --- .../filter/JwtAuthenticationFilter.java | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java b/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java index b8b880a..e155841 100644 --- a/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/kakaoteck/golagola/security/filter/JwtAuthenticationFilter.java @@ -1,4 +1,69 @@ package com.kakaoteck.golagola.security.filter; -public class JwtAuthenticationFilter { +import com.kakaoteck.golagola.security.service.JwtService; +import com.kakaoteck.golagola.security.token.TokenRepository; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; + +@Component +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtService jwtService; + private final UserDetailsService userDetailsService; + private final TokenRepository tokenRepository; + + @Override + protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException { + + final String authHeader = request.getHeader("Authorization"); + final String jwt; + final String userEmail; + + if (request.getServletPath().contains("/api/v1/auth")) { + filterChain.doFilter(request, response); + return; + } + + if (authHeader == null || !authHeader.startsWith("Bearer")) { + filterChain.doFilter(request, response); + return; + } + + jwt = authHeader.substring(7); + userEmail = jwtService.extractUserName(jwt); + + if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail); + + var isTokenValid = tokenRepository.findByToken(jwt) + .map(t -> !t.isExpired() && !t.isRevoked()) + .orElse(false); + + if (jwtService.isTokenValid(jwt, userDetails) && isTokenValid) { + UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( + userDetails, + null, + userDetails.getAuthorities() + ); + authToken.setDetails( + new WebAuthenticationDetailsSource().buildDetails(request) + ); + SecurityContextHolder.getContext().setAuthentication(authToken); + } + } + filterChain.doFilter(request, response); + } } From 04d05dcbe683349171415e468c499219ca294055 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:41:30 +0900 Subject: [PATCH 53/76] SCRUM-49 feat: AuditAware --- .../security/ApplicationAuditAware.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/security/ApplicationAuditAware.java diff --git a/src/main/java/com/kakaoteck/golagola/security/ApplicationAuditAware.java b/src/main/java/com/kakaoteck/golagola/security/ApplicationAuditAware.java new file mode 100644 index 0000000..6c5590f --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/security/ApplicationAuditAware.java @@ -0,0 +1,36 @@ +package com.kakaoteck.golagola.security; + +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import org.springframework.data.domain.AuditorAware; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.Optional; + +public class ApplicationAuditAware implements AuditorAware { + + @Override + public Optional getCurrentAuditor() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication == null || + !authentication.isAuthenticated() || + authentication instanceof AnonymousAuthenticationToken) { + return Optional.empty(); + } + + Object principal = authentication.getPrincipal(); + + if (principal instanceof Seller) { + Seller seller = (Seller) principal; + return Optional.ofNullable(seller.getSellerId()); + } else if (principal instanceof Buyer) { + Buyer buyer = (Buyer) principal; + return Optional.ofNullable(buyer.getBuyerId()); + } else { + return Optional.empty(); + } + } +} \ No newline at end of file From 5536f61cc6a88bd04fc25171561abeb2e19359e9 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:44:41 +0900 Subject: [PATCH 54/76] SCRUM-49 feat: auth Folder init --- .../golagola/domain/auth/controller/AuthController.java | 4 ++++ .../com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java | 4 ++++ .../com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java | 4 ++++ .../kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java | 4 ++++ .../kakaoteck/golagola/domain/auth/service/AuthService.java | 4 ++++ 5 files changed, 20 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java b/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java new file mode 100644 index 0000000..191aec1 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.auth.controller; + +public class AuthController { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java new file mode 100644 index 0000000..d7cd34c --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.auth.dto; + +public record AuthRequest() { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java new file mode 100644 index 0000000..ba32c5d --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.auth.dto; + +public class AuthResponse { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java new file mode 100644 index 0000000..d146e15 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.auth.dto; + +public class JoinUserRequest { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java b/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java new file mode 100644 index 0000000..146d7f4 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.auth.service; + +public class AuthService { +} From aab24d8081486a8cf29e38d2c4e7f60289652a8e Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 18:51:55 +0900 Subject: [PATCH 55/76] =?UTF-8?q?SCRUM-49=20feat:=20auth=20dto=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 --- .../golagola/domain/auth/dto/AuthRequest.java | 5 ++++- .../golagola/domain/auth/dto/AuthResponse.java | 10 ++++++++-- .../golagola/domain/auth/dto/JoinUserRequest.java | 13 ++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java index d7cd34c..f94e011 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthRequest.java @@ -1,4 +1,7 @@ package com.kakaoteck.golagola.domain.auth.dto; -public record AuthRequest() { +public record AuthRequest( + String email, + String password +) { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java index ba32c5d..b252e66 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/AuthResponse.java @@ -1,4 +1,10 @@ package com.kakaoteck.golagola.domain.auth.dto; -public class AuthResponse { -} +import lombok.Builder; + +@Builder +public record AuthResponse( + String accessToken, + String refreshToken +) { +} \ No newline at end of file diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java index d146e15..8368a00 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java @@ -1,4 +1,15 @@ package com.kakaoteck.golagola.domain.auth.dto; -public class JoinUserRequest { +import com.kakaoteck.golagola.global.common.enums.Role; + +import java.time.LocalDate; + +public record JoinUserRequest( + String email, + String password, + String nickname, + String gender, + LocalDate birthDate, + Role role +) { } From c65eabcbd6e83423c66ffda1c94e53923049b20b Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 20:34:38 +0900 Subject: [PATCH 56/76] SCRUM-49 feat: auth Folder --- .../config/util/ApplicationConfig.java | 82 +++++++- .../golagola/config/util/SecurityConfig.java | 59 ++++++ .../domain/auth/dto/JoinUserRequest.java | 2 +- .../domain/auth/service/AuthService.java | 175 ++++++++++++++++++ .../golagola/domain/buyer/entity/Buyer.java | 3 + .../golagola/domain/seller/entity/Seller.java | 3 + 6 files changed, 322 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java b/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java index 3d3be1c..4854cdd 100644 --- a/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java @@ -1,4 +1,84 @@ package com.kakaoteck.golagola.config.util; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.buyer.repository.BuyerRepository; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; +import com.kakaoteck.golagola.security.ApplicationAuditAware; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.domain.AuditorAware; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +import java.util.Collections; + +@Configuration +@RequiredArgsConstructor public class ApplicationConfig { -} + + private final BuyerRepository buyerRepository; + private final SellerRepository sellerRepository; + + @Bean + public UserDetailsService userDetailsService() { + return username -> { + // Try to find the user as a Buyer + Buyer buyer = buyerRepository.findByEmail(username) + .orElse(null); + + if (buyer != null) { + return new org.springframework.security.core.userdetails.User( + buyer.getEmail(), + buyer.getPassword(), + Collections.singleton(new SimpleGrantedAuthority("BUYER")) + ); + } + + // Try to find the user as a Seller + Seller seller = sellerRepository.findByEmail(username) + .orElse(null); + + if (seller != null) { + return new org.springframework.security.core.userdetails.User( + seller.getEmail(), + seller.getPassword(), + Collections.singleton(new SimpleGrantedAuthority("SELLER")) + ); + } + + throw new UsernameNotFoundException("User not found with username: " + username); + }; + } + + @Bean + public AuthenticationProvider authenticationProvider() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(userDetailsService()); + authProvider.setPasswordEncoder(passwordEncoder()); + return authProvider; + } + + @Bean + public AuditorAware auditorAware() { + return new ApplicationAuditAware(); + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { + return config.getAuthenticationManager(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java b/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java index 7353458..a99d59e 100644 --- a/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java @@ -1,4 +1,63 @@ package com.kakaoteck.golagola.config.util; +import com.kakaoteck.golagola.security.filter.JwtAuthenticationFilter; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutHandler; + +import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS; + +@RequiredArgsConstructor +@EnableMethodSecurity +@Configuration +@EnableWebSecurity public class SecurityConfig { + + private final JwtAuthenticationFilter jwtAuthFilter; + private final AuthenticationProvider authenticationProvider; + private final LogoutHandler logoutHandler; + + private static final String[] WHITE_LIST_URL = { + "/api/v1/auth/**", + "/v2/api-docs", + "/v3/api-docs", + "/v3/api-docs/**", + "/swagger-resources", + "/swagger-resources/**", + "/configuration/ui", + "/configuration/security", + "/swagger-ui/**", + "/webjars/**", + "/swagger-ui.html" + }; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(req -> + req.requestMatchers(WHITE_LIST_URL) + .permitAll() + .anyRequest() + .authenticated() + ) + .sessionManagement(session -> session.sessionCreationPolicy(STATELESS)) + .authenticationProvider(authenticationProvider) + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class) + .logout(logout -> + logout.logoutUrl("/api/v1/auth/logout") + .addLogoutHandler(logoutHandler) + ) + ; + + return http.build(); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java index 8368a00..b9468dc 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java @@ -10,6 +10,6 @@ public record JoinUserRequest( String nickname, String gender, LocalDate birthDate, - Role role + String role ) { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java b/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java index 146d7f4..502132a 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java @@ -1,4 +1,179 @@ package com.kakaoteck.golagola.domain.auth.service; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.kakaoteck.golagola.domain.auth.dto.AuthRequest; +import com.kakaoteck.golagola.domain.auth.dto.AuthResponse; +import com.kakaoteck.golagola.domain.auth.dto.JoinUserRequest; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.buyer.repository.BuyerRepository; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; +import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.exception.GeneralException; +import com.kakaoteck.golagola.security.service.JwtService; +import com.kakaoteck.golagola.security.token.Token; +import com.kakaoteck.golagola.security.token.TokenBlackListRepository; +import com.kakaoteck.golagola.security.token.TokenRepository; +import com.kakaoteck.golagola.security.token.enums.TokenType; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.time.LocalDate; +import java.util.NoSuchElementException; +import java.util.Optional; + +@Service +@RequiredArgsConstructor public class AuthService { + private final BuyerRepository buyerRepository; + private final SellerRepository sellerRepository; + private final TokenRepository tokenRepository; + private final TokenBlackListRepository tokenBlackListRepository; + private final PasswordEncoder passwordEncoder; + private final JwtService jwtService; + private final AuthenticationManager authenticationManager; + + public void register(JoinUserRequest request) { + if ("BUYER".equals(request.role())) { + Buyer buyer = Buyer.builder() + .email(request.email()) + .password(passwordEncoder.encode(request.password())) + .nickname(request.nickname()) + .gender(Gender.valueOf(request.gender())) + .registerDate(LocalDate.now()) + .build(); + buyerRepository.save(buyer); + } else if ("SELLER".equals(request.role())) { + Seller seller = Seller.builder() + .email(request.email()) + .password(passwordEncoder.encode(request.password())) + .nickname(request.nickname()) + .gender(Gender.valueOf(request.gender())) + .registerDate(LocalDate.now()) + .build(); + sellerRepository.save(seller); + } + } + + public AuthResponse authenticate(AuthRequest request) { + try { + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + request.email(), + request.password() + ) + ); + } catch (AuthenticationException e) { + throw new GeneralException(ErrorStatus._INVALID_USER); + } + + Buyer buyer = buyerRepository.findByEmail(request.email()).orElse(null); + Seller seller = sellerRepository.findByEmail(request.email()).orElse(null); + + if (buyer == null && seller == null) { + throw new GeneralException(ErrorStatus._INVALID_USER); + } + + // Determine the UserDetails type and generate tokens + UserDetails user = buyer != null ? buyer : seller; + String jwtToken = jwtService.generateToken(user); + String refreshToken = jwtService.generateRefreshToken(user); + + revokeAllUserTokens(user); + saveUserToken(user, jwtToken); + + return AuthResponse.builder() + .accessToken(jwtToken) + .refreshToken(refreshToken) + .build(); + } + + private void saveUserToken(UserDetails user, String jwtToken) { + Token token = Token.builder() + .token(jwtToken) + .tokenType(TokenType.BEARER) + .expired(false) + .revoked(false) + .build(); + + if (user instanceof Buyer) { + token.setBuyer((Buyer) user); + } else if (user instanceof Seller) { + token.setSeller((Seller) user); + } + + tokenRepository.save(token); + } + + private void revokeAllUserTokens(UserDetails user) { + if (user instanceof Buyer) { + var validUserTokens = tokenRepository.findAllValidTokenByBuyer(((Buyer) user).getBuyerId()); + validUserTokens.forEach(token -> { + token.setExpired(true); + token.setRevoked(true); + }); + tokenRepository.saveAll(validUserTokens); + } else if (user instanceof Seller) { + var validUserTokens = tokenRepository.findAllValidTokenBySeller(((Seller) user).getSellerId()); + validUserTokens.forEach(token -> { + token.setExpired(true); + token.setRevoked(true); + }); + tokenRepository.saveAll(validUserTokens); + } + } + + public void refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException { + final String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + return; + } + String refreshToken = authHeader.substring(7); + if (tokenBlackListRepository.existsByToken(refreshToken)) { + throw new NoSuchElementException("유효하지 않은 접근입니다."); + } + + String userEmail = jwtService.extractUserName(refreshToken); + if (userEmail != null) { + var buyerOptional = buyerRepository.findByEmail(userEmail); + var sellerOptional = sellerRepository.findByEmail(userEmail); + + if (buyerOptional.isPresent()) { + processTokenRefresh(buyerOptional.get(), refreshToken, response); + } else if (sellerOptional.isPresent()) { + processTokenRefresh(sellerOptional.get(), refreshToken, response); + } else { + throw new NoSuchElementException("User not found for email: " + userEmail); + } + } + } + + private void processTokenRefresh(UserDetails user, String refreshToken, HttpServletResponse response) throws IOException { + if (jwtService.isTokenValid(refreshToken, user)) { + String accessToken = jwtService.generateToken(user); + revokeAllUserTokens(user); + saveUserToken(user, accessToken); + + AuthResponse authResponse = AuthResponse.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); + new ObjectMapper().writeValue(response.getOutputStream(), authResponse); + } + } + + public boolean checkEmailExists(String email) { + return buyerRepository.existsByEmail(email) || sellerRepository.existsByEmail(email); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index ba8a7c4..0da6cdb 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -44,6 +44,9 @@ public class Buyer extends BaseEntity implements UserDetails { @Column(nullable = false) private String email; + @Column(nullable = false) + private String password; + @Column(nullable = false) private String address; diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 8694429..217cdc0 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -34,6 +34,9 @@ public class Seller extends BaseEntity implements UserDetails { @Column(nullable = false) private String nickname; + @Column(nullable = false) + private String password; + @Enumerated(EnumType.STRING) @Column(nullable = false) private Gender gender; From d4220dfb9cd1e15d8b15d34e6244fc388d097bc1 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 20:35:36 +0900 Subject: [PATCH 57/76] SCRUM-49 feat: AuthController --- .../auth/controller/AuthController.java | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java b/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java index 191aec1..f05157b 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/controller/AuthController.java @@ -1,4 +1,50 @@ package com.kakaoteck.golagola.domain.auth.controller; +import com.kakaoteck.golagola.domain.auth.dto.AuthRequest; +import com.kakaoteck.golagola.domain.auth.dto.AuthResponse; +import com.kakaoteck.golagola.domain.auth.dto.JoinUserRequest; +import com.kakaoteck.golagola.domain.auth.service.AuthService; +import com.kakaoteck.golagola.global.common.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.bind.annotation.*; + +import lombok.RequiredArgsConstructor; + +import java.io.IOException; + +@RequiredArgsConstructor +@RequestMapping("/api/v1/auth") +@RestController +@CrossOrigin("*") public class AuthController { -} + + private final AuthService authService; + + @Operation(summary = "회원가입 기능", description = "gender 값: MALE or FEMALE") + @PostMapping("/join") + public ApiResponse join(@RequestBody JoinUserRequest request) { + authService.register(request); + return ApiResponse.onSuccess("회원가입 성공"); + } + + @Operation(summary = "이메일 중복 검사 버튼", description = "회원가입 과정에서 이메일 중복 검사를 진행합니다.\ntrue = 이미 존재하는 이메일, false = 가입 가능한 이메일") + @GetMapping("/join/email-check/{email}") + public ApiResponse checkEmailExists( + @PathVariable(name = "email") String email + ) { + return ApiResponse.onSuccess(authService.checkEmailExists(email)); + } + + @PostMapping("/login") + public ApiResponse login(@RequestBody AuthRequest request) { + return ApiResponse.onSuccess(authService.authenticate(request)); + } + + @Operation(summary = "리프레시 토큰 발급") + @PostMapping("/refresh-token") + public void refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException { + authService.refreshToken(request, response); + } +} \ No newline at end of file From 7030531635c61e1e0fd7ec7538456af42ede98ae Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 20:36:54 +0900 Subject: [PATCH 58/76] SCRUM-49 feat: LogoutService --- .../security/service/LogoutService.java | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java b/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java index 1a4baa0..c7ef107 100644 --- a/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java +++ b/src/main/java/com/kakaoteck/golagola/security/service/LogoutService.java @@ -1,4 +1,78 @@ package com.kakaoteck.golagola.security.service; -public class LogoutService { -} +import com.kakaoteck.golagola.security.token.TokenBlackList; +import com.kakaoteck.golagola.security.token.TokenBlackListRepository; +import com.kakaoteck.golagola.security.token.TokenRepository; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.stereotype.Service; + +import java.io.IOException; + +@Service +@RequiredArgsConstructor +public class LogoutService implements LogoutHandler { + + private final TokenRepository tokenRepository; + private final TokenBlackListRepository tokenBlackListRepository; + private static final Logger logger = LoggerFactory.getLogger(LogoutService.class); + + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + final String authHeader = request.getHeader("Authorization"); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + sendErrorResponse(response, "Token is missing or invalid"); + return; + } + + final String jwt = authHeader.substring(7); + var storedToken = tokenRepository.findByToken(jwt).orElse(null); + if (storedToken == null || storedToken.isExpired()) { + sendErrorResponse(response, "Token is missing or invalid"); + } else { + if (!tokenBlackListRepository.existsByToken(jwt) ) { + TokenBlackList blackList = new TokenBlackList(); + blackList.setToken(jwt); + tokenBlackListRepository.save(blackList); + storedToken.setExpired(true); + storedToken.setRevoked(true); + tokenRepository.save(storedToken); + SecurityContextHolder.clearContext(); + + sendSuccessResponse(response); + + } else { + sendErrorResponse(response, "Can't use this token"); + } + } + } + + private void sendErrorResponse(HttpServletResponse response, String message) { + try { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setContentType("application/json"); + response.getWriter().write("{\"message\": \"" + message + "\"}"); + response.getWriter().flush(); + } catch (IOException e) { + logger.error("Error writing response", e); + } + } + + private void sendSuccessResponse(HttpServletResponse response) { + try { + response.setStatus(HttpServletResponse.SC_OK); // 200 OK + response.setContentType("application/json"); + response.getWriter().write("{\"message\": \"" + "logout" + "\"}"); + response.getWriter().flush(); + } catch (IOException e) { + logger.error("Error writing response", e); + } + } + +} \ No newline at end of file From dc526ed0e16eb3186b949aa56f820afc7145fd1d Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 20:43:46 +0900 Subject: [PATCH 59/76] SCRUM-49 feat: QueryDslConfig --- .../golagola/config/util/QueryDslConfig.java | 19 +++++++++++++++++++ .../golagola/domain/seller/entity/Seller.java | 2 +- src/main/resources/application.properties | 6 +++++- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java diff --git a/src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java b/src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java new file mode 100644 index 0000000..26cd3ef --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java @@ -0,0 +1,19 @@ +package com.kakaoteck.golagola.config.util; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@RequiredArgsConstructor +public class QueryDslConfig { + + private final EntityManager em; + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(em); + } +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 217cdc0..8ae5b03 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -50,10 +50,10 @@ public class Seller extends BaseEntity implements UserDetails { @Column(nullable = false) private String phoneNum; + @Enumerated(EnumType.STRING) @Column(nullable = false) private Role role; - @Enumerated(EnumType.STRING) @Column(nullable = false) private String realName; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 044a88c..704a5c3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,4 +4,8 @@ spring.datasource.password=8253 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update -spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file +spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect + +spring.jwt.secret=YGiByhzi3WNNsx420kl3yrwejJmV8htQ +spring.jwt.token.access-expiration-time=86400000 +spring.jwt.token.refresh-expiration-time=86400000 From 4121583c4861997359dbc2d94ddc7a2b52c2be54 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 21:11:55 +0900 Subject: [PATCH 60/76] =?UTF-8?q?SCRUM-49=20fix:=20Redis=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../golagola/config/util/RedisConfig.java | 33 +++++++++++++++++++ .../global/common/enums/Category.java | 1 + .../global/common/enums/DetailCategory.java | 1 + src/main/resources/application.properties | 6 +++- 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java diff --git a/build.gradle b/build.gradle index 5eb743f..f09fc8c 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-redis' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java b/src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java new file mode 100644 index 0000000..d3b51ae --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java @@ -0,0 +1,33 @@ +package com.kakaoteck.golagola.config.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Value("${spring.data.redis.host}") + private String redisHost; + + @Value("${spring.data.redis.port}") + private int redisPort; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(redisHost, redisPort); + } + + @Bean + public RedisTemplate redisTemplate() { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory()); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + return redisTemplate; + } +} diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java index ca4112e..66d3178 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/Category.java @@ -1,4 +1,5 @@ package com.kakaoteck.golagola.global.common.enums; public enum Category { + EXAMPLE } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java b/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java index 158d06d..5615bbc 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/enums/DetailCategory.java @@ -1,4 +1,5 @@ package com.kakaoteck.golagola.global.common.enums; public enum DetailCategory { + EXAMPLE } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 704a5c3..e42acfc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,9 +3,13 @@ spring.datasource.username=root spring.datasource.password=8253 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.jpa.hibernate.ddl-auto=update +spring.jpa.hibernate.ddl-auto=create +spring.jpa.generate-ddl=true spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect +spring.data.redis.host=localhost +spring.data.redis.port=6379 + spring.jwt.secret=YGiByhzi3WNNsx420kl3yrwejJmV8htQ spring.jwt.token.access-expiration-time=86400000 spring.jwt.token.refresh-expiration-time=86400000 From 955dea837933c2b4d1409a400952d7218f2c30e6 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 21:16:52 +0900 Subject: [PATCH 61/76] SCRUM-50 feat: RedisUtil --- .../config/{util => }/ApplicationConfig.java | 2 +- .../config/{util => }/QueryDslConfig.java | 2 +- .../config/{util => }/RedisConfig.java | 2 +- .../config/{util => }/SecurityConfig.java | 2 +- .../golagola/config/SwaggerConfig.java | 4 ++ .../golagola/config/util/RedisUtil.java | 56 +++++++++++++++++++ 6 files changed, 64 insertions(+), 4 deletions(-) rename src/main/java/com/kakaoteck/golagola/config/{util => }/ApplicationConfig.java (98%) rename src/main/java/com/kakaoteck/golagola/config/{util => }/QueryDslConfig.java (91%) rename src/main/java/com/kakaoteck/golagola/config/{util => }/RedisConfig.java (96%) rename src/main/java/com/kakaoteck/golagola/config/{util => }/SecurityConfig.java (98%) create mode 100644 src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java create mode 100644 src/main/java/com/kakaoteck/golagola/config/util/RedisUtil.java diff --git a/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java b/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java similarity index 98% rename from src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java rename to src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java index 4854cdd..9c1519f 100644 --- a/src/main/java/com/kakaoteck/golagola/config/util/ApplicationConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java @@ -1,4 +1,4 @@ -package com.kakaoteck.golagola.config.util; +package com.kakaoteck.golagola.config; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; import com.kakaoteck.golagola.domain.buyer.repository.BuyerRepository; diff --git a/src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java b/src/main/java/com/kakaoteck/golagola/config/QueryDslConfig.java similarity index 91% rename from src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java rename to src/main/java/com/kakaoteck/golagola/config/QueryDslConfig.java index 26cd3ef..06a7d89 100644 --- a/src/main/java/com/kakaoteck/golagola/config/util/QueryDslConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/QueryDslConfig.java @@ -1,4 +1,4 @@ -package com.kakaoteck.golagola.config.util; +package com.kakaoteck.golagola.config; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; diff --git a/src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java b/src/main/java/com/kakaoteck/golagola/config/RedisConfig.java similarity index 96% rename from src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java rename to src/main/java/com/kakaoteck/golagola/config/RedisConfig.java index d3b51ae..4c798ca 100644 --- a/src/main/java/com/kakaoteck/golagola/config/util/RedisConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/RedisConfig.java @@ -1,4 +1,4 @@ -package com.kakaoteck.golagola.config.util; +package com.kakaoteck.golagola.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java b/src/main/java/com/kakaoteck/golagola/config/SecurityConfig.java similarity index 98% rename from src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java rename to src/main/java/com/kakaoteck/golagola/config/SecurityConfig.java index a99d59e..7ecc663 100644 --- a/src/main/java/com/kakaoteck/golagola/config/util/SecurityConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/SecurityConfig.java @@ -1,4 +1,4 @@ -package com.kakaoteck.golagola.config.util; +package com.kakaoteck.golagola.config; import com.kakaoteck.golagola.security.filter.JwtAuthenticationFilter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java b/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java new file mode 100644 index 0000000..1b223d5 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.config; + +public class SwaggerConfig { +} diff --git a/src/main/java/com/kakaoteck/golagola/config/util/RedisUtil.java b/src/main/java/com/kakaoteck/golagola/config/util/RedisUtil.java new file mode 100644 index 0000000..6df3532 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/config/util/RedisUtil.java @@ -0,0 +1,56 @@ +package com.kakaoteck.golagola.config.util; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +@RequiredArgsConstructor +public class RedisUtil { + + private final RedisTemplate redisTemplate; + + public void saveAsValue(String key, Object val, Long time, TimeUnit timeUnit) { + redisTemplate.opsForValue().set(key, val, time, timeUnit); + } + + public void appendToRecentlyViewedAnnouncement(String key, String newValue) { + long RECENT_VIEWED_ANNOUNCEMENT_LIMIT = 20; + + log.info("[*] Newly Viewed Announcement: " + newValue); + Object mostRecentlyViewedValue = redisTemplate.opsForList().index(key, 0); + if (Objects.equals(mostRecentlyViewedValue, newValue)) { + log.info("[*] Skip saving viewed history..."); + return; + } + if (Objects.equals(redisTemplate.opsForList().size(key), RECENT_VIEWED_ANNOUNCEMENT_LIMIT)) { + log.info("[*] Recent Announcement Deque Full Capacity.."); + log.info("[*] Del Top()"); + redisTemplate.opsForList().rightPop(key); + } + redisTemplate.opsForList().leftPush(key, newValue); + } + + public boolean hasKey(String key) { + return Boolean.TRUE.equals(redisTemplate.hasKey(key)); + } + + public Object get(String key) { + return redisTemplate.opsForValue().get(key); + } + + public List getList(String key) { + return redisTemplate.opsForList().range(key, 0, -1); + } + + public boolean delete(String key) { + return Boolean.TRUE.equals(redisTemplate.delete(key)); + } +} \ No newline at end of file From 18c69b21af5cc1d40454756d04b4f227d66ae84b Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Mon, 12 Aug 2024 21:17:47 +0900 Subject: [PATCH 62/76] SCRUM-50 feat: Swagger --- .../golagola/config/SwaggerConfig.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java b/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java index 1b223d5..a36a822 100644 --- a/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/SwaggerConfig.java @@ -1,4 +1,48 @@ package com.kakaoteck.golagola.config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; + +@Configuration public class SwaggerConfig { + + // url: http://localhost:8080/swagger-ui/index.html#/ + @Bean + public OpenAPI getOpenApi() { + Server server = new Server().url("/"); + return new OpenAPI() + .info(getSwaggerInfo()) + .components(authSetting()) + .addServersItem(server) + .addSecurityItem(new SecurityRequirement().addList("access-token")); + } + + private Info getSwaggerInfo() { + License license = new License(); + license.setName("{Application}"); + + return new Info() + .title("GolaGola API Document") + .description("This is GolaGola's API document.") + .version("v0.0.1") + .license(license); + } + + private Components authSetting() { + return new Components() + .addSecuritySchemes( + "access-token", + new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT")); + } } From 72cee2f72f6db0985819cbd595beadfa3cda2330 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 01:32:48 +0900 Subject: [PATCH 63/76] =?UTF-8?q?SCRUM-50=20fix:=20auth=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/config/ApplicationConfig.java | 10 +++++---- .../domain/auth/dto/JoinUserRequest.java | 4 +++- .../domain/auth/service/AuthService.java | 16 +++++++++++++- .../golagola/domain/buyer/entity/Buyer.java | 21 +++++++++++-------- .../golagola/domain/seller/entity/Seller.java | 19 ++++++++++------- .../common/code/status/ErrorStatus.java | 1 + .../golagola/security/service/JwtService.java | 11 +++++++++- src/main/resources/application.properties | 4 ++-- 8 files changed, 60 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java b/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java index 9c1519f..fec7a69 100644 --- a/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java @@ -32,10 +32,10 @@ public class ApplicationConfig { public UserDetailsService userDetailsService() { return username -> { // Try to find the user as a Buyer - Buyer buyer = buyerRepository.findByEmail(username) - .orElse(null); + Buyer buyer = buyerRepository.findByEmail(username).orElse(null); if (buyer != null) { + System.out.println("Buyer found: " + username); return new org.springframework.security.core.userdetails.User( buyer.getEmail(), buyer.getPassword(), @@ -44,10 +44,11 @@ public UserDetailsService userDetailsService() { } // Try to find the user as a Seller - Seller seller = sellerRepository.findByEmail(username) - .orElse(null); + Seller seller = sellerRepository.findByEmail(username).orElse(null); if (seller != null) { + System.out.println("Seller found: " + username); + System.out.println("Encoded password: " + seller.getPassword()); return new org.springframework.security.core.userdetails.User( seller.getEmail(), seller.getPassword(), @@ -59,6 +60,7 @@ public UserDetailsService userDetailsService() { }; } + @Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java index b9468dc..ddbbd7a 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/dto/JoinUserRequest.java @@ -8,8 +8,10 @@ public record JoinUserRequest( String email, String password, String nickname, + String realName, + String phoneNum, + String address, String gender, - LocalDate birthDate, String role ) { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java b/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java index 502132a..8dcb7ab 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/auth/service/AuthService.java @@ -10,6 +10,7 @@ import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; import com.kakaoteck.golagola.global.common.exception.GeneralException; import com.kakaoteck.golagola.security.service.JwtService; import com.kakaoteck.golagola.security.token.Token; @@ -50,8 +51,12 @@ public void register(JoinUserRequest request) { .email(request.email()) .password(passwordEncoder.encode(request.password())) .nickname(request.nickname()) + .realName(request.realName()) + .phoneNum(request.phoneNum()) .gender(Gender.valueOf(request.gender())) .registerDate(LocalDate.now()) + .role(Role.valueOf(request.role())) + .address(request.address()) .build(); buyerRepository.save(buyer); } else if ("SELLER".equals(request.role())) { @@ -59,14 +64,20 @@ public void register(JoinUserRequest request) { .email(request.email()) .password(passwordEncoder.encode(request.password())) .nickname(request.nickname()) + .realName(request.realName()) + .phoneNum(request.phoneNum()) .gender(Gender.valueOf(request.gender())) .registerDate(LocalDate.now()) + .address(request.address()) + .role(Role.valueOf(request.role())) .build(); sellerRepository.save(seller); } } public AuthResponse authenticate(AuthRequest request) { + System.out.println("Attempting authentication for: " + request.email()); + try { authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( @@ -75,7 +86,8 @@ public AuthResponse authenticate(AuthRequest request) { ) ); } catch (AuthenticationException e) { - throw new GeneralException(ErrorStatus._INVALID_USER); + System.out.println("Authentication failed for email: " + request.email()); + throw new GeneralException(ErrorStatus._LOGIN_USER_INVALID); } Buyer buyer = buyerRepository.findByEmail(request.email()).orElse(null); @@ -85,6 +97,8 @@ public AuthResponse authenticate(AuthRequest request) { throw new GeneralException(ErrorStatus._INVALID_USER); } + System.out.println("Authentication successful for: " + request.email()); + // Determine the UserDetails type and generate tokens UserDetails user = buyer != null ? buyer : seller; String jwtToken = jwtService.generateToken(user); diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index 0da6cdb..980dd1e 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -13,10 +13,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; import java.util.Collection; +import java.util.Collections; import java.util.List; @Entity @@ -71,37 +73,37 @@ public class Buyer extends BaseEntity implements UserDetails { @Override public Collection getAuthorities() { - return null; + return Collections.singleton(new SimpleGrantedAuthority(role.name())); } @Override public String getPassword() { - return null; + return this.password; } @Override public String getUsername() { - return null; + return this.email; } @Override public boolean isAccountNonExpired() { - return UserDetails.super.isAccountNonExpired(); + return true; } @Override public boolean isAccountNonLocked() { - return UserDetails.super.isAccountNonLocked(); + return true; } @Override public boolean isCredentialsNonExpired() { - return UserDetails.super.isCredentialsNonExpired(); + return true; } @Override public boolean isEnabled() { - return UserDetails.super.isEnabled(); + return true; } public void updateProfile(BuyerRequest.MyPagePutDto request) { @@ -110,7 +112,7 @@ public void updateProfile(BuyerRequest.MyPagePutDto request) { this.phoneNum = request.phoneNum(); } - public static Buyer from(Long buyerId, String nickname, String realName, Gender gender, String email, + public static Buyer from(Long buyerId, String nickname, String realName, Gender gender, String email, String password, String address, String phoneNum, Role role, LocalDate registerDate) { return Buyer.builder() .buyerId(buyerId) @@ -118,11 +120,12 @@ public static Buyer from(Long buyerId, String nickname, String realName, Gender .realName(realName) .gender(gender) .email(email) + .password(password) .address(address) .phoneNum(phoneNum) .role(role) .registerDate(registerDate) .build(); } - } + diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 8ae5b03..2e2d568 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -12,11 +12,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; @Entity @@ -68,45 +70,46 @@ public class Seller extends BaseEntity implements UserDetails { @Override public Collection getAuthorities() { - return null; + return Collections.singleton(new SimpleGrantedAuthority(role.name())); } @Override public String getPassword() { - return null; + return this.password; } @Override public String getUsername() { - return null; + return this.email; } @Override public boolean isAccountNonExpired() { - return UserDetails.super.isAccountNonExpired(); + return true; } @Override public boolean isAccountNonLocked() { - return UserDetails.super.isAccountNonLocked(); + return true; } @Override public boolean isCredentialsNonExpired() { - return UserDetails.super.isCredentialsNonExpired(); + return true; } @Override public boolean isEnabled() { - return UserDetails.super.isEnabled(); + return true; } - public static Seller from(Long sellerId, String nickname, Gender gender, String email, + public static Seller from(Long sellerId, String nickname, Gender gender, String email, String password, String address, String phoneNum, Role role, String realName, LocalDate registerDate, List productList, List orderList) { return Seller.builder() .sellerId(sellerId) .nickname(nickname) + .password(password) .gender(gender) .email(email) .address(address) diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index dc9c95d..d1b6ad6 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -17,6 +17,7 @@ public enum ErrorStatus implements BaseErrorCode { // User 에러 _NOT_FOUND_USER(HttpStatus.NOT_FOUND, "USER400", "사용자가 존재하지 않습니다."), + _LOGIN_USER_INVALID(HttpStatus.BAD_REQUEST, "USER401", "로그인 중 오류가 발생하였습니다."), _INVALID_USER(HttpStatus.BAD_REQUEST, "USER401" , "아이디 또는 비밀번호가 틀렸습니다."), // Security 에러 diff --git a/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java b/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java index 304af1d..66a7da3 100644 --- a/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java +++ b/src/main/java/com/kakaoteck/golagola/security/service/JwtService.java @@ -39,7 +39,16 @@ public String generateToken(UserDetails userDetails) { } public String generateToken(Map extraClaims, UserDetails userDetails) { - return buildToken(extraClaims, userDetails, jwtExpiration); + String token = null; + try { + token = buildToken(extraClaims, userDetails, jwtExpiration); + System.out.println("Generated JWT Token: " + token); + } catch (Exception e) { + e.printStackTrace(); + // 로그 추가 + System.out.println("JWT Token 생성 중 오류 발생: " + e.getMessage()); + } + return token; } public boolean isTokenValid(String token, UserDetails userDetails) { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e42acfc..18436a7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,13 +3,13 @@ spring.datasource.username=root spring.datasource.password=8253 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=update spring.jpa.generate-ddl=true spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect spring.data.redis.host=localhost spring.data.redis.port=6379 -spring.jwt.secret=YGiByhzi3WNNsx420kl3yrwejJmV8htQ +spring.jwt.secret=64461f01e1af406da538b9c48d801ce59142452199ff112fb5404c8e7e98e3ff spring.jwt.token.access-expiration-time=86400000 spring.jwt.token.refresh-expiration-time=86400000 From c544f310846f4fc01a23a8a6496c85160a418069 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 01:53:30 +0900 Subject: [PATCH 64/76] =?UTF-8?q?SCRUM-41=20feat:=20=ED=8C=90=EB=A7=A4?= =?UTF-8?q?=EC=9E=90=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seller/controller/SellerController.java | 30 ++++++++++++++++++ .../domain/seller/dto/SellerResponse.java | 20 ++++++++++++ .../domain/seller/service/SellerService.java | 31 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerResponse.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java b/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java new file mode 100644 index 0000000..9ddd3eb --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java @@ -0,0 +1,30 @@ +package com.kakaoteck.golagola.domain.seller.controller; + +import com.kakaoteck.golagola.domain.seller.dto.SellerResponse; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.domain.seller.service.SellerService; +import com.kakaoteck.golagola.global.common.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/seller") +@CrossOrigin("*") +public class SellerController { + + private final SellerService sellerService; + + @Operation(summary = "판매자 마이페이지 조회", description = "판매자의 정보를 조회합니다.") + @GetMapping("/mypage") + public ApiResponse getMyPage( + @AuthenticationPrincipal Seller seller + ) { + return ApiResponse.onSuccess(sellerService.getMyPage(seller)); + } +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerResponse.java b/src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerResponse.java new file mode 100644 index 0000000..be57834 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerResponse.java @@ -0,0 +1,20 @@ +package com.kakaoteck.golagola.domain.seller.dto; + +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; +import lombok.Builder; + +import java.time.LocalDate; + +@Builder +public record SellerResponse( + String nickname, + String realName, + Gender gender, + String email, + String address, + String phoneNum, + Role role, + LocalDate registerDate +) { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java b/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java new file mode 100644 index 0000000..88a3b05 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java @@ -0,0 +1,31 @@ +package com.kakaoteck.golagola.domain.seller.service; + +import com.kakaoteck.golagola.domain.seller.dto.SellerResponse; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional +@Slf4j +public class SellerService { + + private final SellerRepository sellerRepository; + + public SellerResponse getMyPage(Seller seller) { + return SellerResponse.builder() + .email(seller.getEmail()) + .role(seller.getRole()) + .address(seller.getAddress()) + .registerDate(seller.getRegisterDate()) + .realName(seller.getRealName()) + .gender(seller.getGender()) + .phoneNum(seller.getPhoneNum()) + .nickname(seller.getNickname()) + .build(); + } +} From a6ea66c9d6d932429d4a8f56d60309b0e319fb82 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 02:13:03 +0900 Subject: [PATCH 65/76] =?UTF-8?q?SCRUM-41=20feat:=20=ED=8C=90=EB=A7=A4?= =?UTF-8?q?=EC=9E=90=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/config/ApplicationConfig.java | 16 +++--------- .../seller/controller/SellerController.java | 24 ++++++++++++----- .../domain/seller/dto/SellerRequest.java | 26 +++++++++++++++++++ .../golagola/domain/seller/entity/Seller.java | 8 ++++++ .../domain/seller/service/SellerService.java | 16 ++++++++++++ 5 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerRequest.java diff --git a/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java b/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java index fec7a69..7420773 100644 --- a/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java +++ b/src/main/java/com/kakaoteck/golagola/config/ApplicationConfig.java @@ -36,24 +36,15 @@ public UserDetailsService userDetailsService() { if (buyer != null) { System.out.println("Buyer found: " + username); - return new org.springframework.security.core.userdetails.User( - buyer.getEmail(), - buyer.getPassword(), - Collections.singleton(new SimpleGrantedAuthority("BUYER")) - ); + return buyer; // Buyer 객체를 반환 } // Try to find the user as a Seller Seller seller = sellerRepository.findByEmail(username).orElse(null); if (seller != null) { - System.out.println("Seller found: " + username); - System.out.println("Encoded password: " + seller.getPassword()); - return new org.springframework.security.core.userdetails.User( - seller.getEmail(), - seller.getPassword(), - Collections.singleton(new SimpleGrantedAuthority("SELLER")) - ); + System.out.println("Seller loaded: " + seller.getEmail()); + return seller; // Seller 객체를 반환 } throw new UsernameNotFoundException("User not found with username: " + username); @@ -61,6 +52,7 @@ public UserDetailsService userDetailsService() { } + @Bean public AuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java b/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java index 9ddd3eb..fd09e88 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java @@ -1,16 +1,18 @@ package com.kakaoteck.golagola.domain.seller.controller; +import com.kakaoteck.golagola.domain.seller.dto.SellerRequest; import com.kakaoteck.golagola.domain.seller.dto.SellerResponse; import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; import com.kakaoteck.golagola.domain.seller.service.SellerService; import com.kakaoteck.golagola.global.common.ApiResponse; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @@ -19,12 +21,20 @@ public class SellerController { private final SellerService sellerService; + private final SellerRepository sellerRepository; @Operation(summary = "판매자 마이페이지 조회", description = "판매자의 정보를 조회합니다.") @GetMapping("/mypage") - public ApiResponse getMyPage( - @AuthenticationPrincipal Seller seller - ) { + public ApiResponse getMyPage(@AuthenticationPrincipal Seller seller) { return ApiResponse.onSuccess(sellerService.getMyPage(seller)); } + + @Operation(summary = "판매자 마이페이지 수정", description = "판매자의 정보를 수정합니다.") + @PutMapping("/mypage") + public ApiResponse updateProfile( + @AuthenticationPrincipal Seller seller, + @RequestBody SellerRequest.MyPagePutDto request + ) { + return ApiResponse.onSuccess(sellerService.updateMyPage(seller, request)); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerRequest.java b/src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerRequest.java new file mode 100644 index 0000000..7691c69 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/dto/SellerRequest.java @@ -0,0 +1,26 @@ +package com.kakaoteck.golagola.domain.seller.dto; + +import com.kakaoteck.golagola.global.common.enums.Gender; +import com.kakaoteck.golagola.global.common.enums.Role; +import lombok.Builder; + +import java.time.LocalDate; + +@Builder +public record SellerRequest( + String nickname, + String realName, + Gender gender, + String email, + String address, + String phoneNum, + Role role, + LocalDate registerDate +) { + @Builder + public record MyPagePutDto( + String nickname, + String address, + String phoneNum + ) {} +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java index 2e2d568..4e3b22b 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/entity/Seller.java @@ -1,8 +1,10 @@ package com.kakaoteck.golagola.domain.seller.entity; import com.fasterxml.jackson.databind.ser.Serializers; +import com.kakaoteck.golagola.domain.buyer.dto.BuyerRequest; import com.kakaoteck.golagola.domain.order.entity.Order; import com.kakaoteck.golagola.domain.product.entity.Product; +import com.kakaoteck.golagola.domain.seller.dto.SellerRequest; import com.kakaoteck.golagola.global.common.BaseEntity; import com.kakaoteck.golagola.global.common.enums.Gender; import com.kakaoteck.golagola.global.common.enums.Role; @@ -103,6 +105,12 @@ public boolean isEnabled() { return true; } + public void updateProfile(SellerRequest.MyPagePutDto request) { + this.nickname = request.nickname(); + this.address = request.address(); + this.phoneNum = request.phoneNum(); + } + public static Seller from(Long sellerId, String nickname, Gender gender, String email, String password, String address, String phoneNum, Role role, String realName, LocalDate registerDate, List productList, List orderList) { diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java b/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java index 88a3b05..ad0d889 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/service/SellerService.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.seller.service; +import com.kakaoteck.golagola.domain.seller.dto.SellerRequest; import com.kakaoteck.golagola.domain.seller.dto.SellerResponse; import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; @@ -28,4 +29,19 @@ public SellerResponse getMyPage(Seller seller) { .nickname(seller.getNickname()) .build(); } + + public SellerResponse updateMyPage(Seller seller, SellerRequest.MyPagePutDto request) { + seller.updateProfile(request); + Seller savedSeller = sellerRepository.save(seller); + return SellerResponse.builder() + .email(savedSeller.getEmail()) + .role(savedSeller.getRole()) + .address(savedSeller.getAddress()) + .registerDate(savedSeller.getRegisterDate()) + .realName(savedSeller.getRealName()) + .gender(savedSeller.getGender()) + .phoneNum(savedSeller.getPhoneNum()) + .nickname(savedSeller.getNickname()) + .build(); + } } From e3173506ffa3aa003de927ecc514e6443e748506 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 02:21:20 +0900 Subject: [PATCH 66/76] =?UTF-8?q?SCRUM-51=20feat:=20Cart=20Domain=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/cart/controller/CartController.java | 4 ++++ .../com/kakaoteck/golagola/domain/cart/dto/CartRequest.java | 4 ++++ .../com/kakaoteck/golagola/domain/cart/dto/CartResponse.java | 4 ++++ .../kakaoteck/golagola/domain/cart/service/CartService.java | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java new file mode 100644 index 0000000..7dd4f8c --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.cart.controller; + +public class CartController { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java new file mode 100644 index 0000000..f5023f6 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.cart.dto; + +public record CartRequest() { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java new file mode 100644 index 0000000..2a792dc --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.cart.dto; + +public record CartResponse() { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java new file mode 100644 index 0000000..f466b3e --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.cart.service; + +public class CartService { +} From 08038dfa85af02cdd266ed17656255512900a5be Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 12:26:24 +0900 Subject: [PATCH 67/76] =?UTF-8?q?SCRUM-51=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cart/controller/CartController.java | 24 +++++++++++++++ .../domain/cart/dto/CartResponse.java | 11 ++++++- .../golagola/domain/cart/entity/Cart.java | 2 +- .../domain/cart/service/CartService.java | 29 +++++++++++++++++++ .../seller/controller/SellerController.java | 1 - 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java index 7dd4f8c..97b0c66 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java @@ -1,4 +1,28 @@ package com.kakaoteck.golagola.domain.cart.controller; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.cart.dto.CartResponse; +import com.kakaoteck.golagola.domain.cart.service.CartService; +import com.kakaoteck.golagola.global.common.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/cart") +@CrossOrigin("*") public class CartController { + + private final CartService cartService; + + @Operation(summary = "상품 장바구니 조회", description = "장바구니에 담긴 상품을 조회합니다. / 목록으로 조회됨") + @GetMapping() + public ApiResponse getCartProducts(@AuthenticationPrincipal Buyer buyer) { + return ApiResponse.onSuccess(cartService.getCartProducts(buyer)); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java index 2a792dc..2372ce0 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java @@ -1,4 +1,13 @@ package com.kakaoteck.golagola.domain.cart.dto; -public record CartResponse() { +import com.kakaoteck.golagola.domain.product.entity.Product; +import lombok.Builder; + +import java.util.List; + +@Builder +public record CartResponse( + List productList +) { + } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index df96b58..cc0898f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -19,7 +19,7 @@ public class Cart { @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "buyer_id", nullable = false) + @JoinColumn(name = "buyer_id") private Buyer buyer; @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL) diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java index f466b3e..b31775c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java @@ -1,4 +1,33 @@ package com.kakaoteck.golagola.domain.cart.service; +import com.kakaoteck.golagola.domain.buyer.dto.BuyerResponse; +import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.cart.dto.CartRequest; +import com.kakaoteck.golagola.domain.cart.dto.CartResponse; +import com.kakaoteck.golagola.domain.product.entity.Product; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional +@Slf4j public class CartService { + + public CartResponse getCartProducts(Buyer buyer) { + // Cart가 null이 아닌 경우에만 productList를 가져오고, 그렇지 않으면 빈 리스트를 반환 + List productList = Collections.emptyList(); + if (buyer.getCart() != null) { + productList = buyer.getCart().getProductList() != null ? buyer.getCart().getProductList() : Collections.emptyList(); + } + + return CartResponse.builder() + .productList(productList) + .build(); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java b/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java index fd09e88..f69fdf8 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/seller/controller/SellerController.java @@ -21,7 +21,6 @@ public class SellerController { private final SellerService sellerService; - private final SellerRepository sellerRepository; @Operation(summary = "판매자 마이페이지 조회", description = "판매자의 정보를 조회합니다.") @GetMapping("/mypage") From 2082f6c2a90ab38137f9eca2d3f800d251a68a42 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 12:41:15 +0900 Subject: [PATCH 68/76] =?UTF-8?q?SCRUM-51=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 24 +++++++++++++++++++ .../cart/controller/CartController.java | 16 +++++++++---- .../golagola/domain/cart/dto/CartRequest.java | 9 ++++++- .../golagola/domain/cart/entity/Cart.java | 7 ++++++ .../domain/cart/service/CartService.java | 18 ++++++++++++++ .../common/code/status/ErrorStatus.java | 3 +++ 6 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index 980dd1e..a7fac3a 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -3,6 +3,7 @@ import com.kakaoteck.golagola.domain.buyer.dto.BuyerRequest; import com.kakaoteck.golagola.domain.cart.entity.Cart; import com.kakaoteck.golagola.domain.order.entity.Order; +import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.domain.review.entity.Review; import com.kakaoteck.golagola.global.common.enums.Gender; import com.kakaoteck.golagola.global.common.enums.Role; @@ -112,6 +113,29 @@ public void updateProfile(BuyerRequest.MyPagePutDto request) { this.phoneNum = request.phoneNum(); } + public void assignCart(Cart cart) { + if (cart != null) { + this.cart = cart; + cart.assignBuyer(this); + } + } + + public void addProductToCart(Product product) { + if (this.cart == null) { + this.cart = new Cart(); // 새로운 Cart 객체 생성 + this.cart.assignBuyer(this); // Cart와 Buyer 간의 양방향 연관관계 설정 + } + this.cart.getProductList().add(product); + } + + public Cart getOrCreateCart() { + if (this.cart == null) { + this.cart = new Cart(); // 새로운 Cart 객체 생성 + this.cart.assignBuyer(this); // Cart와 Buyer 간의 양방향 연관관계 설정 + } + return this.cart; + } + public static Buyer from(Long buyerId, String nickname, String realName, Gender gender, String email, String password, String address, String phoneNum, Role role, LocalDate registerDate) { return Buyer.builder() diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java index 97b0c66..32c5e9c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java @@ -1,16 +1,15 @@ package com.kakaoteck.golagola.domain.cart.controller; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; +import com.kakaoteck.golagola.domain.cart.dto.CartRequest; import com.kakaoteck.golagola.domain.cart.dto.CartResponse; import com.kakaoteck.golagola.domain.cart.service.CartService; import com.kakaoteck.golagola.global.common.ApiResponse; +import io.lettuce.core.StrAlgoArgs; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @@ -25,4 +24,13 @@ public class CartController { public ApiResponse getCartProducts(@AuthenticationPrincipal Buyer buyer) { return ApiResponse.onSuccess(cartService.getCartProducts(buyer)); } + + @Operation(summary = "상품 장바구니 추가", description = "장바구니에 상품을 추가합니다.") + @PostMapping() + public ApiResponse addCartProduct( + @AuthenticationPrincipal Buyer buyer, + @RequestBody CartRequest request + ) { + return ApiResponse.onSuccess(cartService.addCartProduct(buyer, request.productId())); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java index f5023f6..a91de42 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartRequest.java @@ -1,4 +1,11 @@ package com.kakaoteck.golagola.domain.cart.dto; -public record CartRequest() { +import com.kakaoteck.golagola.domain.product.entity.Product; +import lombok.Builder; + +@Builder +public record CartRequest( + Long productId + +) { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index cc0898f..ad35481 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -29,4 +29,11 @@ public class Cart { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long cartId; + public void assignBuyer(Buyer buyer) { + if (buyer != null) { + this.buyer = buyer; + buyer.assignCart(this); + } + } + } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java index b31775c..1fa828a 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java @@ -5,6 +5,9 @@ import com.kakaoteck.golagola.domain.cart.dto.CartRequest; import com.kakaoteck.golagola.domain.cart.dto.CartResponse; import com.kakaoteck.golagola.domain.product.entity.Product; +import com.kakaoteck.golagola.domain.product.repository.ProductRepository; +import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; +import com.kakaoteck.golagola.global.common.exception.GeneralException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -12,6 +15,7 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor @@ -19,6 +23,8 @@ @Slf4j public class CartService { + private final ProductRepository productRepository; + public CartResponse getCartProducts(Buyer buyer) { // Cart가 null이 아닌 경우에만 productList를 가져오고, 그렇지 않으면 빈 리스트를 반환 List productList = Collections.emptyList(); @@ -30,4 +36,16 @@ public CartResponse getCartProducts(Buyer buyer) { .productList(productList) .build(); } + + public CartResponse addCartProduct(Buyer buyer, Long productId) { + Product product = productRepository.findById(productId) + .orElseThrow(() -> new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT)); + + // Buyer의 cart에 product를 추가 + buyer.addProductToCart(product); + + return CartResponse.builder() + .productList(buyer.getCart().getProductList()) + .build(); + } } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index d1b6ad6..85396c3 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -20,6 +20,9 @@ public enum ErrorStatus implements BaseErrorCode { _LOGIN_USER_INVALID(HttpStatus.BAD_REQUEST, "USER401", "로그인 중 오류가 발생하였습니다."), _INVALID_USER(HttpStatus.BAD_REQUEST, "USER401" , "아이디 또는 비밀번호가 틀렸습니다."), + // Product 에러 + _NOT_FOUND_PRODUCT(HttpStatus.NOT_FOUND, "USER400", "제품이 존재하지 않습니다."), + // Security 에러 INVALID_TOKEN(HttpStatus.BAD_REQUEST, "SEC4001", "잘못된 형식의 토큰입니다."), UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "SEC4010", "인증이 필요합니다."), From 6e10098197870e958df67c661be9b09ecedb4cf5 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 12:46:28 +0900 Subject: [PATCH 69/76] =?UTF-8?q?SCRUM-51=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cart/controller/CartController.java | 11 ++++++++++ .../domain/cart/service/CartService.java | 20 +++++++++++++++++++ .../common/code/status/ErrorStatus.java | 1 + 3 files changed, 32 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java index 32c5e9c..b46d475 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java @@ -33,4 +33,15 @@ public ApiResponse addCartProduct( ) { return ApiResponse.onSuccess(cartService.addCartProduct(buyer, request.productId())); } + + @Operation(summary = "상품 장바구니 삭제", description = "장바구니에 있는 상품 목록을 수정합니다.") + @DeleteMapping() + public ApiResponse deleteCartProduct( + @AuthenticationPrincipal Buyer buyer, + @RequestBody CartRequest request + ) { + return ApiResponse.onSuccess(cartService.deleteCartProduct(buyer, request.productId())); + } + + } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java index 1fa828a..6381f0c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java @@ -48,4 +48,24 @@ public CartResponse addCartProduct(Buyer buyer, Long productId) { .productList(buyer.getCart().getProductList()) .build(); } + + public CartResponse deleteCartProduct(Buyer buyer, Long productId) { + if (buyer.getCart() == null || buyer.getCart().getProductList() == null) { + throw new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT_IN_CART); + } + + // Buyer의 cart에서 해당 productId에 해당하는 제품을 찾음 + List productList = buyer.getCart().getProductList(); + Product productToRemove = productList.stream() + .filter(product -> product.getProductId().equals(productId)) + .findFirst() + .orElseThrow(() -> new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT_IN_CART)); + + // 제품을 장바구니에서 삭제 + productList.remove(productToRemove); + + return CartResponse.builder() + .productList(productList) + .build(); + } } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index 85396c3..d58a254 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -22,6 +22,7 @@ public enum ErrorStatus implements BaseErrorCode { // Product 에러 _NOT_FOUND_PRODUCT(HttpStatus.NOT_FOUND, "USER400", "제품이 존재하지 않습니다."), + _NOT_FOUND_PRODUCT_IN_CART(HttpStatus.NOT_FOUND, "USER400", "제품이 장바구니에 존재하지 않습니다."), // Security 에러 INVALID_TOKEN(HttpStatus.BAD_REQUEST, "SEC4001", "잘못된 형식의 토큰입니다."), From 170c581286029246238259bba59d3e742185b945 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 12:51:23 +0900 Subject: [PATCH 70/76] =?UTF-8?q?SCRUM-51=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EB=B9=84=EC=9A=B0?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/cart/controller/CartController.java | 8 +++++++- .../golagola/domain/cart/service/CartService.java | 11 +++++++++++ .../global/common/code/status/ErrorStatus.java | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java index b46d475..1903bf0 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/controller/CartController.java @@ -43,5 +43,11 @@ public ApiResponse deleteCartProduct( return ApiResponse.onSuccess(cartService.deleteCartProduct(buyer, request.productId())); } - + @Operation(summary = "상품 장바구니 비우기", description = "장바구니를 비웁니다.") + @DeleteMapping("/empty") + public ApiResponse emptyCart( + @AuthenticationPrincipal Buyer buyer + ) { + return ApiResponse.onSuccess(cartService.emptyCart(buyer)); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java index 6381f0c..238c57c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java @@ -68,4 +68,15 @@ public CartResponse deleteCartProduct(Buyer buyer, Long productId) { .productList(productList) .build(); } + + public String emptyCart(Buyer buyer) { + if (buyer.getCart() == null || buyer.getCart().getProductList() == null) { + throw new GeneralException(ErrorStatus._CART_IS_ALREADY_EMPTY); + } + + // 장바구니를 비움 + buyer.getCart().getProductList().clear(); + + return "장바구니에 있는 모든 제품이 삭제되었습니다."; + } } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index d58a254..98715c8 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -24,6 +24,9 @@ public enum ErrorStatus implements BaseErrorCode { _NOT_FOUND_PRODUCT(HttpStatus.NOT_FOUND, "USER400", "제품이 존재하지 않습니다."), _NOT_FOUND_PRODUCT_IN_CART(HttpStatus.NOT_FOUND, "USER400", "제품이 장바구니에 존재하지 않습니다."), + // Cart 에러 + _CART_IS_ALREADY_EMPTY(HttpStatus.BAD_REQUEST, "USER400", "장바구니가 이미 비어있습니다."), + // Security 에러 INVALID_TOKEN(HttpStatus.BAD_REQUEST, "SEC4001", "잘못된 형식의 토큰입니다."), UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "SEC4010", "인증이 필요합니다."), From d7fa34b8571a7334cac17eeb72f6acbeea69d092 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 12:55:48 +0900 Subject: [PATCH 71/76] SCRUM-44 feat: product folder init --- .../golagola/domain/product/controller/ProductController.java | 4 ++++ .../kakaoteck/golagola/domain/product/dto/ProductRequest.java | 4 ++++ .../golagola/domain/product/dto/ProductResponse.java | 4 ++++ .../golagola/domain/product/service/ProductService.java | 4 ++++ 4 files changed, 16 insertions(+) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java new file mode 100644 index 0000000..503e99f --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.product.controller; + +public class ProductController { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java new file mode 100644 index 0000000..e9370f9 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.product.dto; + +public record ProductRequest() { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java new file mode 100644 index 0000000..a697e98 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.product.dto; + +public record ProductResponse() { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java new file mode 100644 index 0000000..eb842d5 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java @@ -0,0 +1,4 @@ +package com.kakaoteck.golagola.domain.product.service; + +public class ProductService { +} From b7b58b0a958037b89098b00acf37d0e0afa4c73b Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 13:11:19 +0900 Subject: [PATCH 72/76] =?UTF-8?q?SCRUM-44=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/controller/ProductController.java | 25 +++++++++++ .../domain/product/dto/ProductRequest.java | 17 ++++++- .../domain/product/entity/Product.java | 4 +- .../product/service/ProductService.java | 44 +++++++++++++++++++ 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java index 503e99f..7f25933 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java @@ -1,4 +1,29 @@ package com.kakaoteck.golagola.domain.product.controller; +import com.kakaoteck.golagola.domain.product.dto.ProductRequest; +import com.kakaoteck.golagola.domain.product.service.ProductService; +import com.kakaoteck.golagola.domain.seller.dto.SellerResponse; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.global.common.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/product") +@CrossOrigin("*") public class ProductController { + + private final ProductService productService; + + @Operation(summary = "상품 등록", description = "상품을 등록합니다. 판매자 전용") + @PostMapping() + public ApiResponse postProduct( + @AuthenticationPrincipal Seller seller, + @RequestBody ProductRequest request + ) { + return ApiResponse.onSuccess(productService.postProduct(seller, request)); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java index e9370f9..7fb83b3 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductRequest.java @@ -1,4 +1,19 @@ package com.kakaoteck.golagola.domain.product.dto; -public record ProductRequest() { +import com.kakaoteck.golagola.global.common.enums.Category; +import com.kakaoteck.golagola.global.common.enums.DetailCategory; +import lombok.Builder; + +@Builder +public record ProductRequest( + String productName, + String productExplanation, + String productImage, + Long productPrice, + Long productInventory, + Category category, + DetailCategory detailCategory, + Long discount, + Long productQuantity +) { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index 3031f8f..0ec8649 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -77,10 +77,10 @@ public class Product extends BaseEntity { @Column(nullable = false) private Long productQuantity; - @Column(nullable = false) + @Column() private Float predictReviewStar; - @Column(nullable = false) + @Column() private Float productStar; public static Product from(Long productId, Seller seller, Cart cart, List reviewList, diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java index eb842d5..de30e34 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java @@ -1,4 +1,48 @@ package com.kakaoteck.golagola.domain.product.service; +import com.kakaoteck.golagola.domain.product.dto.ProductRequest; +import com.kakaoteck.golagola.domain.product.entity.Product; +import com.kakaoteck.golagola.domain.product.repository.ProductRepository; +import com.kakaoteck.golagola.domain.seller.entity.Seller; +import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalTime; + +@Service +@RequiredArgsConstructor +@Transactional +@Slf4j public class ProductService { + + private final SellerRepository sellerRepository; + private final ProductRepository productRepository; + + public String postProduct(Seller seller, ProductRequest request) { + // Product 객체 생성 + Product product = Product.builder() + .seller(seller) + .productName(request.productName()) + .productExplanation(request.productExplanation()) + .productImage(request.productImage()) + .productPrice(request.productPrice()) + .productInventory(request.productInventory()) + .category(request.category()) + .detailCategory(request.detailCategory()) + .discount(request.discount()) + .createTime(LocalTime.now()) + .updateTime(LocalTime.now()) + .productQuantity(request.productQuantity()) + .predictReviewStar(0.0f) // 초기 예상 리뷰 별점 + .productStar(0.0f) // 초기 실제 리뷰 별점 + .build(); + + // Product 저장 + productRepository.save(product); + + return "상품등록 성공"; + } } From 79a1b53100aee0fc16500f1fd2f863a06d9fca25 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 13:22:55 +0900 Subject: [PATCH 73/76] =?UTF-8?q?SCRUM-44=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/controller/ProductController.java | 11 +++++ .../domain/product/dto/ProductResponse.java | 20 ++++++++- .../domain/product/entity/Product.java | 16 +++++++ .../product/service/ProductService.java | 44 +++++++++++++++++++ .../common/code/status/ErrorStatus.java | 1 + 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java index 7f25933..d97e4a8 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.product.controller; import com.kakaoteck.golagola.domain.product.dto.ProductRequest; +import com.kakaoteck.golagola.domain.product.dto.ProductResponse; import com.kakaoteck.golagola.domain.product.service.ProductService; import com.kakaoteck.golagola.domain.seller.dto.SellerResponse; import com.kakaoteck.golagola.domain.seller.entity.Seller; @@ -26,4 +27,14 @@ public ApiResponse postProduct( ) { return ApiResponse.onSuccess(productService.postProduct(seller, request)); } + + @Operation(summary = "상품 수정", description = "상품 정보를 수정합니다.") + @PutMapping() + public ApiResponse modifyProduct( + @AuthenticationPrincipal Seller seller, + @PathVariable Long productId, + @RequestBody ProductRequest request + ) { + return ApiResponse.onSuccess(productService.modifyProduct(seller, productId, request)); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java index a697e98..078c281 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java @@ -1,4 +1,22 @@ package com.kakaoteck.golagola.domain.product.dto; -public record ProductResponse() { +import com.kakaoteck.golagola.global.common.enums.Category; +import com.kakaoteck.golagola.global.common.enums.DetailCategory; +import lombok.Builder; + +@Builder +public record ProductResponse( + Long productId, + String productName, + String productExplanation, + String productImage, + Long productPrice, + Long productInventory, + Category category, + DetailCategory detailCategory, + Long discount, + Long productQuantity, + Float predictReviewStar, + Float productStar +) { } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index 0ec8649..ddef5af 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -83,6 +83,22 @@ public class Product extends BaseEntity { @Column() private Float productStar; + + public void updateProduct(String productName, String productExplanation, String productImage, Long productPrice, + Long productInventory, Category category, DetailCategory detailCategory, + Long discount, Long productQuantity, LocalTime updateTime) { + this.productName = productName; + this.productExplanation = productExplanation; + this.productImage = productImage; + this.productPrice = productPrice; + this.productInventory = productInventory; + this.category = category; + this.detailCategory = detailCategory; + this.discount = discount; + this.productQuantity = productQuantity; + this.updateTime = updateTime; + } + public static Product from(Long productId, Seller seller, Cart cart, List reviewList, List orderProductList, String productName, String productExplanation, String productImage, Long productPrice, diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java index de30e34..7ae6b82 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java @@ -1,10 +1,13 @@ package com.kakaoteck.golagola.domain.product.service; import com.kakaoteck.golagola.domain.product.dto.ProductRequest; +import com.kakaoteck.golagola.domain.product.dto.ProductResponse; import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.domain.product.repository.ProductRepository; import com.kakaoteck.golagola.domain.seller.entity.Seller; import com.kakaoteck.golagola.domain.seller.repository.SellerRepository; +import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; +import com.kakaoteck.golagola.global.common.exception.GeneralException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -45,4 +48,45 @@ public String postProduct(Seller seller, ProductRequest request) { return "상품등록 성공"; } + + public ProductResponse modifyProduct(Seller seller, Long productId, ProductRequest request) { + // productId로 해당 상품을 찾음 + Product product = productRepository.findById(productId) + .orElseThrow(() -> new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT)); + + // 해당 상품이 현재 로그인한 seller가 등록한 것인지 확인 + if (!product.getSeller().getSellerId().equals(seller.getSellerId())) { + throw new GeneralException(ErrorStatus._UNAUTHORIZED_ACCESS); + } + + // Product 정보 업데이트 + product.updateProduct( + request.productName(), + request.productExplanation(), + request.productImage(), + request.productPrice(), + request.productInventory(), + request.category(), + request.detailCategory(), + request.discount(), + request.productQuantity(), + LocalTime.now() // updateTime을 현재 시간으로 업데이트 + ); + + // 업데이트된 Product 저장 + productRepository.save(product); + + return ProductResponse.builder() + .productId(product.getProductId()) + .productName(product.getProductName()) + .productExplanation(product.getProductExplanation()) + .productImage(product.getProductImage()) + .productPrice(product.getProductPrice()) + .productInventory(product.getProductInventory()) + .category(product.getCategory()) + .detailCategory(product.getDetailCategory()) + .discount(product.getDiscount()) + .productQuantity(product.getProductQuantity()) + .build(); + } } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index 98715c8..f7e5f86 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -19,6 +19,7 @@ public enum ErrorStatus implements BaseErrorCode { _NOT_FOUND_USER(HttpStatus.NOT_FOUND, "USER400", "사용자가 존재하지 않습니다."), _LOGIN_USER_INVALID(HttpStatus.BAD_REQUEST, "USER401", "로그인 중 오류가 발생하였습니다."), _INVALID_USER(HttpStatus.BAD_REQUEST, "USER401" , "아이디 또는 비밀번호가 틀렸습니다."), + _UNAUTHORIZED_ACCESS(HttpStatus.UNAUTHORIZED, "USER401", "본인이 등록한 제품만 수정할 수 있습니다."), // Product 에러 _NOT_FOUND_PRODUCT(HttpStatus.NOT_FOUND, "USER400", "제품이 존재하지 않습니다."), From 5534d2a42eb08623afde6ba0bbaa88e51e9655ca Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 13:30:16 +0900 Subject: [PATCH 74/76] =?UTF-8?q?SCRUM-44=20feat:=20=EC=83=81=ED=92=88=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/controller/ProductController.java | 13 ++++++++++++- .../domain/product/service/ProductService.java | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java index d97e4a8..2fe7a71 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/controller/ProductController.java @@ -29,7 +29,7 @@ public ApiResponse postProduct( } @Operation(summary = "상품 수정", description = "상품 정보를 수정합니다.") - @PutMapping() + @PutMapping("/{productId}") public ApiResponse modifyProduct( @AuthenticationPrincipal Seller seller, @PathVariable Long productId, @@ -37,4 +37,15 @@ public ApiResponse modifyProduct( ) { return ApiResponse.onSuccess(productService.modifyProduct(seller, productId, request)); } + + @Operation(summary = "상품 삭제", description = "상품을 삭제합니다. 판매자 전용") + @DeleteMapping("/{productId}") + public ApiResponse deleteProduct( + @AuthenticationPrincipal Seller seller, + @PathVariable Long productId + ) { + productService.deleteProduct(seller, productId); + return ApiResponse.onSuccess("상품이 성공적으로 삭제되었습니다."); + } + } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java index 7ae6b82..490308c 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java @@ -89,4 +89,18 @@ public ProductResponse modifyProduct(Seller seller, Long productId, ProductReque .productQuantity(product.getProductQuantity()) .build(); } + + public void deleteProduct(Seller seller, Long productId) { + // productId로 Product를 찾음 + Product product = productRepository.findById(productId) + .orElseThrow(() -> new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT)); + + // 해당 Product가 현재 로그인된 seller가 등록한 제품인지 확인 + if (!product.getSeller().getSellerId().equals(seller.getSellerId())) { + throw new GeneralException(ErrorStatus._UNAUTHORIZED_ACCESS); + } + + // Product 삭제 + productRepository.delete(product); + } } From cf500f254aef16d3eb99a54445c5476d469c0d3d Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 15:04:07 +0900 Subject: [PATCH 75/76] =?UTF-8?q?SCRUM-44=20fix:=20=EC=A7=80=EC=97=B0?= =?UTF-8?q?=EB=A1=9C=EB=94=A9=20=EB=AC=B8=EC=A0=9C,=20=EB=8B=A4=EB=8C=80?= =?UTF-8?q?=EB=8B=A4=20=EA=B4=80=EA=B3=84,=20dto=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/buyer/entity/Buyer.java | 30 ++++--- .../domain/cart/dto/CartResponse.java | 4 +- .../golagola/domain/cart/entity/Cart.java | 15 +++- .../domain/cart/entity/CartProduct.java | 43 ++++++++++ .../repository/CartProductRepository.java | 10 +++ .../domain/cart/service/CartService.java | 80 ++++++++++++------- .../domain/product/dto/ProductResponse.java | 7 ++ .../domain/product/entity/Product.java | 35 ++++---- .../golagola/domain/seller/entity/Seller.java | 2 + .../common/code/status/ErrorStatus.java | 1 + 10 files changed, 161 insertions(+), 66 deletions(-) create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/entity/CartProduct.java create mode 100644 src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartProductRepository.java diff --git a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java index a7fac3a..ec1386f 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java +++ b/src/main/java/com/kakaoteck/golagola/domain/buyer/entity/Buyer.java @@ -2,6 +2,7 @@ import com.kakaoteck.golagola.domain.buyer.dto.BuyerRequest; import com.kakaoteck.golagola.domain.cart.entity.Cart; +import com.kakaoteck.golagola.domain.cart.entity.CartProduct; import com.kakaoteck.golagola.domain.order.entity.Order; import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.domain.review.entity.Review; @@ -25,8 +26,8 @@ @Entity @NoArgsConstructor @AllArgsConstructor -@Builder @Getter +@Builder @Table(name = "buyer_table") public class Buyer extends BaseEntity implements UserDetails { @@ -63,7 +64,7 @@ public class Buyer extends BaseEntity implements UserDetails { @Column(nullable = false) private LocalDate registerDate; - @OneToOne(mappedBy = "buyer", cascade = CascadeType.ALL) + @OneToOne(mappedBy = "buyer", cascade = CascadeType.ALL, orphanRemoval = true) private Cart cart; @OneToMany(mappedBy = "buyer", cascade = CascadeType.ALL) @@ -114,28 +115,36 @@ public void updateProfile(BuyerRequest.MyPagePutDto request) { } public void assignCart(Cart cart) { - if (cart != null) { - this.cart = cart; + this.cart = cart; + if (cart.getBuyer() != this) { cart.assignBuyer(this); } } - public void addProductToCart(Product product) { + // Cart를 자동으로 초기화 + @PrePersist + public void initializeCart() { if (this.cart == null) { - this.cart = new Cart(); // 새로운 Cart 객체 생성 - this.cart.assignBuyer(this); // Cart와 Buyer 간의 양방향 연관관계 설정 + Cart newCart = new Cart(); + newCart.assignBuyer(this); + this.cart = newCart; } - this.cart.getProductList().add(product); } public Cart getOrCreateCart() { if (this.cart == null) { - this.cart = new Cart(); // 새로운 Cart 객체 생성 - this.cart.assignBuyer(this); // Cart와 Buyer 간의 양방향 연관관계 설정 + Cart newCart = new Cart(); + newCart.assignBuyer(this); + this.cart = newCart; } return this.cart; } + public void addProductToCart(Product product) { + Cart cart = this.getOrCreateCart(); + cart.addProduct(product); + } + public static Buyer from(Long buyerId, String nickname, String realName, Gender gender, String email, String password, String address, String phoneNum, Role role, LocalDate registerDate) { return Buyer.builder() @@ -152,4 +161,3 @@ public static Buyer from(Long buyerId, String nickname, String realName, Gender .build(); } } - diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java index 2372ce0..9ceb9b6 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/dto/CartResponse.java @@ -1,5 +1,6 @@ package com.kakaoteck.golagola.domain.cart.dto; +import com.kakaoteck.golagola.domain.product.dto.ProductResponse; import com.kakaoteck.golagola.domain.product.entity.Product; import lombok.Builder; @@ -7,7 +8,6 @@ @Builder public record CartResponse( - List productList + List productList ) { - } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java index ad35481..c1b4ca6 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/Cart.java @@ -8,6 +8,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.ArrayList; import java.util.List; @Entity @@ -22,18 +23,24 @@ public class Cart { @JoinColumn(name = "buyer_id") private Buyer buyer; - @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL) - private List productList; + @OneToMany(mappedBy = "cart", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + private List cartProducts = new ArrayList<>(); @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long cartId; public void assignBuyer(Buyer buyer) { - if (buyer != null) { - this.buyer = buyer; + this.buyer = buyer; + if (buyer.getCart() != this) { buyer.assignCart(this); } } + public void addProduct(Product product) { + CartProduct cartProduct = new CartProduct(); + cartProduct.assignCart(this); + cartProduct.assignProduct(product); + this.cartProducts.add(cartProduct); + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/entity/CartProduct.java b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/CartProduct.java new file mode 100644 index 0000000..b6257a7 --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/entity/CartProduct.java @@ -0,0 +1,43 @@ +package com.kakaoteck.golagola.domain.cart.entity; + +import com.kakaoteck.golagola.domain.product.entity.Product; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +@Table(name = "cart_product_table") +public class CartProduct { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "cart_id") + private Cart cart; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "product_id") + private Product product; + + public void assignCart(Cart cart) { + this.cart = cart; + if (!cart.getCartProducts().contains(this)) { + cart.getCartProducts().add(this); + } + } + + public void assignProduct(Product product) { + this.product = product; + if (!product.getCartProducts().contains(this)) { + product.getCartProducts().add(this); + } + } +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartProductRepository.java b/src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartProductRepository.java new file mode 100644 index 0000000..155a72e --- /dev/null +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/repository/CartProductRepository.java @@ -0,0 +1,10 @@ +package com.kakaoteck.golagola.domain.cart.repository; + +import com.kakaoteck.golagola.domain.cart.entity.Cart; +import com.kakaoteck.golagola.domain.cart.entity.CartProduct; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CartProductRepository extends JpaRepository { +} diff --git a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java index 238c57c..31cac9e 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/cart/service/CartService.java @@ -1,21 +1,23 @@ package com.kakaoteck.golagola.domain.cart.service; -import com.kakaoteck.golagola.domain.buyer.dto.BuyerResponse; import com.kakaoteck.golagola.domain.buyer.entity.Buyer; -import com.kakaoteck.golagola.domain.cart.dto.CartRequest; import com.kakaoteck.golagola.domain.cart.dto.CartResponse; +import com.kakaoteck.golagola.domain.cart.entity.Cart; +import com.kakaoteck.golagola.domain.cart.entity.CartProduct; +import com.kakaoteck.golagola.domain.cart.repository.CartProductRepository; +import com.kakaoteck.golagola.domain.product.dto.ProductResponse; import com.kakaoteck.golagola.domain.product.entity.Product; import com.kakaoteck.golagola.domain.product.repository.ProductRepository; import com.kakaoteck.golagola.global.common.code.status.ErrorStatus; import com.kakaoteck.golagola.global.common.exception.GeneralException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.hibernate.Hibernate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; import java.util.List; -import java.util.Optional; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -24,16 +26,29 @@ public class CartService { private final ProductRepository productRepository; + private final CartProductRepository cartProductRepository; public CartResponse getCartProducts(Buyer buyer) { - // Cart가 null이 아닌 경우에만 productList를 가져오고, 그렇지 않으면 빈 리스트를 반환 - List productList = Collections.emptyList(); - if (buyer.getCart() != null) { - productList = buyer.getCart().getProductList() != null ? buyer.getCart().getProductList() : Collections.emptyList(); - } + Cart cart = buyer.getCart(); + + // Lazy 로딩을 명시적으로 초기화 + Hibernate.initialize(cart.getCartProducts()); + + // CartProduct 객체에서 Product를 추출하여 리스트 생성 + List products = cart.getCartProducts().stream() + .map(cartProduct -> { + Product product = cartProduct.getProduct(); + return ProductResponse.ProductDto.builder() + .productId(product.getProductId()) + .productName(product.getProductName()) + .productExplanation(product.getProductExplanation()) + .productPrice(product.getProductPrice()) + .build(); + }) + .collect(Collectors.toList()); return CartResponse.builder() - .productList(productList) + .productList(products) .build(); } @@ -41,41 +56,48 @@ public CartResponse addCartProduct(Buyer buyer, Long productId) { Product product = productRepository.findById(productId) .orElseThrow(() -> new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT)); - // Buyer의 cart에 product를 추가 - buyer.addProductToCart(product); + Cart cart = buyer.getOrCreateCart(); - return CartResponse.builder() - .productList(buyer.getCart().getProductList()) + // 장바구니에 이미 동일한 상품이 있는지 확인 + boolean productExistsInCart = cart.getCartProducts().stream() + .anyMatch(cp -> cp.getProduct().getProductId().equals(productId)); + + if (productExistsInCart) { + throw new GeneralException(ErrorStatus._PRODUCT_ALREADY_IN_CART); // 이미 존재한다면 예외를 던집니다. + } + + // 장바구니에 상품 추가 + CartProduct cartProduct = CartProduct.builder() + .cart(cart) + .product(product) .build(); + + cartProductRepository.save(cartProduct); + + return getCartProducts(buyer); } public CartResponse deleteCartProduct(Buyer buyer, Long productId) { - if (buyer.getCart() == null || buyer.getCart().getProductList() == null) { - throw new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT_IN_CART); - } + Cart cart = buyer.getCart(); - // Buyer의 cart에서 해당 productId에 해당하는 제품을 찾음 - List productList = buyer.getCart().getProductList(); - Product productToRemove = productList.stream() - .filter(product -> product.getProductId().equals(productId)) + CartProduct cartProduct = cart.getCartProducts().stream() + .filter(cp -> cp.getProduct().getProductId().equals(productId)) .findFirst() .orElseThrow(() -> new GeneralException(ErrorStatus._NOT_FOUND_PRODUCT_IN_CART)); - // 제품을 장바구니에서 삭제 - productList.remove(productToRemove); + cartProductRepository.delete(cartProduct); - return CartResponse.builder() - .productList(productList) - .build(); + return getCartProducts(buyer); } public String emptyCart(Buyer buyer) { - if (buyer.getCart() == null || buyer.getCart().getProductList() == null) { + Cart cart = buyer.getCart(); + + if (cart.getCartProducts().isEmpty()) { throw new GeneralException(ErrorStatus._CART_IS_ALREADY_EMPTY); } - // 장바구니를 비움 - buyer.getCart().getProductList().clear(); + cartProductRepository.deleteAll(cart.getCartProducts()); return "장바구니에 있는 모든 제품이 삭제되었습니다."; } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java index 078c281..9b5eec4 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/dto/ProductResponse.java @@ -19,4 +19,11 @@ public record ProductResponse( Float predictReviewStar, Float productStar ) { + @Builder + public record ProductDto (Long productId, + String productName, + String productExplanation, + Long productPrice) { + + } } diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java index ddef5af..52db5a0 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/entity/Product.java @@ -1,6 +1,7 @@ package com.kakaoteck.golagola.domain.product.entity; -import com.kakaoteck.golagola.domain.cart.entity.Cart; +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.kakaoteck.golagola.domain.cart.entity.CartProduct; import com.kakaoteck.golagola.domain.orderProduct.entity.OrderProduct; import com.kakaoteck.golagola.domain.review.entity.Review; import com.kakaoteck.golagola.domain.seller.entity.Seller; @@ -30,11 +31,11 @@ public class Product extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "seller_id") + @JsonBackReference private Seller seller; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "cart_id") - private Cart cart; + @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true) + private List cartProducts; @OneToMany(mappedBy = "product", cascade = CascadeType.ALL) private List reviewList; @@ -83,7 +84,7 @@ public class Product extends BaseEntity { @Column() private Float productStar; - + // Product 수정 메서드 public void updateProduct(String productName, String productExplanation, String productImage, Long productPrice, Long productInventory, Category category, DetailCategory detailCategory, Long discount, Long productQuantity, LocalTime updateTime) { @@ -99,18 +100,13 @@ public void updateProduct(String productName, String productExplanation, String this.updateTime = updateTime; } - public static Product from(Long productId, Seller seller, Cart cart, List reviewList, - List orderProductList, String productName, - String productExplanation, String productImage, Long productPrice, - Long productInventory, Category category, DetailCategory detailCategory, - Long discount, LocalTime createTime, LocalTime updateTime, - Long productQuantity, Float predictReviewStar, Float productStar) { + // Product 생성 메서드 + public static Product createProduct(Seller seller, String productName, String productExplanation, + String productImage, Long productPrice, Long productInventory, + Category category, DetailCategory detailCategory, Long discount, + Long productQuantity) { return Product.builder() - .productId(productId) .seller(seller) - .cart(cart) - .reviewList(reviewList) - .orderProductList(orderProductList) .productName(productName) .productExplanation(productExplanation) .productImage(productImage) @@ -119,12 +115,11 @@ public static Product from(Long productId, Seller seller, Cart cart, List productList = new ArrayList<>(); @OneToMany(mappedBy = "seller", cascade = CascadeType.ALL) diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index f7e5f86..c40e425 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -27,6 +27,7 @@ public enum ErrorStatus implements BaseErrorCode { // Cart 에러 _CART_IS_ALREADY_EMPTY(HttpStatus.BAD_REQUEST, "USER400", "장바구니가 이미 비어있습니다."), + _PRODUCT_ALREADY_IN_CART(HttpStatus.BAD_REQUEST, "USER400", "장바구니에 이미 해당상품이 존재합니다."), // Security 에러 INVALID_TOKEN(HttpStatus.BAD_REQUEST, "SEC4001", "잘못된 형식의 토큰입니다."), From b6308e76f17e66abc7f1675356dc79c3beebb030 Mon Sep 17 00:00:00 2001 From: Kim Seung-yeop Date: Tue, 13 Aug 2024 15:08:14 +0900 Subject: [PATCH 76/76] =?UTF-8?q?SCRUM-44=20feat:=20=EC=9E=A5=EB=B0=94?= =?UTF-8?q?=EA=B5=AC=EB=8B=88=EC=97=90=20=EB=8B=B4=EA=B2=A8=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EC=83=81=ED=92=88=EC=9D=80=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B6=88=EA=B0=80=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../golagola/domain/product/service/ProductService.java | 8 ++++++++ .../golagola/global/common/code/status/ErrorStatus.java | 1 + 2 files changed, 9 insertions(+) diff --git a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java index 490308c..5166ba8 100644 --- a/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java +++ b/src/main/java/com/kakaoteck/golagola/domain/product/service/ProductService.java @@ -100,7 +100,15 @@ public void deleteProduct(Seller seller, Long productId) { throw new GeneralException(ErrorStatus._UNAUTHORIZED_ACCESS); } + // 해당 Product가 장바구니에 담겨 있는지 확인 + boolean isInCart = product.getCartProducts() != null && !product.getCartProducts().isEmpty(); + + if (isInCart) { + throw new GeneralException(ErrorStatus._PRODUCT_IN_CART_CANNOT_DELETE); + } + // Product 삭제 productRepository.delete(product); } + } diff --git a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java index c40e425..3849fbc 100644 --- a/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java +++ b/src/main/java/com/kakaoteck/golagola/global/common/code/status/ErrorStatus.java @@ -24,6 +24,7 @@ public enum ErrorStatus implements BaseErrorCode { // Product 에러 _NOT_FOUND_PRODUCT(HttpStatus.NOT_FOUND, "USER400", "제품이 존재하지 않습니다."), _NOT_FOUND_PRODUCT_IN_CART(HttpStatus.NOT_FOUND, "USER400", "제품이 장바구니에 존재하지 않습니다."), + _PRODUCT_IN_CART_CANNOT_DELETE(HttpStatus.BAD_REQUEST, "USER400", "장바구니에 담겨있는 상품은 삭제할 수 없습니다."), // Cart 에러 _CART_IS_ALREADY_EMPTY(HttpStatus.BAD_REQUEST, "USER400", "장바구니가 이미 비어있습니다."),