From 8646b1ab6ca01c586fd34f598e593576e72610bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=8C=8D=28junpak=29?= <112045553+junpakPark@users.noreply.github.com> Date: Tue, 18 Jul 2023 13:49:45 +0900 Subject: [PATCH 01/88] =?UTF-8?q?[Docs]=20GitHub=20Issue=20=EB=B0=8F=20PR?= =?UTF-8?q?=20Template=20=EC=84=A4=EC=A0=95=20(#37)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: .gitignore 추가 * chore: GitHub PR 및 Issue Template * Revert "chore: GitHub PR 및 Issue Template" This reverts commit 65915f72740bbf22899ef7ac52fefa99cde96a8b. * Revert "chore: .gitignore 추가" This reverts commit 1e1865a1cb7f0a279b4e74c12cd0f66631809ff3. * chore: .gitignore 추가 * chore: GitHub Issue 및 PR Template 추가 --- .github/ISSUE_TEMPLATE/bug.yml | 44 ++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/deploy.yml | 28 ++++++++++++++++++ .github/ISSUE_TEMPLATE/env.yml | 28 ++++++++++++++++++ .github/ISSUE_TEMPLATE/feat.yml | 28 ++++++++++++++++++ .github/ISSUE_TEMPLATE/meeting.yml | 36 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/refactor.yml | 28 ++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 21 +++++++++++++ .gitignore | 41 ++++++++++++++++++++++++++ 8 files changed, 254 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/deploy.yml create mode 100644 .github/ISSUE_TEMPLATE/env.yml create mode 100644 .github/ISSUE_TEMPLATE/feat.yml create mode 100644 .github/ISSUE_TEMPLATE/meeting.yml create mode 100644 .github/ISSUE_TEMPLATE/refactor.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .gitignore diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 000000000..ba8e60888 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,44 @@ +name: "bug" +description: "버그 발생 시" +labels: "bug" +body: + - type: textarea + attributes: + label: 🐞버그 설명 + description: 버그에 대한 설명을 작성해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: 📄 버그 로그 + description: 로그가 있으면 입력해 주세요. + render: shell + validations: + required: false + - type: textarea + attributes: + label: 🌏 버그 발생 환경 + description: 버그가 발생한 환경에 대해 작성해 주세요. + placeholder: | + OS: macOS + validations: + required: true + - type: textarea + attributes: + label: ✅ 버그 재현 방법 + description: Given-When-Then 형식으로 버그를 재현할 수 있는 방법에 대해 작성해 주세요. + validations: + required: false + - type: textarea + attributes: + label: 📎 참고 자료 + description: 발생한 버그에 대한 참고 자료가 있다면 작성해 주세요. + validations: + required: false + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 버그를 해결하기 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/deploy.yml b/.github/ISSUE_TEMPLATE/deploy.yml new file mode 100644 index 000000000..778c62372 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/deploy.yml @@ -0,0 +1,28 @@ +name: "deploy" +description: "배포 시" +labels: "deploy" +body: + - type: textarea + attributes: + label: 📄 작업 설명 + description: 배포에 대한 설명을 작성해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: ✅ 작업 내용 + description: 배포에 대한 Tasks를 작성해 주세요. + placeholder: 최대한 세분화 해서 적어주세요! + validations: + required: true + - type: textarea + attributes: + label: 📎 참고 자료 + description: 배포에 대한 참고 자료가 있다면 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 배포를 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/env.yml b/.github/ISSUE_TEMPLATE/env.yml new file mode 100644 index 000000000..af06b0b4e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/env.yml @@ -0,0 +1,28 @@ +name: "env" +description: "환경 설정 시" +labels: "env" +body: + - type: textarea + attributes: + label: 📄 작업 대상 + description: 작업할 환경 설정에 대해 설명해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: ✅ 작업할 내용 + description: 환경 설정에 대한 Tasks를 작성해주세요. + placeholder: 최대한 세분화 해서 적어주세요! + validations: + required: true + - type: textarea + attributes: + label: 📎 참고 자료 + description: 환경 설정에 대한 참고 자료가 있다면 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 환경설정을 추가하기 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/feat.yml b/.github/ISSUE_TEMPLATE/feat.yml new file mode 100644 index 000000000..5abde3749 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feat.yml @@ -0,0 +1,28 @@ +name: "feat" +description: "기능 추가 시" +labels: "feat" +body: + - type: textarea + attributes: + label: 📄 작업 대상 + description: 작업할 기능에 대한 설명을 작성해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: ✅ 작업 내용 + description: 기능 구현에 대한 Tasks를 작성해 주세요. + placeholder: 최대한 세분화 해서 적어주세요! + validations: + required: true + - type: textarea + attributes: + label: 📎 참고 자료 + description: 새로운 기능에 대한 참고 자료가 있다면 URL을 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 새로운 기능을 추가하기 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/meeting.yml b/.github/ISSUE_TEMPLATE/meeting.yml new file mode 100644 index 000000000..d07e0f303 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/meeting.yml @@ -0,0 +1,36 @@ +name: "meeting" +description: "회의 시" +labels: "meeting" +body: + - type: textarea + attributes: + label: 📝 설명 + description: 회의 주제에 대한 설명을 작성해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: 🙋🏻 참가 인원 + validations: + required: true + description: 회의에 참여할 인원 및 역할(진행자, 서기)을 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 회의 시간 + validations: + required: true + description: 회의 날짜와 시간을 입력해 주세요. + - type: textarea + attributes: + label: ✅ 회의 안건 + description: 해야 하는 일에 대한 Tasks를 작성해 주세요. + placeholder: 최대한 세분화 해서 적어 주세요! + validations: + required: true + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 회의를 진행하는데 필요한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/refactor.yml b/.github/ISSUE_TEMPLATE/refactor.yml new file mode 100644 index 000000000..ae5d0d05a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/refactor.yml @@ -0,0 +1,28 @@ +name: "refactor" +description: "리팩터링 시" +labels: "refactor" +body: + - type: textarea + attributes: + label: 🛠️ 작업 대상 + description: 리팩터링에 해야할 범위를 설명해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: ✅ 작업 내용 + description: 리팩터링을 할 부분에 대한 Tasks를 작성해 주세요. + placeholder: 최대한 세분화 해서 적어주세요! + validations: + required: true + - type: textarea + attributes: + label: 📎 참고 자료 + description: 리팩터링에 대한 참고 자료가 있다면 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 리펙토링을 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..3f5b9136e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,21 @@ + + +## 작업 대상 + + +## 📄 작업 내용 + + +## 🙋🏻 주의 사항 + + +## 스크린샷 + + +## 📎 관련 이슈 + + + + +## 레퍼런스 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..8ccd3c55b --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +node_modules/ + +dist/ From 5b153cc49d884ad80e672ec9f98b4e03b0c8e9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=ED=8C=8D=28junpak=29?= <112045553+junpakPark@users.noreply.github.com> Date: Tue, 18 Jul 2023 13:56:16 +0900 Subject: [PATCH 02/88] =?UTF-8?q?[Docs]=20GitHub=20Issue=20Template=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: .gitignore 추가 * chore: GitHub PR 및 Issue Template * Revert "chore: GitHub PR 및 Issue Template" This reverts commit 65915f72740bbf22899ef7ac52fefa99cde96a8b. * Revert "chore: .gitignore 추가" This reverts commit 1e1865a1cb7f0a279b4e74c12cd0f66631809ff3. * chore: .gitignore 추가 * chore: GitHub Issue 및 PR Template 추가 * chore: GitHub Issue 및 PR Template 추가 --- .github/ISSUE_TEMPLATE/bug.yml | 44 +++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/deploy.yml | 28 ++++++++++++++++++ .github/ISSUE_TEMPLATE/refactor.yml | 28 ++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/deploy.yml create mode 100644 .github/ISSUE_TEMPLATE/refactor.yml diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 000000000..ba8e60888 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,44 @@ +name: "bug" +description: "버그 발생 시" +labels: "bug" +body: + - type: textarea + attributes: + label: 🐞버그 설명 + description: 버그에 대한 설명을 작성해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: 📄 버그 로그 + description: 로그가 있으면 입력해 주세요. + render: shell + validations: + required: false + - type: textarea + attributes: + label: 🌏 버그 발생 환경 + description: 버그가 발생한 환경에 대해 작성해 주세요. + placeholder: | + OS: macOS + validations: + required: true + - type: textarea + attributes: + label: ✅ 버그 재현 방법 + description: Given-When-Then 형식으로 버그를 재현할 수 있는 방법에 대해 작성해 주세요. + validations: + required: false + - type: textarea + attributes: + label: 📎 참고 자료 + description: 발생한 버그에 대한 참고 자료가 있다면 작성해 주세요. + validations: + required: false + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 버그를 해결하기 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/deploy.yml b/.github/ISSUE_TEMPLATE/deploy.yml new file mode 100644 index 000000000..778c62372 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/deploy.yml @@ -0,0 +1,28 @@ +name: "deploy" +description: "배포 시" +labels: "deploy" +body: + - type: textarea + attributes: + label: 📄 작업 설명 + description: 배포에 대한 설명을 작성해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: ✅ 작업 내용 + description: 배포에 대한 Tasks를 작성해 주세요. + placeholder: 최대한 세분화 해서 적어주세요! + validations: + required: true + - type: textarea + attributes: + label: 📎 참고 자료 + description: 배포에 대한 참고 자료가 있다면 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 배포를 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/refactor.yml b/.github/ISSUE_TEMPLATE/refactor.yml new file mode 100644 index 000000000..ae5d0d05a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/refactor.yml @@ -0,0 +1,28 @@ +name: "refactor" +description: "리팩터링 시" +labels: "refactor" +body: + - type: textarea + attributes: + label: 🛠️ 작업 대상 + description: 리팩터링에 해야할 범위를 설명해 주세요. + placeholder: 자세히 적을수록 좋습니다! + validations: + required: true + - type: textarea + attributes: + label: ✅ 작업 내용 + description: 리팩터링을 할 부분에 대한 Tasks를 작성해 주세요. + placeholder: 최대한 세분화 해서 적어주세요! + validations: + required: true + - type: textarea + attributes: + label: 📎 참고 자료 + description: 리팩터링에 대한 참고 자료가 있다면 작성해 주세요. + - type: textarea + attributes: + label: ⏰ 추정 시간 + description: 리펙토링을 위한 추정 시간(비관적 추정, 낙관적 추정)에 대해 작성해주세요. + validations: + required: true From 29997b1bfcf323f835b1349b567883e1bd8fa26d Mon Sep 17 00:00:00 2001 From: junpakPark Date: Thu, 27 Jul 2023 20:17:58 +0900 Subject: [PATCH 03/88] =?UTF-8?q?feat:=20member=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jaeyeon kim --- .../mapbefine/mapbefine/entity/Member.java | 85 +++++++++++++++++++ .../com/mapbefine/mapbefine/entity/Pin.java | 20 +++-- .../com/mapbefine/mapbefine/entity/Role.java | 20 +++++ .../com/mapbefine/mapbefine/entity/Topic.java | 32 +++++-- .../entity/TopicPermissionMember.java | 36 ++++++++ .../mapbefine/entity/TopicStatus.java | 17 ++++ .../repository/MemberRepository.java | 11 +++ .../mapbefine/service/TopicQueryService.java | 10 ++- .../mapbefine/mapbefine/MemberFixture.java | 27 ++++++ 9 files changed, 246 insertions(+), 12 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java new file mode 100644 index 000000000..179264cbf --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java @@ -0,0 +1,85 @@ +package com.mapbefine.mapbefine.entity; + +import static lombok.AccessLevel.PROTECTED; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = PROTECTED) +@Getter +public class Member extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 20) + private String name; + + @Column(nullable = false) + private String email; + + @Column(nullable = false) + private String imageUrl; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private Role role; + + @OneToMany(mappedBy = "member") + private List createdTopic = new ArrayList<>(); + + @OneToMany(mappedBy = "member") + private List topicsWithPermission = new ArrayList<>(); + + public Member( + String name, + String email, + String imageUrl, + Role role + ) { + this.name = name; + this.email = email; + this.imageUrl = imageUrl; + this.role = role; + } + + public void update(String name, String imageUrl) { + this.name = name; + this.imageUrl = imageUrl; + } + + public void addTopic(Topic topic) { + createdTopic.add(topic); + } + + public String getRoleKey() { + return this.role.getKey(); + } + + public List getAllTopicsWithPermission() { + List allTopicsWithPermission = topicsWithPermission.stream() + .map(TopicPermissionMember::getTopic) + .collect(Collectors.toList()); + + allTopicsWithPermission.addAll(createdTopic); + return allTopicsWithPermission; + } + + public boolean isAdmin() { + return role == Role.ADMIN; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java index e34858a5d..31804ddd9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java @@ -1,15 +1,23 @@ package com.mapbefine.mapbefine.entity; -import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; +import static lombok.AccessLevel.PROTECTED; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; - -import static lombok.AccessLevel.PROTECTED; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; @Entity @NoArgsConstructor(access = PROTECTED) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java new file mode 100644 index 000000000..083fc102b --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java @@ -0,0 +1,20 @@ +package com.mapbefine.mapbefine.entity; + +import lombok.Getter; + +@Getter +public enum Role { + + ADMIN("ROLE_ADMIN", "운영자"), + USER("ROLE_USER", "로그인 유저"), + GUEST("ROLE_GUEST", "손님"); + + private final String key; + private final String title; + + Role(String key, String title) { + this.key = key; + this.title = title; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java index 33c0211a3..225980bbe 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java @@ -2,8 +2,16 @@ import static lombok.AccessLevel.PROTECTED; -import jakarta.persistence.*; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.OneToMany; import java.util.ArrayList; import java.util.List; import lombok.Getter; @@ -40,6 +48,10 @@ public class Topic extends BaseEntity { @ColumnDefault(value = "false") private boolean isDeleted = false; + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private TopicStatus topicStatus; + public Topic( String name, String description, @@ -74,9 +86,11 @@ private void validateDescription(String description) { } } - public void update(String name, - String description, - String imageUrl) { + public void update( + String name, + String description, + String imageUrl + ) { validateName(name); validateDescription(description); // TODO : URL 형식 검증 필요? @@ -96,4 +110,12 @@ public void addPin(Pin pin) { pins.add(pin); } + public boolean isPublic() { + return topicStatus == TopicStatus.PUBLIC; + } + + public boolean isPrivate() { + return topicStatus == TopicStatus.PRIVATE; + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java new file mode 100644 index 000000000..48a61979e --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java @@ -0,0 +1,36 @@ +package com.mapbefine.mapbefine.entity; + +import static lombok.AccessLevel.PROTECTED; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = PROTECTED) +@Getter +public class TopicPermissionMember extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "topic_id", nullable = false) + private Topic topic; + + @ManyToOne + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + public TopicPermissionMember(Topic topic, Member member) { + this.topic = topic; + this.member = member; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java new file mode 100644 index 000000000..f6fd0349b --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java @@ -0,0 +1,17 @@ +package com.mapbefine.mapbefine.entity; + +import lombok.Getter; + +@Getter +public enum TopicStatus { + + PUBLIC("같이 볼 지도"), + PRIVATE("혼자 볼 지도"); + + private final String title; + + TopicStatus(String title) { + this.title = title; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java new file mode 100644 index 000000000..b72902e03 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java @@ -0,0 +1,11 @@ +package com.mapbefine.mapbefine.repository; + +import com.mapbefine.mapbefine.entity.Member; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { + + Optional findByEmail(String email); + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index d1723e023..374134af5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -7,6 +7,7 @@ import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; import com.mapbefine.mapbefine.entity.Location; +import com.mapbefine.mapbefine.entity.Member; import com.mapbefine.mapbefine.entity.Pin; import com.mapbefine.mapbefine.entity.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; @@ -32,12 +33,19 @@ public TopicQueryService(final TopicRepository topicRepository, LocationReposito this.locationRepository = locationRepository; } - public List findAll() { + public List findAll(Member member) { + List allTopicsWithPermission = member.getAllTopicsWithPermission(); + return topicRepository.findAll().stream() + .filter(topic -> hasPermission(allTopicsWithPermission, topic, member)) .map(TopicResponse::from) .collect(Collectors.toList()); } + private boolean hasPermission(List allTopicsWithPermission, Topic topic, Member member) { + return member.isAdmin() || topic.isPublic() || allTopicsWithPermission.contains(topic); + } + public TopicDetailResponse findById(Long id) { Topic topic = topicRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java new file mode 100644 index 000000000..293811a62 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java @@ -0,0 +1,27 @@ +package com.mapbefine.mapbefine; + +import com.mapbefine.mapbefine.entity.Member; +import com.mapbefine.mapbefine.entity.Role; + +public class MemberFixture { + + public static final Member ADMIN_MEMBER = new Member( + "운영자", + "admin@naver.com", + "image.url", + Role.ADMIN + ); + public static final Member USER_MEMBER = new Member( + "사용자", + "user@naver.com", + "image.url", + Role.USER + ); + public static final Member GUEST_MEMBER = new Member( + "게스트", + "guest@naver.com", + "image.url", + Role.GUEST + ); + +} From 70f351f2493bfdac59595ac268c1ce05fa33ada8 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Fri, 28 Jul 2023 13:38:25 +0900 Subject: [PATCH 04/88] =?UTF-8?q?feat:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC,=20AuthMember=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jaeyeon kim --- .../mapbefine/config/auth/Admin.java | 45 ++++++++++++ .../mapbefine/config/auth/AuthMember.java | 70 +++++++++++++++++++ .../mapbefine/config/auth/Guest.java | 41 +++++++++++ .../mapbefine/mapbefine/config/auth/User.java | 57 +++++++++++++++ .../controller/MemberController.java | 19 +++++ .../mapbefine/dto/PinDetailResponse.java | 5 +- .../mapbefine/mapbefine/dto/PinResponse.java | 2 +- .../mapbefine/dto/TopicDetailResponse.java | 2 +- .../mapbefine/dto/TopicResponse.java | 2 +- .../mapbefine/entity/{ => member}/Member.java | 12 +++- .../MemberTopicPermission.java} | 8 ++- .../mapbefine/entity/{ => member}/Role.java | 2 +- .../entity/{ => pin}/Coordinate.java | 11 ++- .../mapbefine/entity/{ => pin}/Location.java | 18 +++-- .../mapbefine/entity/{ => pin}/Pin.java | 4 +- .../mapbefine/entity/{ => pin}/PinImage.java | 12 +++- .../mapbefine/entity/topic/Permission.java | 16 +++++ .../Publicity.java} | 6 +- .../mapbefine/entity/{ => topic}/Topic.java | 18 +++-- .../repository/LocationRepository.java | 2 +- .../repository/MemberRepository.java | 6 +- .../mapbefine/repository/PinRepository.java | 2 +- .../mapbefine/repository/TopicRepository.java | 2 +- .../mapbefine/service/PinCommandService.java | 16 ++--- .../mapbefine/service/PinQueryService.java | 2 +- .../service/TopicCommandService.java | 9 ++- .../mapbefine/service/TopicQueryService.java | 8 +-- .../mapbefine/mapbefine/LocationFixture.java | 7 +- .../mapbefine/mapbefine/MemberFixture.java | 4 +- .../com/mapbefine/mapbefine/PinFixture.java | 6 +- .../com/mapbefine/mapbefine/TopicFixture.java | 2 +- .../mapbefine/entity/CoordinateTest.java | 14 ++-- .../mapbefine/mapbefine/entity/PinTest.java | 17 +++-- .../integration/PinIntegrationTest.java | 16 ++--- .../integration/TopicIntegrationTest.java | 35 +++++----- .../repository/LocationRepositoryTest.java | 15 ++-- .../repository/PinRepositoryTest.java | 8 +-- .../service/PinCommandServiceTest.java | 26 +++---- .../service/PinQueryServiceTest.java | 24 ++++--- .../service/TopicCommandServiceTest.java | 6 +- .../service/TopicQueryServiceTest.java | 4 +- 41 files changed, 429 insertions(+), 152 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => member}/Member.java (85%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{TopicPermissionMember.java => member/MemberTopicPermission.java} (73%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => member}/Role.java (87%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => pin}/Coordinate.java (98%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => pin}/Location.java (81%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => pin}/Pin.java (96%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => pin}/PinImage.java (70%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java rename backend/src/main/java/com/mapbefine/mapbefine/entity/{TopicStatus.java => topic/Publicity.java} (63%) rename backend/src/main/java/com/mapbefine/mapbefine/entity/{ => topic}/Topic.java (89%) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java new file mode 100644 index 000000000..b7c4d8494 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java @@ -0,0 +1,45 @@ +package com.mapbefine.mapbefine.config.auth; + +import com.mapbefine.mapbefine.entity.topic.Publicity; +import java.util.List; + +public class Admin extends AuthMember { + + protected Admin( + Long memberId, + List createdTopic, + List topicsWithPermission + ) { + super( + memberId, + createdTopic, + topicsWithPermission + ); + } + + @Override + public boolean canRead(Long topicId, Publicity publicity) { + return true; + } + + @Override + public boolean canDelete(Long topicId, Publicity publicity) { + return true; + } + + @Override + public boolean canTopicCreate(Long topicId, Publicity publicity) { + return true; + } + + @Override + public boolean canTopicUpdate(Long topicId, Publicity publicity) { + return true; + } + + @Override + public boolean canPinCreateOrUpdate(Long topicId, Publicity publicity) { + return true; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java new file mode 100644 index 000000000..f7f06e60e --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -0,0 +1,70 @@ +package com.mapbefine.mapbefine.config.auth; + +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.member.MemberTopicPermission; +import com.mapbefine.mapbefine.entity.topic.Publicity; +import com.mapbefine.mapbefine.entity.topic.Topic; +import java.util.List; + +public abstract class AuthMember { + + protected Long memberId; + protected List createdTopic; + protected List topicsWithPermission; + + protected AuthMember( + Long memberId, + List createdTopic, + List topicsWithPermission + ) { + this.memberId = memberId; + this.createdTopic = createdTopic; + this.topicsWithPermission = topicsWithPermission; + } + + public static AuthMember from(Member member) { + if (member == null) { + return new Guest(); + } + + if (member.isUser()) { + return new User(member.getId(), getCreatedTopics(member), getTopicsWithPermission(member)); + } + + return new Admin(member.getId(), getCreatedTopics(member), getTopicsWithPermission(member)); + } + + private static List getTopicsWithPermission(Member member) { + return member.getTopicsWithPermission() + .stream() + .map(MemberTopicPermission::getTopic) + .map(Topic::getId) + .toList(); + } + + private static List getCreatedTopics(Member member) { + return member.getCreatedTopic() + .stream() + .map(Topic::getId) + .toList(); + } + + public abstract boolean canRead(Long topicId, Publicity publicity); + + public abstract boolean canDelete(Long topicId, Publicity publicity); + + public abstract boolean canTopicCreate(Long topicId, Publicity publicity); + + public abstract boolean canTopicUpdate(Long topicId, Publicity publicity); + + public abstract boolean canPinCreateOrUpdate(Long topicId, Publicity publicity); + + protected boolean isPublic(Publicity publicity) { + return publicity == Publicity.PUBLIC; + } + + protected boolean isPrivate(Publicity publicity) { + return publicity == Publicity.PRIVATE; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java new file mode 100644 index 000000000..164deda3c --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java @@ -0,0 +1,41 @@ +package com.mapbefine.mapbefine.config.auth; + +import com.mapbefine.mapbefine.entity.topic.Publicity; + +public class Guest extends AuthMember { + + + protected Guest() { + super( + null, + null, + null + ); + } + + @Override + public boolean canRead(Long topicId, Publicity publicity) { + return isPublic(publicity); + } + + @Override + public boolean canDelete(Long topicId, Publicity publicity) { + return false; + } + + @Override + public boolean canTopicCreate(Long topicId, Publicity publicity) { + return false; + } + + @Override + public boolean canTopicUpdate(Long topicId, Publicity publicity) { + return false; + } + + @Override + public boolean canPinCreateOrUpdate(Long topicId, Publicity publicity) { + return false; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java new file mode 100644 index 000000000..fe8906163 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -0,0 +1,57 @@ +package com.mapbefine.mapbefine.config.auth; + +import com.mapbefine.mapbefine.entity.topic.Publicity; +import java.util.List; + +public class User extends AuthMember { + + protected User( + Long memberId, + List createdTopic, + List topicsWithPermission + ) { + super( + memberId, + createdTopic, + topicsWithPermission + ); + } + + @Override + public boolean canRead(Long topicId, Publicity publicity) { + return isPublic(publicity) || isGroup(topicId); + } + + @Override + public boolean canDelete(Long topicId, Publicity publicity) { + return isPrivate(publicity) && isCreator(topicId); + } + + @Override + public boolean canTopicCreate(Long topicId, Publicity publicity) { + return true; + } + + @Override + public boolean canTopicUpdate(Long topicId, Publicity publicity) { + return isCreator(topicId); + } + + @Override + public boolean canPinCreateOrUpdate(Long topicId, Publicity publicity) { + return isPublic(publicity) || isGroup(topicId); + } + + private boolean isGroup(Long topicId) { + return isCreator(topicId) || hasPermission(topicId); + } + + private boolean hasPermission(Long topicId) { + return topicsWithPermission.contains(topicId); + } + + private boolean isCreator(Long topicId) { + return createdTopic.contains(topicId); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java new file mode 100644 index 000000000..c2256df2d --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java @@ -0,0 +1,19 @@ +package com.mapbefine.mapbefine.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/members") +public class MemberController { // Mypage 내용, Member 들 리스트 + +// @GetMapping("/topics") +// public List topicResponseList(AuthMember member) { // 현재 Login 한 User 의 정보가 넘어와야함 +// // Member member -> MyTopic -> .get -> +//// memberService.findMyTopic(member); // member.getCreateTopics().stream(TopicResponse::From) +// +// // memberService TopicId -> 다 각각 조회해서 TopicResponse 로 감싸서 보내준다. +// } + + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java index d7ed8b8f3..1027b08f4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java @@ -1,8 +1,7 @@ package com.mapbefine.mapbefine.dto; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.PinImage; - +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.pin.PinImage; import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java index 47a5b00e0..aa22d8445 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine.dto; -import com.mapbefine.mapbefine.entity.Pin; +import com.mapbefine.mapbefine.entity.pin.Pin; public record PinResponse( Long id, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java index 371da776d..5e584a7d5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine.dto; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.topic.Topic; import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java index 5f318a0ac..3f7ae2b22 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine.dto; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.topic.Topic; import java.time.LocalDateTime; public record TopicResponse( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java similarity index 85% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java index 179264cbf..6b45f9995 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java @@ -1,7 +1,9 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.member; import static lombok.AccessLevel.PROTECTED; +import com.mapbefine.mapbefine.entity.BaseEntity; +import com.mapbefine.mapbefine.entity.topic.Topic; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -42,7 +44,7 @@ public class Member extends BaseEntity { private List createdTopic = new ArrayList<>(); @OneToMany(mappedBy = "member") - private List topicsWithPermission = new ArrayList<>(); + private List topicsWithPermission = new ArrayList<>(); public Member( String name, @@ -71,7 +73,7 @@ public String getRoleKey() { public List getAllTopicsWithPermission() { List allTopicsWithPermission = topicsWithPermission.stream() - .map(TopicPermissionMember::getTopic) + .map(MemberTopicPermission::getTopic) .collect(Collectors.toList()); allTopicsWithPermission.addAll(createdTopic); @@ -82,4 +84,8 @@ public boolean isAdmin() { return role == Role.ADMIN; } + public boolean isUser() { + return role == Role.USER; + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/MemberTopicPermission.java similarity index 73% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/member/MemberTopicPermission.java index 48a61979e..2b8bbc12f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicPermissionMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/MemberTopicPermission.java @@ -1,7 +1,9 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.member; import static lombok.AccessLevel.PROTECTED; +import com.mapbefine.mapbefine.entity.BaseEntity; +import com.mapbefine.mapbefine.entity.topic.Topic; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -14,7 +16,7 @@ @Entity @NoArgsConstructor(access = PROTECTED) @Getter -public class TopicPermissionMember extends BaseEntity { +public class MemberTopicPermission extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -28,7 +30,7 @@ public class TopicPermissionMember extends BaseEntity { @JoinColumn(name = "member_id", nullable = false) private Member member; - public TopicPermissionMember(Topic topic, Member member) { + public MemberTopicPermission(Topic topic, Member member) { this.topic = topic; this.member = member; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Role.java similarity index 87% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/member/Role.java index 083fc102b..0f75f4196 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Role.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Role.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.member; import lombok.Getter; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Coordinate.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Coordinate.java similarity index 98% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/Coordinate.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Coordinate.java index 81e93578f..8d2721823 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Coordinate.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Coordinate.java @@ -1,15 +1,14 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.pin; + +import static lombok.AccessLevel.PROTECTED; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; -import lombok.Getter; -import lombok.NoArgsConstructor; - import java.math.BigDecimal; import java.math.MathContext; import java.util.function.DoubleUnaryOperator; - -import static lombok.AccessLevel.PROTECTED; +import lombok.Getter; +import lombok.NoArgsConstructor; @Embeddable @NoArgsConstructor(access = PROTECTED) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Location.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java similarity index 81% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/Location.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java index c37ec2e63..624127598 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Location.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java @@ -1,14 +1,20 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.pin; -import jakarta.persistence.*; -import lombok.Getter; -import lombok.NoArgsConstructor; +import static lombok.AccessLevel.PROTECTED; +import com.mapbefine.mapbefine.entity.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; - -import static lombok.AccessLevel.PROTECTED; +import lombok.Getter; +import lombok.NoArgsConstructor; @Entity @NoArgsConstructor(access = PROTECTED) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java similarity index 96% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java index 31804ddd9..926a8a0df 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java @@ -1,7 +1,9 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.pin; import static lombok.AccessLevel.PROTECTED; +import com.mapbefine.mapbefine.entity.BaseEntity; +import com.mapbefine.mapbefine.entity.topic.Topic; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/PinImage.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/PinImage.java similarity index 70% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/PinImage.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/pin/PinImage.java index f1ea00b9e..b2c753d92 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/PinImage.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/PinImage.java @@ -1,6 +1,12 @@ -package com.mapbefine.mapbefine.entity; - -import jakarta.persistence.*; +package com.mapbefine.mapbefine.entity.pin; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java new file mode 100644 index 000000000..3ab36b2b3 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java @@ -0,0 +1,16 @@ +package com.mapbefine.mapbefine.entity.topic; + +import lombok.Getter; + +@Getter +public enum Permission { + + ALL_MEMBERS("모든 회원"), + GROUP_ONLY("소속 회원"); + + private final String title; + + Permission(String title) { + this.title = title; + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java similarity index 63% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java index f6fd0349b..7704817b2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/TopicStatus.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java @@ -1,16 +1,16 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.topic; import lombok.Getter; @Getter -public enum TopicStatus { +public enum Publicity { PUBLIC("같이 볼 지도"), PRIVATE("혼자 볼 지도"); private final String title; - TopicStatus(String title) { + Publicity(String title) { this.title = title; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java similarity index 89% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java rename to backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java index 225980bbe..4779f761d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java @@ -1,7 +1,9 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.entity.topic; import static lombok.AccessLevel.PROTECTED; +import com.mapbefine.mapbefine.entity.BaseEntity; +import com.mapbefine.mapbefine.entity.pin.Pin; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -44,13 +46,17 @@ public class Topic extends BaseEntity { @OneToMany(mappedBy = "topic", cascade = CascadeType.PERSIST) private List pins = new ArrayList<>(); + @Enumerated(EnumType.STRING) @Column(nullable = false) - @ColumnDefault(value = "false") - private boolean isDeleted = false; + private Publicity publicity; @Enumerated(EnumType.STRING) @Column(nullable = false) - private TopicStatus topicStatus; + private Permission permission; + + @Column(nullable = false) + @ColumnDefault(value = "false") + private boolean isDeleted = false; public Topic( String name, @@ -111,11 +117,11 @@ public void addPin(Pin pin) { } public boolean isPublic() { - return topicStatus == TopicStatus.PUBLIC; + return publicity == Publicity.PUBLIC; } public boolean isPrivate() { - return topicStatus == TopicStatus.PRIVATE; + return publicity == Publicity.PRIVATE; } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java index 9abd096df..c439983eb 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine.repository; -import com.mapbefine.mapbefine.entity.Location; +import com.mapbefine.mapbefine.entity.pin.Location; import java.math.BigDecimal; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java index b72902e03..8dcccf17a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java @@ -1,11 +1,7 @@ package com.mapbefine.mapbefine.repository; -import com.mapbefine.mapbefine.entity.Member; -import java.util.Optional; +import com.mapbefine.mapbefine.entity.member.Member; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberRepository extends JpaRepository { - - Optional findByEmail(String email); - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java index 8a64f8315..0665f0162 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine.repository; -import com.mapbefine.mapbefine.entity.Pin; +import com.mapbefine.mapbefine.entity.pin.Pin; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java index da74629f0..cdd567426 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine.repository; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.topic.Topic; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java index 37a851c50..68cdd21f3 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java @@ -2,19 +2,18 @@ import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinUpdateRequest; -import com.mapbefine.mapbefine.entity.Coordinate; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.PinImage; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.pin.PinImage; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; +import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.NoSuchElementException; - @Transactional @Service public class PinCommandService { @@ -49,7 +48,8 @@ public Long save(PinCreateRequest request) { .findFirst() .orElseGet(() -> saveLocation(request, coordinate)); - Pin pin = Pin.createPinAssociatedWithLocationAndTopic(request.name(), request.description(), pinLocation, topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopic(request.name(), request.description(), pinLocation, + topic); for (String pinImage : request.images()) { PinImage.createPinImageAssociatedWithPin(pinImage, pin); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java index 7322c8baa..2b3f020df 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java @@ -2,7 +2,7 @@ import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.entity.Pin; +import com.mapbefine.mapbefine.entity.pin.Pin; import com.mapbefine.mapbefine.repository.PinRepository; import java.util.List; import java.util.NoSuchElementException; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java index 2191400bb..7aa328a51 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java @@ -3,16 +3,15 @@ import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - import java.util.Collection; import java.util.List; import java.util.stream.Collectors; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Transactional @Service diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index 374134af5..7570ca222 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -6,10 +6,10 @@ import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Member; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import java.math.BigDecimal; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java index fcd0b95eb..7950fe8b8 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java @@ -1,7 +1,7 @@ package com.mapbefine.mapbefine; -import com.mapbefine.mapbefine.entity.Coordinate; -import com.mapbefine.mapbefine.entity.Location; +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; import java.math.BigDecimal; public class LocationFixture { @@ -11,6 +11,7 @@ public static Location create() { } public static Location createByCoordinate(double latitude, double longitude) { - return new Location("지번주소", "도로명주소", new Coordinate(BigDecimal.valueOf(latitude), BigDecimal.valueOf(longitude)), "111000"); + return new Location("지번주소", "도로명주소", + new Coordinate(BigDecimal.valueOf(latitude), BigDecimal.valueOf(longitude)), "111000"); } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java index 293811a62..168b7c2da 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java @@ -1,7 +1,7 @@ package com.mapbefine.mapbefine; -import com.mapbefine.mapbefine.entity.Member; -import com.mapbefine.mapbefine.entity.Role; +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.member.Role; public class MemberFixture { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java index c8b8238f3..511522e1c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java @@ -1,8 +1,8 @@ package com.mapbefine.mapbefine; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; public class PinFixture { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java index 0c1c0b62a..6e66aafae 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java @@ -1,6 +1,6 @@ package com.mapbefine.mapbefine; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.topic.Topic; public class TopicFixture { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java b/backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java index a527651f7..c5d8b87a9 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java @@ -1,18 +1,18 @@ package com.mapbefine.mapbefine.entity; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import java.math.BigDecimal; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import java.math.BigDecimal; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; - class CoordinateTest { @ParameterizedTest diff --git a/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java index 858385751..f58f24de2 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java @@ -1,17 +1,20 @@ package com.mapbefine.mapbefine.entity; +import static com.mapbefine.mapbefine.entity.pin.Pin.createPinAssociatedWithLocationAndTopic; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; +import java.math.BigDecimal; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.math.BigDecimal; -import java.util.stream.Stream; - -import static com.mapbefine.mapbefine.entity.Pin.createPinAssociatedWithLocationAndTopic; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - class PinTest { private static final Location location = new Location( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java index d06c98645..9286e7405 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java @@ -1,15 +1,17 @@ package com.mapbefine.mapbefine.integration; +import static org.assertj.core.api.Assertions.assertThat; + import com.mapbefine.mapbefine.LocationFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.dto.PinCreateRequest; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; +import io.restassured.*; +import io.restassured.response.*; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -17,10 +19,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - public class PinIntegrationTest extends IntegrationTest { private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); private Topic topic; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java index 62da6eafd..5277967cd 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java @@ -1,27 +1,25 @@ package com.mapbefine.mapbefine.integration; +import static org.assertj.core.api.Assertions.assertThat; + import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; +import io.restassured.*; +import io.restassured.response.*; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; - public class TopicIntegrationTest extends IntegrationTest { @Autowired @@ -33,7 +31,8 @@ public class TopicIntegrationTest extends IntegrationTest { @Test @DisplayName("Pin 목록 없이 Topic을 생성하면 201을 반환한다") void createNewTopicWithoutPins_Success() { - TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 2번 이상 간집 ", Collections.emptyList()); + TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest("준팍의 또간집", + "https://map-befine-official.github.io/favicon.png", "준팍이 2번 이상 간집 ", Collections.emptyList()); // when ExtractableResponse response = createNewTopic(준팍의_또간집); @@ -85,7 +84,8 @@ void createMergeTopic_Success() { .map(Topic::getId) .collect(Collectors.toList()); - TopicMergeRequest 송파_데이트코스 = new TopicMergeRequest("송파 데이트코스", "https://map-befine-official.github.io/favicon.png", "맛집과 카페 토픽 합치기", topicIds); + TopicMergeRequest 송파_데이트코스 = new TopicMergeRequest("송파 데이트코스", + "https://map-befine-official.github.io/favicon.png", "맛집과 카페 토픽 합치기", topicIds); // when ExtractableResponse response = RestAssured @@ -105,11 +105,13 @@ void createMergeTopic_Success() { @DisplayName("Topic을 수정하면 200을 반환한다") void updateTopic_Success() { ExtractableResponse newTopic = createNewTopic( - new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 간집", Collections.emptyList())); + new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 간집", + Collections.emptyList())); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); // when - TopicUpdateRequest 송파_데이트코스 = new TopicUpdateRequest("송파 데이트코스", "https://map-befine-official.github.io/favicon.png", "수정한 토픽"); + TopicUpdateRequest 송파_데이트코스 = new TopicUpdateRequest("송파 데이트코스", + "https://map-befine-official.github.io/favicon.png", "수정한 토픽"); ExtractableResponse response = RestAssured .given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) @@ -126,7 +128,8 @@ void updateTopic_Success() { @DisplayName("Topic을 삭제하면 204를 반환한다") void deleteTopic_Success() { ExtractableResponse newTopic = createNewTopic( - new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 간집 ", Collections.emptyList())); + new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 간집 ", + Collections.emptyList())); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); // when diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java index de4cb4894..8dcd75ecf 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java @@ -1,7 +1,12 @@ package com.mapbefine.mapbefine.repository; -import com.mapbefine.mapbefine.entity.Coordinate; -import com.mapbefine.mapbefine.entity.Location; +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; +import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -9,12 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import java.math.BigDecimal; -import java.util.List; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; - @DataJpaTest class LocationRepositoryTest { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java index dc015edbf..cc1899028 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java @@ -2,10 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.entity.Coordinate; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java index 2059a544a..41f735cd9 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java @@ -1,28 +1,27 @@ package com.mapbefine.mapbefine.service; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinUpdateRequest; -import com.mapbefine.mapbefine.entity.Coordinate; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import jakarta.transaction.Transactional; +import java.math.BigDecimal; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import java.math.BigDecimal; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - @Transactional @SpringBootTest class PinCommandServiceTest { @@ -47,7 +46,8 @@ class PinCommandServiceTest { @BeforeEach void setUp() { - topic = topicRepository.save(new Topic("topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png")); + topic = topicRepository.save( + new Topic("topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png")); } @Test @@ -216,7 +216,7 @@ void update_Fail() { Long savedPinId = pinCommandService.save(createRequest); // when then - PinUpdateRequest updateRequest = new PinUpdateRequest("", "updatedDescription",BASE_IMAGES); + PinUpdateRequest updateRequest = new PinUpdateRequest("", "updatedDescription", BASE_IMAGES); assertThatThrownBy(() -> pinCommandService.update(savedPinId, updateRequest)) .isInstanceOf(IllegalArgumentException.class); } @@ -290,4 +290,4 @@ void removeAllByTopicId_Success() { assertThat(findTopicAfterDeleting.getPins()).extractingResultOf("isDeleted") .doesNotContain(false); } -} \ No newline at end of file +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java index 3ab4b7747..0f7d4197b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java @@ -1,26 +1,29 @@ package com.mapbefine.mapbefine.service; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.entity.*; +import com.mapbefine.mapbefine.entity.pin.Coordinate; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.pin.PinImage; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import jakarta.transaction.Transactional; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - @Transactional @SpringBootTest class PinQueryServiceTest { @@ -50,7 +53,8 @@ void setUp() { BigDecimal longitude = BigDecimal.valueOf(127.123456); coordinate = new Coordinate(latitude, longitude); location = saveLocation(coordinate); - topic = topicRepository.save(new Topic("topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png")); + topic = topicRepository.save( + new Topic("topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png")); } @Test diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java index 56b15cc45..d6c4fd433 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java @@ -6,9 +6,9 @@ import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Pin; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java index 8f0444878..86c9fdc01 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java @@ -8,8 +8,8 @@ import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.entity.Location; -import com.mapbefine.mapbefine.entity.Topic; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import java.util.List; From b98ce0216d2ca2ed62288704f2b6b5a3e7ea3402 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Fri, 28 Jul 2023 14:30:25 +0900 Subject: [PATCH 05/88] =?UTF-8?q?feat:=20MemberArgumentResolver=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/MemberArgumentResolver.java | 44 +++++++++++++++++++ .../mapbefine/config/WebMvcConfig.java | 15 +++++++ .../mapbefine/controller/TopicController.java | 9 ++-- .../mapbefine/mapbefine/entity/Member.java | 18 +++++++- .../com/mapbefine/mapbefine/entity/Topic.java | 6 +++ .../src/main/resources/application.properties | 2 +- 6 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java new file mode 100644 index 000000000..5af828d16 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java @@ -0,0 +1,44 @@ +package com.mapbefine.mapbefine.config; + +import com.mapbefine.mapbefine.entity.Member; +import com.mapbefine.mapbefine.entity.Role; +import com.mapbefine.mapbefine.repository.MemberRepository; +import jakarta.servlet.http.HttpServletRequest; +import java.util.NoSuchElementException; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +public class MemberArgumentResolver implements HandlerMethodArgumentResolver { + + private static final String AUTHORIZATION = "Authorization"; + private static final Member GUEST = new Member("게스트", "guest@naver.com", "image.url", Role.GUEST); // Guest 객체는 따로 만드는 것이 좋을까? + + private final MemberRepository memberRepository; + + public MemberArgumentResolver(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType() + .equals(Member.class); + } + + @Override + public Object resolveArgument( + MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory + ) throws Exception { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + String memberEmail = request.getHeader(AUTHORIZATION); + Member member = memberRepository.findByEmail(memberEmail).orElse(null); + + return AuthMember.from(member); // 이런 식으로 하면 바로 Guest, User, Admin 이 가능하지 않을까 + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java index 7f510898b..27162c5ed 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java @@ -1,12 +1,21 @@ package com.mapbefine.mapbefine.config; +import com.mapbefine.mapbefine.repository.MemberRepository; +import java.util.List; import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { + private final MemberRepository memberRepository; + + public WebMvcConfig(final MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") @@ -14,4 +23,10 @@ public void addCorsMappings(CorsRegistry registry) { .allowedMethods("*") .exposedHeaders("Location"); } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new MemberArgumentResolver(memberRepository)); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java index c28d5bce0..ae08e4296 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java @@ -6,6 +6,7 @@ import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicResponse; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; +import com.mapbefine.mapbefine.entity.Member; import com.mapbefine.mapbefine.service.TopicCommandService; import com.mapbefine.mapbefine.service.TopicQueryService; import java.net.URI; @@ -33,7 +34,8 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic } @PostMapping("/new") - public ResponseEntity create(@RequestBody TopicCreateRequest request) { + public ResponseEntity create(Member member, @RequestBody TopicCreateRequest request) { + System.out.println(member); long topicId = topicCommandService.createNew(request); return ResponseEntity.created(URI.create("/topics/" + topicId)) @@ -63,8 +65,9 @@ public ResponseEntity delete(@PathVariable Long topicId) { } @GetMapping - public ResponseEntity> findAll() { - List topics = topicQueryService.findAll(); + public ResponseEntity> findAll(Member member) { + System.out.println(member); + List topics = topicQueryService.findAll(member); return ResponseEntity.ok(topics); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java index 179264cbf..84fa64b85 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/Member.java @@ -10,6 +10,7 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -19,6 +20,7 @@ @Entity @NoArgsConstructor(access = PROTECTED) @Getter +@Table(name = "member") public class Member extends BaseEntity { @Id @@ -38,7 +40,7 @@ public class Member extends BaseEntity { @Column(nullable = false) private Role role; - @OneToMany(mappedBy = "member") + @OneToMany(mappedBy = "creator") private List createdTopic = new ArrayList<>(); @OneToMany(mappedBy = "member") @@ -66,7 +68,7 @@ public void addTopic(Topic topic) { } public String getRoleKey() { - return this.role.getKey(); + return role.getKey(); } public List getAllTopicsWithPermission() { @@ -82,4 +84,16 @@ public boolean isAdmin() { return role == Role.ADMIN; } + @Override + public String toString() { + return "Member{" + + "id=" + id + + ", name='" + name + '\'' + + ", email='" + email + '\'' + + ", imageUrl='" + imageUrl + '\'' + + ", role=" + role + + ", createdTopic=" + createdTopic + + ", topicsWithPermission=" + topicsWithPermission + + '}'; + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java index 225980bbe..aa4695f40 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/Topic.java @@ -10,7 +10,9 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import java.util.ArrayList; import java.util.List; @@ -52,6 +54,10 @@ public class Topic extends BaseEntity { @Column(nullable = false) private TopicStatus topicStatus; + @ManyToOne + @JoinColumn(name = "member_id") + private Member creator; + public Topic( String name, String description, diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 91734ebef..7b318f992 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -6,4 +6,4 @@ spring.jpa.show-sql=true logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.jpa.hibernate.ddl-auto=create spring.h2.console.enabled=true -spring.h2.console.path=/h2-console +spring.h2.console.path=/h2-console \ No newline at end of file From 69268ee6d7dd3f02556c171e51c8a0d9d75d3de7 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Fri, 28 Jul 2023 14:46:54 +0900 Subject: [PATCH 06/88] =?UTF-8?q?feat:=20AuthTopic=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/config/auth/Admin.java | 11 ++++---- .../mapbefine/config/auth/AuthMember.java | 11 ++++---- .../mapbefine/config/auth/Guest.java | 11 ++++---- .../mapbefine/mapbefine/config/auth/User.java | 25 +++++++++++-------- .../mapbefine/mapbefine/dto/AuthTopic.java | 20 +++++++++++++++ .../mapbefine/entity/topic/Topic.java | 8 ------ .../mapbefine/service/TopicQueryService.java | 16 ++++++------ 7 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java index b7c4d8494..84f868d83 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.config.auth; +import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.entity.topic.Publicity; import java.util.List; @@ -18,27 +19,27 @@ protected Admin( } @Override - public boolean canRead(Long topicId, Publicity publicity) { + public boolean canRead(AuthTopic authTopic) { return true; } @Override - public boolean canDelete(Long topicId, Publicity publicity) { + public boolean canDelete(AuthTopic authTopic) { return true; } @Override - public boolean canTopicCreate(Long topicId, Publicity publicity) { + public boolean canTopicCreate(AuthTopic authTopic) { return true; } @Override - public boolean canTopicUpdate(Long topicId, Publicity publicity) { + public boolean canTopicUpdate(AuthTopic authTopic) { return true; } @Override - public boolean canPinCreateOrUpdate(Long topicId, Publicity publicity) { + public boolean canPinCreateOrUpdate(AuthTopic authTopic) { return true; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index f7f06e60e..bd49059bb 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.config.auth; +import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.MemberTopicPermission; import com.mapbefine.mapbefine.entity.topic.Publicity; @@ -49,15 +50,15 @@ private static List getCreatedTopics(Member member) { .toList(); } - public abstract boolean canRead(Long topicId, Publicity publicity); + public abstract boolean canRead(AuthTopic authTopic); - public abstract boolean canDelete(Long topicId, Publicity publicity); + public abstract boolean canDelete(AuthTopic authTopic); - public abstract boolean canTopicCreate(Long topicId, Publicity publicity); + public abstract boolean canTopicCreate(AuthTopic authTopic); - public abstract boolean canTopicUpdate(Long topicId, Publicity publicity); + public abstract boolean canTopicUpdate(AuthTopic authTopic); - public abstract boolean canPinCreateOrUpdate(Long topicId, Publicity publicity); + public abstract boolean canPinCreateOrUpdate(AuthTopic authTopic); protected boolean isPublic(Publicity publicity) { return publicity == Publicity.PUBLIC; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java index 164deda3c..5bdfb364b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.config.auth; +import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.entity.topic.Publicity; public class Guest extends AuthMember { @@ -14,27 +15,27 @@ protected Guest() { } @Override - public boolean canRead(Long topicId, Publicity publicity) { + public boolean canRead(AuthTopic authTopic) { return isPublic(publicity); } @Override - public boolean canDelete(Long topicId, Publicity publicity) { + public boolean canDelete(AuthTopic authTopic) { return false; } @Override - public boolean canTopicCreate(Long topicId, Publicity publicity) { + public boolean canTopicCreate(AuthTopic authTopic) { return false; } @Override - public boolean canTopicUpdate(Long topicId, Publicity publicity) { + public boolean canTopicUpdate(AuthTopic authTopic) { return false; } @Override - public boolean canPinCreateOrUpdate(Long topicId, Publicity publicity) { + public boolean canPinCreateOrUpdate(AuthTopic authTopic) { return false; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index fe8906163..c98071934 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -1,6 +1,7 @@ package com.mapbefine.mapbefine.config.auth; -import com.mapbefine.mapbefine.entity.topic.Publicity; +import com.mapbefine.mapbefine.dto.AuthTopic; +import com.mapbefine.mapbefine.entity.topic.Permission; import java.util.List; public class User extends AuthMember { @@ -18,28 +19,32 @@ protected User( } @Override - public boolean canRead(Long topicId, Publicity publicity) { - return isPublic(publicity) || isGroup(topicId); + public boolean canRead(AuthTopic authTopic) { + return isPublic(authTopic.publicity()) || isGroup(authTopic.topicId()); } @Override - public boolean canDelete(Long topicId, Publicity publicity) { - return isPrivate(publicity) && isCreator(topicId); + public boolean canDelete(AuthTopic authTopic) { + return isPrivate(authTopic.publicity()) && isCreator(authTopic.topicId()); } @Override - public boolean canTopicCreate(Long topicId, Publicity publicity) { + public boolean canTopicCreate(AuthTopic authTopic) { return true; } @Override - public boolean canTopicUpdate(Long topicId, Publicity publicity) { - return isCreator(topicId); + public boolean canTopicUpdate(AuthTopic authTopic) { + return isCreator(authTopic.topicId()); } @Override - public boolean canPinCreateOrUpdate(Long topicId, Publicity publicity) { - return isPublic(publicity) || isGroup(topicId); + public boolean canPinCreateOrUpdate(AuthTopic authTopic) { + return isAllMembers(authTopic) || hasPermission(authTopic.topicId()); + } + + private boolean isAllMembers(final AuthTopic authTopic) { + return authTopic.permission() == Permission.ALL_MEMBERS; } private boolean isGroup(Long topicId) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java new file mode 100644 index 000000000..9ae7d566f --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java @@ -0,0 +1,20 @@ +package com.mapbefine.mapbefine.dto; + +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; +import com.mapbefine.mapbefine.entity.topic.Topic; + +public record AuthTopic( + Long topicId, + Publicity publicity, + Permission permission + +) { + public static AuthTopic from(Topic topic) { + return new AuthTopic( + topic.getId(), + topic.getPublicity(), + topic.getPermission() + ); + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java index 4779f761d..aeb3302d4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java @@ -116,12 +116,4 @@ public void addPin(Pin pin) { pins.add(pin); } - public boolean isPublic() { - return publicity == Publicity.PUBLIC; - } - - public boolean isPrivate() { - return publicity == Publicity.PRIVATE; - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index 7570ca222..603d223b9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -3,6 +3,8 @@ import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; +import com.mapbefine.mapbefine.config.auth.AuthMember; +import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; @@ -33,17 +35,15 @@ public TopicQueryService(final TopicRepository topicRepository, LocationReposito this.locationRepository = locationRepository; } - public List findAll(Member member) { - List allTopicsWithPermission = member.getAllTopicsWithPermission(); + public List findAll(AuthMember member) { + // 여기서 사실 Member -> AuthMember 여야한다. + // AuthMember 의 canRead 에다가 AuthTopic 을 넘겨야 한다. + // 여기에는 Permision 등등ㄷ이 필요하다. return topicRepository.findAll().stream() - .filter(topic -> hasPermission(allTopicsWithPermission, topic, member)) + .filter(topic -> member.canRead(AuthTopic.from(topic))) .map(TopicResponse::from) - .collect(Collectors.toList()); - } - - private boolean hasPermission(List allTopicsWithPermission, Topic topic, Member member) { - return member.isAdmin() || topic.isPublic() || allTopicsWithPermission.contains(topic); + .toList(); } public TopicDetailResponse findById(Long id) { From 5bda12ffcd267f10d63354f059a42ebab55cc280 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Fri, 28 Jul 2023 15:50:25 +0900 Subject: [PATCH 07/88] =?UTF-8?q?refactor:=20API=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=9E=84?= =?UTF-8?q?=EC=9D=98=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jaeyeon kim --- .../mapbefine/config/WebMvcConfig.java | 9 +-- .../mapbefine/config/auth/Admin.java | 16 ++--- .../mapbefine/config/auth/AuthMember.java | 3 +- .../{dto => config/auth}/AuthTopic.java | 2 +- .../mapbefine/config/auth/Guest.java | 5 +- .../mapbefine/mapbefine/config/auth/User.java | 1 - .../mapbefine/controller/TopicController.java | 9 +-- .../mapbefine/entity/member/Member.java | 2 +- .../mapbefine/entity/topic/Topic.java | 59 ++++++++++++++----- .../mapbefine/service/TopicQueryService.java | 20 +++---- 10 files changed, 65 insertions(+), 61 deletions(-) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => config/auth}/AuthTopic.java (91%) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java index 27162c5ed..bf4bea886 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java @@ -1,9 +1,7 @@ package com.mapbefine.mapbefine.config; import com.mapbefine.mapbefine.repository.MemberRepository; -import java.util.List; import org.springframework.context.annotation.Configuration; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -23,10 +21,5 @@ public void addCorsMappings(CorsRegistry registry) { .allowedMethods("*") .exposedHeaders("Location"); } - - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(new MemberArgumentResolver(memberRepository)); - } - + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java index 84f868d83..afbbdd99d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java @@ -1,20 +1,12 @@ package com.mapbefine.mapbefine.config.auth; -import com.mapbefine.mapbefine.dto.AuthTopic; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import java.util.List; - public class Admin extends AuthMember { - protected Admin( - Long memberId, - List createdTopic, - List topicsWithPermission - ) { + protected Admin() { super( - memberId, - createdTopic, - topicsWithPermission + null, + null, + null ); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index bd49059bb..3e784e575 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -1,6 +1,5 @@ package com.mapbefine.mapbefine.config.auth; -import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.MemberTopicPermission; import com.mapbefine.mapbefine.entity.topic.Publicity; @@ -32,7 +31,7 @@ public static AuthMember from(Member member) { return new User(member.getId(), getCreatedTopics(member), getTopicsWithPermission(member)); } - return new Admin(member.getId(), getCreatedTopics(member), getTopicsWithPermission(member)); + return new Admin(); } private static List getTopicsWithPermission(Member member) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java similarity index 91% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java rename to backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java index 9ae7d566f..8ff62e9e7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/AuthTopic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.config.auth; import com.mapbefine.mapbefine.entity.topic.Permission; import com.mapbefine.mapbefine.entity.topic.Publicity; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java index 5bdfb364b..d62771d4b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java @@ -1,8 +1,5 @@ package com.mapbefine.mapbefine.config.auth; -import com.mapbefine.mapbefine.dto.AuthTopic; -import com.mapbefine.mapbefine.entity.topic.Publicity; - public class Guest extends AuthMember { @@ -16,7 +13,7 @@ protected Guest() { @Override public boolean canRead(AuthTopic authTopic) { - return isPublic(publicity); + return isPublic(authTopic.publicity()); } @Override diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index c98071934..8f8f2d731 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -1,6 +1,5 @@ package com.mapbefine.mapbefine.config.auth; -import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.entity.topic.Permission; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java index ae08e4296..c28d5bce0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java @@ -6,7 +6,6 @@ import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicResponse; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.Member; import com.mapbefine.mapbefine.service.TopicCommandService; import com.mapbefine.mapbefine.service.TopicQueryService; import java.net.URI; @@ -34,8 +33,7 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic } @PostMapping("/new") - public ResponseEntity create(Member member, @RequestBody TopicCreateRequest request) { - System.out.println(member); + public ResponseEntity create(@RequestBody TopicCreateRequest request) { long topicId = topicCommandService.createNew(request); return ResponseEntity.created(URI.create("/topics/" + topicId)) @@ -65,9 +63,8 @@ public ResponseEntity delete(@PathVariable Long topicId) { } @GetMapping - public ResponseEntity> findAll(Member member) { - System.out.println(member); - List topics = topicQueryService.findAll(member); + public ResponseEntity> findAll() { + List topics = topicQueryService.findAll(); return ResponseEntity.ok(topics); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java index 6b45f9995..b7e30ebf8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java @@ -40,7 +40,7 @@ public class Member extends BaseEntity { @Column(nullable = false) private Role role; - @OneToMany(mappedBy = "member") + @OneToMany(mappedBy = "creator") private List createdTopic = new ArrayList<>(); @OneToMany(mappedBy = "member") diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java index ece5e8328..1e404ffe2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java @@ -3,6 +3,7 @@ import static lombok.AccessLevel.PROTECTED; import com.mapbefine.mapbefine.entity.BaseEntity; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.pin.Pin; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -56,31 +57,53 @@ public class Topic extends BaseEntity { @Column(nullable = false) private Permission permission; - @Column(nullable = false) - @ColumnDefault(value = "false") - private boolean isDeleted = false; - @ManyToOne @JoinColumn(name = "member_id") private Member creator; + @Column(nullable = false) + @ColumnDefault(value = "false") + private boolean isDeleted = false; + public Topic( String name, String description, - String imageUrl + String imageUrl, + Publicity publicity, + Permission permission, + Member creator + ) { + this.name = name; + this.description = description; + this.imageUrl = imageUrl; + this.publicity = publicity; + this.permission = permission; + this.creator = creator; + } + + public static Topic of( + String name, + String description, + String imageUrl, + Publicity publicity, + Permission permission, + Member creator ) { validateName(name); validateDescription(description); - this.name = name; - this.description = description; + return new Topic( + name, + description, + validateImageUrl(imageUrl), + publicity, + permission, + creator + ); - if (imageUrl != null) { // TODO : 정팩매 레츠기릿 - this.imageUrl = imageUrl; - } } - private void validateName(String name) { + private static void validateName(String name) { if (name == null) { throw new IllegalArgumentException("name null"); } @@ -89,7 +112,7 @@ private void validateName(String name) { } } - private void validateDescription(String description) { + private static void validateDescription(String description) { if (description == null) { throw new IllegalArgumentException("description null"); } @@ -98,6 +121,13 @@ private void validateDescription(String description) { } } + private static String validateImageUrl(String imageUrl) { + if (imageUrl == null) { // TODO: 2023/07/28 URL 검증 + return DEFAULT_IMAGE_URL; + } + return imageUrl; + } + public void update( String name, String description, @@ -105,13 +135,10 @@ public void update( ) { validateName(name); validateDescription(description); - // TODO : URL 형식 검증 필요? this.name = name; this.description = description; - if (imageUrl != null) { // TODO : 생성자와 중복 코드 - this.imageUrl = imageUrl; - } + this.imageUrl = validateImageUrl(imageUrl); } public int countPins() { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index 603d223b9..8a059fd53 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -3,12 +3,9 @@ import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.AuthTopic; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; import com.mapbefine.mapbefine.entity.topic.Topic; @@ -35,17 +32,20 @@ public TopicQueryService(final TopicRepository topicRepository, LocationReposito this.locationRepository = locationRepository; } - public List findAll(AuthMember member) { - // 여기서 사실 Member -> AuthMember 여야한다. - // AuthMember 의 canRead 에다가 AuthTopic 을 넘겨야 한다. - // 여기에는 Permision 등등ㄷ이 필요하다. - - return topicRepository.findAll().stream() - .filter(topic -> member.canRead(AuthTopic.from(topic))) + public List findAll() { + return topicRepository.findAll() + .stream() .map(TopicResponse::from) .toList(); } +// public List findAll(AuthMember member) { +// return topicRepository.findAll().stream() +// .filter(topic -> member.canRead(AuthTopic.from(topic))) +// .map(TopicResponse::from) +// .toList(); +// } + public TopicDetailResponse findById(Long id) { Topic topic = topicRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); From 83f79ff02672581ce6467fd2b08604fee77571e3 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Fri, 28 Jul 2023 16:18:12 +0900 Subject: [PATCH 08/88] =?UTF-8?q?feat:=20Publicity,=20Permission=20?= =?UTF-8?q?=EC=A0=95=EC=A0=81=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?Converter=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/StringToPermissionConverter.java | 13 +++++++++++++ .../config/StringToPublicityConverter.java | 15 +++++++++++++++ .../mapbefine/config/WebMvcConfig.java | 16 +++++++++++++++- .../mapbefine/entity/topic/Permission.java | 17 +++++++++++++++++ .../mapbefine/entity/topic/Publicity.java | 16 ++++++++++++++++ 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java new file mode 100644 index 000000000..eff8a063a --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java @@ -0,0 +1,13 @@ +package com.mapbefine.mapbefine.config; + +import com.mapbefine.mapbefine.entity.topic.Publicity; +import org.springframework.core.convert.converter.Converter; + +public class StringToPermissionConverter implements Converter { + + @Override + public Publicity convert(String input) { + return Publicity.from(input); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java new file mode 100644 index 000000000..be3c34236 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java @@ -0,0 +1,15 @@ +package com.mapbefine.mapbefine.config; + +import com.mapbefine.mapbefine.entity.topic.Publicity; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +@Component +public class StringToPublicityConverter implements Converter { + + @Override + public Publicity convert(String input) { + return Publicity.from(input); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java index bf4bea886..fb5a25910 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java @@ -1,7 +1,10 @@ package com.mapbefine.mapbefine.config; import com.mapbefine.mapbefine.repository.MemberRepository; +import java.util.List; import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -21,5 +24,16 @@ public void addCorsMappings(CorsRegistry registry) { .allowedMethods("*") .exposedHeaders("Location"); } - + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new MemberArgumentResolver(memberRepository)); + } + + @Override + public void addFormatters(final FormatterRegistry registry) { + registry.addConverter(new StringToPermissionConverter()); + registry.addConverter(new StringToPublicityConverter()); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java index 3ab36b2b3..f5c2cf1d5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java @@ -1,5 +1,8 @@ package com.mapbefine.mapbefine.entity.topic; +import com.fasterxml.jackson.annotation.JsonCreator; +import java.util.Arrays; +import java.util.NoSuchElementException; import lombok.Getter; @Getter @@ -13,4 +16,18 @@ public enum Permission { Permission(String title) { this.title = title; } + + @JsonCreator + public static Publicity from(String input) { + return Arrays.stream(values()) + .filter(permission -> isSameName(input, permission)) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } + + private static boolean isSameName(String input, Publicity permission) { + return permission.name() + .equalsIgnoreCase(input); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java index 7704817b2..842f145d4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java @@ -1,5 +1,8 @@ package com.mapbefine.mapbefine.entity.topic; +import com.fasterxml.jackson.annotation.JsonCreator; +import java.util.Arrays; +import java.util.NoSuchElementException; import lombok.Getter; @Getter @@ -14,4 +17,17 @@ public enum Publicity { this.title = title; } + @JsonCreator + public static Publicity from(String input) { + return Arrays.stream(values()) + .filter(publicity -> isSameName(input, publicity)) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } + + private static boolean isSameName(String input, Publicity publicity) { + return publicity.name() + .equalsIgnoreCase(input); + } + } From 27a07382fb069a9304e2e2b215e9d585001c31f8 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 01:45:16 +0900 Subject: [PATCH 09/88] =?UTF-8?q?refactor:=20Topic=20=EC=97=90=20Publicity?= =?UTF-8?q?,=20Permission=20=EC=B6=94=EA=B0=80=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/MemberArgumentResolver.java | 9 ++-- .../mapbefine/config/auth/AuthMember.java | 2 + .../mapbefine/mapbefine/config/auth/User.java | 1 + .../mapbefine/controller/TopicController.java | 9 ++-- .../mapbefine/dto/TopicCreateRequest.java | 4 ++ .../mapbefine/dto/TopicMergeRequest.java | 4 ++ .../mapbefine/entity/topic/Permission.java | 4 +- .../repository/MemberRepository.java | 3 ++ .../service/TopicCommandService.java | 40 ++++++++++++-- .../mapbefine/mapbefine/MemberFixture.java | 29 ++++------ .../com/mapbefine/mapbefine/TopicFixture.java | 15 +++++- .../mapbefine/annotation/ServiceTest.java | 22 ++++++++ .../controller/TopicControllerTest.java | 24 +++++++-- .../mapbefine/mapbefine/entity/PinTest.java | 13 ++++- .../integration/TopicIntegrationTest.java | 53 +++++++++++++++---- .../repository/PinRepositoryTest.java | 23 +++++++- .../service/PinCommandServiceTest.java | 20 +++++-- .../service/PinQueryServiceTest.java | 18 +++++-- .../service/TopicCommandServiceTest.java | 13 +++-- .../service/TopicQueryServiceTest.java | 12 ++--- 20 files changed, 243 insertions(+), 75 deletions(-) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java index 5af828d16..828313c68 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java @@ -1,10 +1,9 @@ package com.mapbefine.mapbefine.config; -import com.mapbefine.mapbefine.entity.Member; -import com.mapbefine.mapbefine.entity.Role; +import com.mapbefine.mapbefine.config.auth.AuthMember; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.repository.MemberRepository; import jakarta.servlet.http.HttpServletRequest; -import java.util.NoSuchElementException; import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; @@ -14,7 +13,6 @@ public class MemberArgumentResolver implements HandlerMethodArgumentResolver { private static final String AUTHORIZATION = "Authorization"; - private static final Member GUEST = new Member("게스트", "guest@naver.com", "image.url", Role.GUEST); // Guest 객체는 따로 만드는 것이 좋을까? private final MemberRepository memberRepository; @@ -37,7 +35,8 @@ public Object resolveArgument( ) throws Exception { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); String memberEmail = request.getHeader(AUTHORIZATION); - Member member = memberRepository.findByEmail(memberEmail).orElse(null); + Member member = memberRepository.findByEmail(memberEmail) + .orElse(null); return AuthMember.from(member); // 이런 식으로 하면 바로 Guest, User, Admin 이 가능하지 않을까 } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index 3e784e575..743b6fbbe 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -5,7 +5,9 @@ import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import java.util.List; +import lombok.Getter; +@Getter public abstract class AuthMember { protected Long memberId; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index 8f8f2d731..7a38588d0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -1,6 +1,7 @@ package com.mapbefine.mapbefine.config.auth; import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import java.util.List; public class User extends AuthMember { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java index c28d5bce0..a9644db88 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.controller; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; @@ -33,16 +34,16 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic } @PostMapping("/new") - public ResponseEntity create(@RequestBody TopicCreateRequest request) { - long topicId = topicCommandService.createNew(request); + public ResponseEntity create(AuthMember authMember, @RequestBody TopicCreateRequest request) { + long topicId = topicCommandService.createNew(authMember, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) .build(); } @PostMapping("/merge") - public ResponseEntity mergeAndCreate(@RequestBody TopicMergeRequest request) { - long topicId = topicCommandService.createMerge(request); + public ResponseEntity mergeAndCreate(AuthMember authMember, @RequestBody TopicMergeRequest request) { + long topicId = topicCommandService.createMerge(authMember, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) .build(); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java index b382ae761..cad728e33 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java @@ -1,11 +1,15 @@ package com.mapbefine.mapbefine.dto; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import java.util.List; public record TopicCreateRequest( String name, String image, String description, + Publicity publicity, + Permission permission, List pins ) { } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java index 52683babb..48158c4d8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java @@ -1,11 +1,15 @@ package com.mapbefine.mapbefine.dto; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import java.util.List; public record TopicMergeRequest( String name, String image, String description, + Publicity publicity, + Permission permission, List topics ) { } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java index f5c2cf1d5..fe77ddb14 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java @@ -18,14 +18,14 @@ public enum Permission { } @JsonCreator - public static Publicity from(String input) { + public static Permission from(String input) { return Arrays.stream(values()) .filter(permission -> isSameName(input, permission)) .findFirst() .orElseThrow(NoSuchElementException::new); } - private static boolean isSameName(String input, Publicity permission) { + private static boolean isSameName(String input, Permission permission) { return permission.name() .equalsIgnoreCase(input); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java index 8dcccf17a..bdf269a6e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java @@ -1,7 +1,10 @@ package com.mapbefine.mapbefine.repository; import com.mapbefine.mapbefine.entity.member.Member; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberRepository extends JpaRepository { + + Optional findByEmail(String email); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java index 7aa328a51..9405df5e5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java @@ -1,14 +1,18 @@ package com.mapbefine.mapbefine.service; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.pin.Pin; import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import java.util.Collection; import java.util.List; +import java.util.NoSuchElementException; import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,14 +23,28 @@ public class TopicCommandService { private final TopicRepository topicRepository; private final PinRepository pinRepository; + private final MemberRepository memberRepository; - public TopicCommandService(final TopicRepository topicRepository, final PinRepository pinRepository) { + public TopicCommandService( + TopicRepository topicRepository, + PinRepository pinRepository, + MemberRepository memberRepository + ) { this.topicRepository = topicRepository; this.pinRepository = pinRepository; + this.memberRepository = memberRepository; } - public long createNew(final TopicCreateRequest request) { - Topic topic = new Topic(request.name(), request.description(), request.image()); + public long createNew(AuthMember authMember, TopicCreateRequest request) { + Topic topic = new Topic( + request.name(), + request.description(), + request.image(), + request.publicity(), + request.permission(), + findCreatorByAuthMember(authMember) + ); + topicRepository.save(topic); List pinIds = request.pins(); @@ -38,6 +56,11 @@ public long createNew(final TopicCreateRequest request) { return topic.getId(); } + private Member findCreatorByAuthMember(final AuthMember authMember) { + return memberRepository.findById(authMember.getMemberId()) + .orElseThrow(NoSuchElementException::new); + } + private void validateExist(int idCount, int existCount) { if (idCount != existCount) { throw new IllegalArgumentException("찾을 수 없는 ID가 포함되어 있습니다."); @@ -50,13 +73,20 @@ private List duplicateUserPins(List pins, Topic topic) { .collect(Collectors.toList()); } - public long createMerge(TopicMergeRequest request) { + public long createMerge(AuthMember authMember, TopicMergeRequest request) { List topicIds = request.topics(); List topics = topicRepository.findAllById(topicIds); validateExist(topicIds.size(), topics.size()); - Topic topic = new Topic(request.name(), request.description(), request.image()); + Topic topic = new Topic( + request.name(), + request.description(), + request.image(), + request.publicity(), + request.permission(), + findCreatorByAuthMember(authMember) + ); topicRepository.save(topic); List original = topics.stream() diff --git a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java index 168b7c2da..c5f0d9b43 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java @@ -2,26 +2,19 @@ import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; +import com.mapbefine.mapbefine.entity.pin.Location; +import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Topic; public class MemberFixture { - public static final Member ADMIN_MEMBER = new Member( - "운영자", - "admin@naver.com", - "image.url", - Role.ADMIN - ); - public static final Member USER_MEMBER = new Member( - "사용자", - "user@naver.com", - "image.url", - Role.USER - ); - public static final Member GUEST_MEMBER = new Member( - "게스트", - "guest@naver.com", - "image.url", - Role.GUEST - ); + public static Member create(Role role) { + return new Member( + "member", + "member@naver.com", + "image.com", + role + ); + } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java index 6e66aafae..2c3ba0349 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java @@ -1,11 +1,22 @@ package com.mapbefine.mapbefine; + +import com.mapbefine.mapbefine.entity.member.Role; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; public class TopicFixture { - public static Topic createByName(String name) { - return new Topic(name, "설명", null); + public static Topic createByName(String name) { // TODO : 추후에 Fixture 를 더 구체화 할 수 있도록 + return new Topic( + name, + "설명", + null, + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + MemberFixture.create(Role.ADMIN) + ); } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java new file mode 100644 index 000000000..559995ba9 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java @@ -0,0 +1,22 @@ +package com.mapbefine.mapbefine.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.FilterType; +import org.springframework.stereotype.Service; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@DataJpaTest( + includeFilters = @Filter( + type = FilterType.ANNOTATION, value = Service.class + ) +) +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +public @interface ServiceTest { +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java index 558c38014..ba1aa5640 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java @@ -10,6 +10,8 @@ import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicResponse; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.service.TopicCommandService; import com.mapbefine.mapbefine.service.TopicQueryService; import java.math.BigDecimal; @@ -33,8 +35,15 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Imag @Test @DisplayName("토픽 새로 생성") void create() throws Exception { - given(topicCommandService.createNew(any())).willReturn(1L); - TopicCreateRequest topicCreateRequest = new TopicCreateRequest("준팍의 안갈집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 다시 안갈집", List.of(1L, 2L, 3L)); + given(topicCommandService.createNew(any(), any())).willReturn(1L); + TopicCreateRequest topicCreateRequest = new TopicCreateRequest( + "준팍의 안갈집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 두번 다시 안갈집", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + List.of(1L, 2L, 3L) + ); mockMvc.perform( MockMvcRequestBuilders.post("/topics/new") @@ -46,8 +55,15 @@ void create() throws Exception { @Test @DisplayName("토픽 병합 생성") void mergeAndCreate() throws Exception { - given(topicCommandService.createMerge(any())).willReturn(1L); - TopicMergeRequest topicMergeRequest = new TopicMergeRequest("준팍의 안갈집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 다시 안갈집", List.of(1L, 2L, 3L)); + given(topicCommandService.createMerge(any(), any())).willReturn(1L); + TopicMergeRequest topicMergeRequest = new TopicMergeRequest( + "준팍의 안갈집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 두번 다시 안갈집", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + List.of(1L, 2L, 3L) + ); mockMvc.perform( MockMvcRequestBuilders.post("/topics/merge") diff --git a/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java index f58f24de2..532789eed 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java @@ -4,9 +4,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.mapbefine.mapbefine.MemberFixture; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import java.math.BigDecimal; import java.util.stream.Stream; @@ -26,7 +30,14 @@ class PinTest { ), "legalDongCode" ); - private static final Topic topic = new Topic("topicName", "topicDescription", null); + private static final Topic topic = new Topic( + "topicName", + "topicDescription", + null, + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + MemberFixture.create(Role.ADMIN) + ); @ParameterizedTest @MethodSource(value = "validNameAndDescription") diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java index 5277967cd..4571e56b3 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java @@ -6,6 +6,8 @@ import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; @@ -31,8 +33,14 @@ public class TopicIntegrationTest extends IntegrationTest { @Test @DisplayName("Pin 목록 없이 Topic을 생성하면 201을 반환한다") void createNewTopicWithoutPins_Success() { - TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest("준팍의 또간집", - "https://map-befine-official.github.io/favicon.png", "준팍이 2번 이상 간집 ", Collections.emptyList()); + TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( + "준팍의 또간집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 2번 이상 간집 ", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + Collections.emptyList() + ); // when ExtractableResponse response = createNewTopic(준팍의_또간집); @@ -65,7 +73,10 @@ void createNewTopicWithPins_Success() { "준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 2번 이상 간집 ", - pinIds); + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + pinIds + ); // when ExtractableResponse response = createNewTopic(준팍의_또간집); @@ -84,8 +95,13 @@ void createMergeTopic_Success() { .map(Topic::getId) .collect(Collectors.toList()); - TopicMergeRequest 송파_데이트코스 = new TopicMergeRequest("송파 데이트코스", - "https://map-befine-official.github.io/favicon.png", "맛집과 카페 토픽 합치기", topicIds); + TopicMergeRequest 송파_데이트코스 = new TopicMergeRequest( + "송파 데이트코스", + "https://map-befine-official.github.io/favicon.png", + "맛집과 카페 토픽 합치기", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + topicIds); // when ExtractableResponse response = RestAssured @@ -105,13 +121,23 @@ void createMergeTopic_Success() { @DisplayName("Topic을 수정하면 200을 반환한다") void updateTopic_Success() { ExtractableResponse newTopic = createNewTopic( - new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 간집", - Collections.emptyList())); + new TopicCreateRequest( + "준팍의 또간집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 두번 간집", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + Collections.emptyList() + ) + ); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); // when - TopicUpdateRequest 송파_데이트코스 = new TopicUpdateRequest("송파 데이트코스", - "https://map-befine-official.github.io/favicon.png", "수정한 토픽"); + TopicUpdateRequest 송파_데이트코스 = new TopicUpdateRequest( + "송파 데이트코스", + "https://map-befine-official.github.io/favicon.png", + "수정한 토픽" + ); ExtractableResponse response = RestAssured .given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) @@ -128,7 +154,12 @@ void updateTopic_Success() { @DisplayName("Topic을 삭제하면 204를 반환한다") void deleteTopic_Success() { ExtractableResponse newTopic = createNewTopic( - new TopicCreateRequest("준팍의 또간집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 간집 ", + new TopicCreateRequest( + "준팍의 또간집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 두번 간집 ", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, Collections.emptyList())); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); @@ -167,6 +198,8 @@ void findTopicDetail_Success() { "topicName", "image", "description", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, Collections.emptyList() ); ExtractableResponse createResponse = createNewTopic(request); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java index cc1899028..7853b29fa 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java @@ -2,9 +2,13 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.mapbefine.mapbefine.MemberFixture; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import java.math.BigDecimal; import java.util.List; @@ -31,7 +35,14 @@ class PinRepositoryTest { @DisplayName("핀을 삭제하면 soft-deleting 된다.") void deleteById_Success() { // given - Topic topic = new Topic("topicName", "topicDescription", null); + Topic topic = new Topic( + "topicName", + "topicDescription", + null, + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + MemberFixture.create(Role.ADMIN) + ); Location location = new Location( "parcel", "road", @@ -57,7 +68,14 @@ void deleteById_Success() { @DisplayName("토픽 ID로 핀을 삭제하면 soft-deleting 된다.") void deleteAllByTopicId_Success() { // given - Topic topic = new Topic("topicName", "topicDescription", null); + Topic topic = new Topic( + "topicName", + "topicDescription", + null, + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + MemberFixture.create(Role.ADMIN) + ); Location location = new Location( "parcel", "road", @@ -82,4 +100,5 @@ void deleteAllByTopicId_Success() { assertThat(deletedPins).extractingResultOf("isDeleted") .doesNotContain(false); } + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java index 41f735cd9..646e0bad4 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java @@ -3,27 +3,29 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.mapbefine.mapbefine.MemberFixture; +import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinUpdateRequest; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import jakarta.transaction.Transactional; import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -@Transactional -@SpringBootTest +@ServiceTest class PinCommandServiceTest { private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); @@ -47,7 +49,15 @@ class PinCommandServiceTest { @BeforeEach void setUp() { topic = topicRepository.save( - new Topic("topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png")); + new Topic( + "topicName", + "topicDescription", + "https://map-befine-official.github.io/favicon.png", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + MemberFixture.create(Role.ADMIN) + ) + ); } @Test diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java index 0f7d4197b..d625725fa 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java @@ -3,12 +3,17 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.mapbefine.mapbefine.MemberFixture; +import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; import com.mapbefine.mapbefine.entity.pin.PinImage; +import com.mapbefine.mapbefine.entity.topic.Permission; +import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.PinRepository; @@ -24,8 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -@Transactional -@SpringBootTest +@ServiceTest class PinQueryServiceTest { private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); @@ -54,7 +58,15 @@ void setUp() { coordinate = new Coordinate(latitude, longitude); location = saveLocation(coordinate); topic = topicRepository.save( - new Topic("topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png")); + new Topic( + "topicName", + "topicDescription", + "https://map-befine-official.github.io/favicon.png", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + MemberFixture.create(Role.ADMIN) + ) + ); } @Test diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java index d6c4fd433..de7a8b4f4 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java @@ -5,6 +5,7 @@ import com.mapbefine.mapbefine.LocationFixture; import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; +import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; @@ -18,28 +19,26 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.FilterType; +import org.springframework.stereotype.Service; -@DataJpaTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ServiceTest class TopicCommandServiceTest { - @Autowired - private PinRepository pinRepository; - @Autowired private TopicRepository topicRepository; @Autowired private LocationRepository locationRepository; + @Autowired private TopicCommandService topicCommandService; private Topic TOPIC_WITH_TWO_PINS; @BeforeEach void setup() { - topicCommandService = new TopicCommandService(topicRepository, pinRepository); - TOPIC_WITH_TWO_PINS = TopicFixture.createByName("준팍의 또간집"); Location location = LocationFixture.create(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java index 86c9fdc01..e37ce5646 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java @@ -5,6 +5,7 @@ import com.mapbefine.mapbefine.LocationFixture; import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; +import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; @@ -17,20 +18,19 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -@DataJpaTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ServiceTest class TopicQueryServiceTest { @Autowired private LocationRepository locationRepository; + @Autowired + private TopicQueryService topicQueryService; + @Autowired private TopicRepository topicRepository; - private com.mapbefine.mapbefine.service.TopicQueryService topicQueryService; private Topic TOPIC_BEST_3RD; private Topic TOPIC_BEST_2ND; private Topic TOPIC_BEST_1ST; @@ -38,8 +38,6 @@ class TopicQueryServiceTest { @BeforeEach void setup() { - topicQueryService = new com.mapbefine.mapbefine.service.TopicQueryService(topicRepository, locationRepository); - ALL_PINS_LOCATION = LocationFixture.createByCoordinate(35.0, 127.0); locationRepository.save(ALL_PINS_LOCATION); From 41ee4ef0b26b60a830e8ae6974c6c6305088f2ff Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 03:10:53 +0900 Subject: [PATCH 10/88] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EA=B0=80=20=ED=86=B5=EA=B3=BC?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/MemberArgumentResolver.java | 2 +- .../mapbefine/config/auth/Admin.java | 4 +-- .../mapbefine/config/auth/AuthMember.java | 11 +++++++- .../mapbefine/config/auth/Guest.java | 2 +- .../mapbefine/mapbefine/config/auth/User.java | 2 +- .../mapbefine/entity/pin/Location.java | 12 +++++++++ .../mapbefine/mapbefine/entity/pin/Pin.java | 13 ++++++++++ .../mapbefine/service/PinCommandService.java | 8 ++++-- .../com/mapbefine/mapbefine/TopicFixture.java | 8 +++--- .../mapbefine/annotation/ServiceTest.java | 4 ++- .../controller/TopicControllerTest.java | 7 ++++++ .../integration/PinIntegrationTest.java | 12 ++++++++- .../integration/TopicIntegrationTest.java | 18 ++++++++++--- .../repository/PinRepositoryTest.java | 25 +++++++------------ .../service/PinCommandServiceTest.java | 19 +++++++++++--- .../service/PinQueryServiceTest.java | 9 ++++++- .../service/TopicCommandServiceTest.java | 16 ++++++------ .../service/TopicQueryServiceTest.java | 11 +++++++- 18 files changed, 138 insertions(+), 45 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java index 828313c68..b2011a376 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java @@ -23,7 +23,7 @@ public MemberArgumentResolver(MemberRepository memberRepository) { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType() - .equals(Member.class); + .equals(AuthMember.class); } @Override diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java index afbbdd99d..9fd03de55 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java @@ -2,9 +2,9 @@ public class Admin extends AuthMember { - protected Admin() { + public Admin(Long memberId) { // 준팍 여기에 memberId 는 넣어야지 찾을 수 있더라고요 super( - null, + memberId, null, null ); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index 743b6fbbe..cd8bc0975 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -33,7 +33,7 @@ public static AuthMember from(Member member) { return new User(member.getId(), getCreatedTopics(member), getTopicsWithPermission(member)); } - return new Admin(); + return new Admin(member.getId()); } private static List getTopicsWithPermission(Member member) { @@ -69,4 +69,13 @@ protected boolean isPrivate(Publicity publicity) { return publicity == Publicity.PRIVATE; } + @Override + public String toString() { + return "AuthMember{" + + "memberId=" + memberId + + ", createdTopic=" + createdTopic + + ", topicsWithPermission=" + topicsWithPermission + + '}'; + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java index d62771d4b..129dc8400 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java @@ -3,7 +3,7 @@ public class Guest extends AuthMember { - protected Guest() { + public Guest() { super( null, null, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index 7a38588d0..cde0c0722 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -6,7 +6,7 @@ public class User extends AuthMember { - protected User( + public User( Long memberId, List createdTopic, List topicsWithPermission diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java index 624127598..6cfea14c1 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java @@ -68,8 +68,20 @@ public BigDecimal getLatitude() { return coordinate.getLatitude(); } + public BigDecimal getLongitude() { return coordinate.getLongitude(); } + @Override + public String toString() { + return "Location{" + + "id=" + id + + ", parcelBaseAddress='" + parcelBaseAddress + '\'' + + ", roadBaseAddress='" + roadBaseAddress + '\'' + + ", coordinate=" + coordinate + + ", legalDongCode='" + legalDongCode + '\'' + + '}'; + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java index 926a8a0df..304b6b219 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java @@ -128,4 +128,17 @@ public String getRoadBaseAddress() { return location.getRoadBaseAddress(); } + @Override + public String toString() { + return "Pin{" + + "id=" + id + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", pinImages=" + pinImages + + ", location=" + location + + ", isDeleted=" + isDeleted + + ", topic=" + topic + + '}'; + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java index 68cdd21f3..4e93b3750 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java @@ -48,8 +48,12 @@ public Long save(PinCreateRequest request) { .findFirst() .orElseGet(() -> saveLocation(request, coordinate)); - Pin pin = Pin.createPinAssociatedWithLocationAndTopic(request.name(), request.description(), pinLocation, - topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopic( + request.name(), + request.description(), + pinLocation, + topic + ); for (String pinImage : request.images()) { PinImage.createPinImageAssociatedWithPin(pinImage, pin); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java index 2c3ba0349..ed6cf1d22 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java @@ -1,21 +1,21 @@ package com.mapbefine.mapbefine; -import com.mapbefine.mapbefine.entity.member.Role; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.topic.Permission; import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; public class TopicFixture { - public static Topic createByName(String name) { // TODO : 추후에 Fixture 를 더 구체화 할 수 있도록 - return new Topic( + public static Topic createByName(String name, Member member) { + return Topic.of( name, "설명", null, Publicity.PUBLIC, Permission.ALL_MEMBERS, - MemberFixture.create(Role.ADMIN) + member ); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java index 559995ba9..4bf135738 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java @@ -9,14 +9,16 @@ import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) +@Transactional @DataJpaTest( includeFilters = @Filter( type = FilterType.ANNOTATION, value = Service.class ) ) -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public @interface ServiceTest { } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java index ba1aa5640..39265443d 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java @@ -3,6 +3,8 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import com.mapbefine.mapbefine.config.MemberArgumentResolver; +import com.mapbefine.mapbefine.config.auth.Admin; import com.mapbefine.mapbefine.dto.PinResponse; import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicDetailResponse; @@ -19,6 +21,7 @@ import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.mockito.Mock; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -31,11 +34,15 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Imag @MockBean private TopicQueryService topicQueryService; + @MockBean + private MemberArgumentResolver memberArgumentResolver; + @Test @DisplayName("토픽 새로 생성") void create() throws Exception { given(topicCommandService.createNew(any(), any())).willReturn(1L); + TopicCreateRequest topicCreateRequest = new TopicCreateRequest( "준팍의 안갈집", "https://map-befine-official.github.io/favicon.png", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java index 9286e7405..7ac91a45b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java @@ -3,11 +3,15 @@ import static org.assertj.core.api.Assertions.assertThat; import com.mapbefine.mapbefine.LocationFixture; +import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.dto.PinCreateRequest; +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import io.restassured.*; import io.restassured.response.*; @@ -20,9 +24,14 @@ import org.springframework.http.MediaType; public class PinIntegrationTest extends IntegrationTest { + private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); private Topic topic; private Location location; + private Member member; + + @Autowired + private MemberRepository memberRepository; @Autowired private TopicRepository topicRepository; @@ -32,7 +41,8 @@ public class PinIntegrationTest extends IntegrationTest { @BeforeEach void saveTopicAndLocation() { - topic = topicRepository.save(TopicFixture.createByName("PinIntegration 토픽")); + member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + topic = topicRepository.save(TopicFixture.createByName("PinIntegration 토픽", member)); location = locationRepository.save(LocationFixture.createByCoordinate(37.5152933, 127.1029866)); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java index 4571e56b3..b3c2c77ca 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java @@ -2,13 +2,17 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Pin; import com.mapbefine.mapbefine.entity.topic.Permission; import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import io.restassured.*; @@ -22,7 +26,9 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -public class TopicIntegrationTest extends IntegrationTest { +class TopicIntegrationTest extends IntegrationTest { + + private static final String AUTHORIZATION = "Authorization"; @Autowired private PinRepository pinRepository; @@ -30,6 +36,9 @@ public class TopicIntegrationTest extends IntegrationTest { @Autowired private TopicRepository topicRepository; + @Autowired + private MemberRepository memberRepository; + @Test @DisplayName("Pin 목록 없이 Topic을 생성하면 201을 반환한다") void createNewTopicWithoutPins_Success() { @@ -51,8 +60,10 @@ void createNewTopicWithoutPins_Success() { } private ExtractableResponse createNewTopic(TopicCreateRequest request) { + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); return RestAssured.given() .log().all() + .header(AUTHORIZATION, member.getEmail()) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/topics/new") @@ -63,7 +74,6 @@ private ExtractableResponse createNewTopic(TopicCreateRequest request) @Test @DisplayName("Pin 목록과 함께 Topic을 생성하면 201을 반환한다") void createNewTopicWithPins_Success() { - List pins = pinRepository.findAll(); List pinIds = pins.stream() .map(Pin::getId) @@ -160,7 +170,9 @@ void deleteTopic_Success() { "준팍이 두번 간집 ", Publicity.PUBLIC, Permission.ALL_MEMBERS, - Collections.emptyList())); + Collections.emptyList() + ) + ); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); // when diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java index 7853b29fa..a41e9f41c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java @@ -3,6 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import com.mapbefine.mapbefine.MemberFixture; +import com.mapbefine.mapbefine.TopicFixture; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; @@ -31,18 +33,15 @@ class PinRepositoryTest { @Autowired private LocationRepository locationRepository; + @Autowired + private MemberRepository memberRepository; + @Test @DisplayName("핀을 삭제하면 soft-deleting 된다.") void deleteById_Success() { // given - Topic topic = new Topic( - "topicName", - "topicDescription", - null, - Publicity.PUBLIC, - Permission.ALL_MEMBERS, - MemberFixture.create(Role.ADMIN) - ); + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Topic topic = TopicFixture.createByName("name", member); Location location = new Location( "parcel", "road", @@ -68,14 +67,8 @@ void deleteById_Success() { @DisplayName("토픽 ID로 핀을 삭제하면 soft-deleting 된다.") void deleteAllByTopicId_Success() { // given - Topic topic = new Topic( - "topicName", - "topicDescription", - null, - Publicity.PUBLIC, - Permission.ALL_MEMBERS, - MemberFixture.create(Role.ADMIN) - ); + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Topic topic = TopicFixture.createByName("name", member); Location location = new Location( "parcel", "road", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java index 646e0bad4..6ff9b0dc0 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java @@ -4,10 +4,10 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinUpdateRequest; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; @@ -16,6 +16,7 @@ import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import java.math.BigDecimal; @@ -24,9 +25,13 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; -@ServiceTest +@Transactional +@SpringBootTest class PinCommandServiceTest { + // TODO : Custom Annotation 인 @ServiceTest 를 붙여서 동작시키면, 중복된 Location 을 전혀 찾아오지 못하는 문제가 발생 (터지는 테스트는 @DisplayName("핀을 저장하려는 위치(Location)가 존재하면 해당 위치에 핀을 저장한다." 이 테스트)) private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); @Autowired @@ -44,10 +49,17 @@ class PinCommandServiceTest { @Autowired private TopicRepository topicRepository; + @Autowired + private MemberRepository memberRepository; + + private Topic topic; + private Member member; @BeforeEach void setUp() { + locationRepository.deleteAll(); + member = memberRepository.save(MemberFixture.create(Role.ADMIN)); topic = topicRepository.save( new Topic( "topicName", @@ -55,7 +67,7 @@ void setUp() { "https://map-befine-official.github.io/favicon.png", Publicity.PUBLIC, Permission.ALL_MEMBERS, - MemberFixture.create(Role.ADMIN) + member ) ); } @@ -80,6 +92,7 @@ void saveIfExistLocation_Success() { longitude.toString(), BASE_IMAGES ); + Long savedPinId = pinCommandService.save(request); // then diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java index d625725fa..f305c67f8 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java @@ -7,6 +7,7 @@ import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; +import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Coordinate; import com.mapbefine.mapbefine.entity.pin.Location; @@ -16,6 +17,7 @@ import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import jakarta.transaction.Transactional; @@ -45,11 +47,15 @@ class PinQueryServiceTest { @Autowired private LocationRepository locationRepository; + @Autowired + private MemberRepository memberRepository; + private Location location; private Coordinate coordinate; private Topic topic; + private Member member; @BeforeEach void setUp() { @@ -57,6 +63,7 @@ void setUp() { BigDecimal longitude = BigDecimal.valueOf(127.123456); coordinate = new Coordinate(latitude, longitude); location = saveLocation(coordinate); + member = memberRepository.save(MemberFixture.create(Role.ADMIN)); topic = topicRepository.save( new Topic( "topicName", @@ -64,7 +71,7 @@ void setUp() { "https://map-befine-official.github.io/favicon.png", Publicity.PUBLIC, Permission.ALL_MEMBERS, - MemberFixture.create(Role.ADMIN) + member ) ); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java index de7a8b4f4..b61657bda 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java @@ -3,29 +3,30 @@ import static org.assertj.core.api.Assertions.assertThat; import com.mapbefine.mapbefine.LocationFixture; +import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.pin.Pin; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.PinRepository; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.context.annotation.ComponentScan.Filter; -import org.springframework.context.annotation.FilterType; -import org.springframework.stereotype.Service; @ServiceTest class TopicCommandServiceTest { + @Autowired + private MemberRepository memberRepository; + @Autowired private TopicRepository topicRepository; @@ -39,7 +40,8 @@ class TopicCommandServiceTest { @BeforeEach void setup() { - TOPIC_WITH_TWO_PINS = TopicFixture.createByName("준팍의 또간집"); + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + TOPIC_WITH_TWO_PINS = TopicFixture.createByName("준팍의 또간집", member); Location location = LocationFixture.create(); locationRepository.save(location); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java index e37ce5646..b1fe450b7 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java @@ -3,15 +3,19 @@ import static org.assertj.core.api.Assertions.assertThat; import com.mapbefine.mapbefine.LocationFixture; +import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.annotation.ServiceTest; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; +import com.mapbefine.mapbefine.entity.member.Member; +import com.mapbefine.mapbefine.entity.member.Role; import com.mapbefine.mapbefine.entity.pin.Location; import com.mapbefine.mapbefine.entity.topic.Topic; import com.mapbefine.mapbefine.repository.LocationRepository; +import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.TopicRepository; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -22,6 +26,9 @@ @ServiceTest class TopicQueryServiceTest { + @Autowired + private MemberRepository memberRepository; + @Autowired private LocationRepository locationRepository; @@ -35,9 +42,11 @@ class TopicQueryServiceTest { private Topic TOPIC_BEST_2ND; private Topic TOPIC_BEST_1ST; private Location ALL_PINS_LOCATION; + private Member member; @BeforeEach void setup() { + member = memberRepository.save(MemberFixture.create(Role.ADMIN)); ALL_PINS_LOCATION = LocationFixture.createByCoordinate(35.0, 127.0); locationRepository.save(ALL_PINS_LOCATION); @@ -47,7 +56,7 @@ void setup() { } private Topic createAndSaveByNameAndPinCounts(String topicName, int pinCounts) { - Topic topic = TopicFixture.createByName(topicName); + Topic topic = TopicFixture.createByName(topicName, member); for (int i = 0; i < pinCounts; i++) { PinFixture.create(ALL_PINS_LOCATION, topic); } From b0850afcf8121b81225ef3a604fb75b770c6fd6d Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 03:33:25 +0900 Subject: [PATCH 11/88] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EA=B0=80=20=ED=86=B5=EA=B3=BC?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/IntegrationTest.java | 3 +- .../integration/TopicIntegrationTest.java | 47 +++++++++++++++---- backend/src/test/resources/initialization.sql | 1 + 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java index 0c0fdd017..9890a13b3 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java @@ -5,8 +5,9 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.Sql.ExecutionPhase; -@Sql("/initialization.sql") +@Sql(value = "/initialization.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class IntegrationTest { @LocalServerPort diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java index b3c2c77ca..a0f8e1e07 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java @@ -15,8 +15,9 @@ import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import io.restassured.*; -import io.restassured.response.*; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -42,6 +43,7 @@ class TopicIntegrationTest extends IntegrationTest { @Test @DisplayName("Pin 목록 없이 Topic을 생성하면 201을 반환한다") void createNewTopicWithoutPins_Success() { + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( "준팍의 또간집", "https://map-befine-official.github.io/favicon.png", @@ -52,15 +54,14 @@ void createNewTopicWithoutPins_Success() { ); // when - ExtractableResponse response = createNewTopic(준팍의_또간집); + ExtractableResponse response = createNewTopic(준팍의_또간집, member); // then assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); assertThat(response.header("Location")).isNotBlank(); } - private ExtractableResponse createNewTopic(TopicCreateRequest request) { - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + private ExtractableResponse createNewTopic(TopicCreateRequest request, Member member) { return RestAssured.given() .log().all() .header(AUTHORIZATION, member.getEmail()) @@ -74,6 +75,7 @@ private ExtractableResponse createNewTopic(TopicCreateRequest request) @Test @DisplayName("Pin 목록과 함께 Topic을 생성하면 201을 반환한다") void createNewTopicWithPins_Success() { + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); List pins = pinRepository.findAll(); List pinIds = pins.stream() .map(Pin::getId) @@ -89,7 +91,7 @@ void createNewTopicWithPins_Success() { ); // when - ExtractableResponse response = createNewTopic(준팍의_또간집); + ExtractableResponse response = createNewTopic(준팍의_또간집, member); // then assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); @@ -100,6 +102,27 @@ void createNewTopicWithPins_Success() { @DisplayName("여러개의 토픽을 병합하면 201을 반환한다") void createMergeTopic_Success() { // given + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + // TODO : 준팍! 해당 Merge Test 에는 topicRepository.findAll 을 통해서 이미 저장되어 있던 토픽들을 병합해주는 것으로 보이는데 + // TODO : 이러면 다른 테스트에 의존적이게 되지 않을까요? 일단은 의도가 있었을 수도 있을까봐 데이터를 추가하는 로직은 주석처리 해놓겠습니다. +// TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( +// "준팍의 또간집", +// "https://map-befine-official.github.io/favicon.png", +// "준팍이 2번 이상 간집 ", +// Publicity.PUBLIC, +// Permission.ALL_MEMBERS, +// Collections.emptyList() +// ); +// TopicCreateRequest 준팍의_또안간집 = new TopicCreateRequest( +// "준팍의 또안간집", +// "https://map-befine-official.github.io/favicon.png", +// "준팍이 2번 이상 안간집 ", +// Publicity.PUBLIC, +// Permission.ALL_MEMBERS, +// Collections.emptyList() +// ); +// createNewTopic(준팍의_또간집, member); +// createNewTopic(준팍의_또안간집, member); List topics = topicRepository.findAll(); List topicIds = topics.stream() .map(Topic::getId) @@ -116,6 +139,7 @@ void createMergeTopic_Success() { // when ExtractableResponse response = RestAssured .given().log().all() + .header(AUTHORIZATION, member.getEmail()) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(송파_데이트코스) .when().post("/topics/merge") @@ -130,6 +154,7 @@ void createMergeTopic_Success() { @Test @DisplayName("Topic을 수정하면 200을 반환한다") void updateTopic_Success() { + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); ExtractableResponse newTopic = createNewTopic( new TopicCreateRequest( "준팍의 또간집", @@ -138,7 +163,8 @@ void updateTopic_Success() { Publicity.PUBLIC, Permission.ALL_MEMBERS, Collections.emptyList() - ) + ), + member ); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); @@ -163,6 +189,7 @@ void updateTopic_Success() { @Test @DisplayName("Topic을 삭제하면 204를 반환한다") void deleteTopic_Success() { + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); ExtractableResponse newTopic = createNewTopic( new TopicCreateRequest( "준팍의 또간집", @@ -171,7 +198,8 @@ void deleteTopic_Success() { Publicity.PUBLIC, Permission.ALL_MEMBERS, Collections.emptyList() - ) + ), + member ); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); @@ -206,6 +234,7 @@ void findTopics_Success() { @DisplayName("Topic 상세 정보를 조회하면 200을 반환한다") void findTopicDetail_Success() { //given + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); TopicCreateRequest request = new TopicCreateRequest( "topicName", "image", @@ -214,7 +243,7 @@ void findTopicDetail_Success() { Permission.ALL_MEMBERS, Collections.emptyList() ); - ExtractableResponse createResponse = createNewTopic(request); + ExtractableResponse createResponse = createNewTopic(request, member); String locationHeader = createResponse.header("Location"); long topicId = Long.parseLong(locationHeader.split("/")[2]); diff --git a/backend/src/test/resources/initialization.sql b/backend/src/test/resources/initialization.sql index e747971f1..942bef990 100644 --- a/backend/src/test/resources/initialization.sql +++ b/backend/src/test/resources/initialization.sql @@ -2,4 +2,5 @@ SET FOREIGN_KEY_CHECKS = 0; TRUNCATE TABLE PIN; TRUNCATE TABLE LOCATION; TRUNCATE TABLE TOPIC; +TRUNCATE TABLE MEMBER; SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file From 9ffcefdab1cfd291ff48a3dd18d0b4a445c0bb7a Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 13:30:33 +0900 Subject: [PATCH 12/88] =?UTF-8?q?feat:=20Topic=20=EC=97=90=20=EA=B4=80?= =?UTF-8?q?=ED=95=9C=20CRUD=20=EC=97=90=20=EA=B6=8C=ED=95=9C=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/MemberArgumentResolver.java | 2 +- .../mapbefine/config/auth/Admin.java | 14 +++----- .../mapbefine/config/auth/AuthMember.java | 9 ++--- .../mapbefine/config/auth/Guest.java | 16 ++++----- .../mapbefine/mapbefine/config/auth/User.java | 21 ++++++----- .../controller/MemberController.java | 11 +----- .../mapbefine/controller/TopicController.java | 35 +++++++++++-------- .../service/TopicCommandService.java | 27 +++++++++----- .../mapbefine/service/TopicQueryService.java | 27 +++++++------- .../controller/TopicControllerTest.java | 13 ++----- .../integration/TopicIntegrationTest.java | 2 ++ .../service/TopicCommandServiceTest.java | 10 ++++-- .../service/TopicQueryServiceTest.java | 9 +++-- 13 files changed, 103 insertions(+), 93 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java index b2011a376..f2b1ce82e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java @@ -38,6 +38,6 @@ public Object resolveArgument( Member member = memberRepository.findByEmail(memberEmail) .orElse(null); - return AuthMember.from(member); // 이런 식으로 하면 바로 Guest, User, Admin 이 가능하지 않을까 + return AuthMember.from(member); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java index 9fd03de55..3473acdf0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java @@ -2,7 +2,7 @@ public class Admin extends AuthMember { - public Admin(Long memberId) { // 준팍 여기에 memberId 는 넣어야지 찾을 수 있더라고요 + public Admin(Long memberId) { // TODO : 준팍 여기에 memberId 는 넣어야지 찾을 수 있더라고요 super( memberId, null, @@ -16,23 +16,19 @@ public boolean canRead(AuthTopic authTopic) { } @Override - public boolean canDelete(AuthTopic authTopic) { - return true; + public void canDelete(AuthTopic authTopic) { } @Override - public boolean canTopicCreate(AuthTopic authTopic) { - return true; + public void canTopicCreate() { } @Override - public boolean canTopicUpdate(AuthTopic authTopic) { - return true; + public void canTopicUpdate(AuthTopic authTopic) { } @Override - public boolean canPinCreateOrUpdate(AuthTopic authTopic) { - return true; + public void canPinCreateOrUpdate(AuthTopic authTopic) { } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index cd8bc0975..be03ad29b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -5,6 +5,7 @@ import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import java.util.List; +import java.util.function.Predicate; import lombok.Getter; @Getter @@ -53,13 +54,13 @@ private static List getCreatedTopics(Member member) { public abstract boolean canRead(AuthTopic authTopic); - public abstract boolean canDelete(AuthTopic authTopic); + public abstract void canDelete(AuthTopic authTopic); - public abstract boolean canTopicCreate(AuthTopic authTopic); + public abstract void canTopicCreate(); - public abstract boolean canTopicUpdate(AuthTopic authTopic); + public abstract void canTopicUpdate(AuthTopic authTopic); - public abstract boolean canPinCreateOrUpdate(AuthTopic authTopic); + public abstract void canPinCreateOrUpdate(AuthTopic authTopic); protected boolean isPublic(Publicity publicity) { return publicity == Publicity.PUBLIC; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java index 129dc8400..da43ff6bd 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java @@ -17,23 +17,23 @@ public boolean canRead(AuthTopic authTopic) { } @Override - public boolean canDelete(AuthTopic authTopic) { - return false; + public void canDelete(AuthTopic authTopic) { + throw new IllegalArgumentException("권한이 없습니다."); } @Override - public boolean canTopicCreate(AuthTopic authTopic) { - return false; + public void canTopicCreate() { + throw new IllegalArgumentException("권한이 없습니다."); } @Override - public boolean canTopicUpdate(AuthTopic authTopic) { - return false; + public void canTopicUpdate(AuthTopic authTopic) { + throw new IllegalArgumentException("권한이 없습니다."); } @Override - public boolean canPinCreateOrUpdate(AuthTopic authTopic) { - return false; + public void canPinCreateOrUpdate(AuthTopic authTopic) { + throw new IllegalArgumentException("권한이 없습니다."); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index cde0c0722..9aa01b37f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -24,23 +24,28 @@ public boolean canRead(AuthTopic authTopic) { } @Override - public boolean canDelete(AuthTopic authTopic) { - return isPrivate(authTopic.publicity()) && isCreator(authTopic.topicId()); + public void canDelete(AuthTopic authTopic) { + if (isPrivate(authTopic.publicity()) && isCreator(authTopic.topicId())) { + throw new IllegalArgumentException("권한이 없습니다."); + } } @Override - public boolean canTopicCreate(AuthTopic authTopic) { - return true; + public void canTopicCreate() { } @Override - public boolean canTopicUpdate(AuthTopic authTopic) { - return isCreator(authTopic.topicId()); + public void canTopicUpdate(AuthTopic authTopic) { + if (isCreator(authTopic.topicId())) { + throw new IllegalArgumentException("권한이 없습니다."); + } } @Override - public boolean canPinCreateOrUpdate(AuthTopic authTopic) { - return isAllMembers(authTopic) || hasPermission(authTopic.topicId()); + public void canPinCreateOrUpdate(AuthTopic authTopic) { + if (isAllMembers(authTopic) || hasPermission(authTopic.topicId())) { + throw new IllegalArgumentException("권한이 없습니다."); + } } private boolean isAllMembers(final AuthTopic authTopic) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java index c2256df2d..485c5f5ac 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java @@ -5,15 +5,6 @@ @RestController @RequestMapping("/members") -public class MemberController { // Mypage 내용, Member 들 리스트 - -// @GetMapping("/topics") -// public List topicResponseList(AuthMember member) { // 현재 Login 한 User 의 정보가 넘어와야함 -// // Member member -> MyTopic -> .get -> -//// memberService.findMyTopic(member); // member.getCreateTopics().stream(TopicResponse::From) -// -// // memberService TopicId -> 다 각각 조회해서 TopicResponse 로 감싸서 보내준다. -// } - +public class MemberController { } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java index a9644db88..455e0de7b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java @@ -34,52 +34,59 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic } @PostMapping("/new") - public ResponseEntity create(AuthMember authMember, @RequestBody TopicCreateRequest request) { - long topicId = topicCommandService.createNew(authMember, request); + public ResponseEntity create(AuthMember member, @RequestBody TopicCreateRequest request) { + long topicId = topicCommandService.createNew(member, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) .build(); } @PostMapping("/merge") - public ResponseEntity mergeAndCreate(AuthMember authMember, @RequestBody TopicMergeRequest request) { - long topicId = topicCommandService.createMerge(authMember, request); + public ResponseEntity mergeAndCreate(AuthMember member, @RequestBody TopicMergeRequest request) { + long topicId = topicCommandService.createMerge(member, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) .build(); } @PutMapping("/{topicId}") - public ResponseEntity update(@PathVariable Long topicId, @RequestBody TopicUpdateRequest request) { - topicCommandService.update(topicId, request); + public ResponseEntity update( + AuthMember member, + @PathVariable Long topicId, + @RequestBody TopicUpdateRequest request + ) { + topicCommandService.update(member, topicId, request); return ResponseEntity.ok().build(); } @DeleteMapping("/{topicId}") - public ResponseEntity delete(@PathVariable Long topicId) { - topicCommandService.delete(topicId); + public ResponseEntity delete(AuthMember member, @PathVariable Long topicId) { + topicCommandService.delete(member, topicId); return ResponseEntity.noContent().build(); } @GetMapping - public ResponseEntity> findAll() { - List topics = topicQueryService.findAll(); + public ResponseEntity> findAll(AuthMember member) { + List topics = topicQueryService.findAll(member); return ResponseEntity.ok(topics); } @GetMapping("/{id}") - public ResponseEntity findById(@PathVariable Long id) { - TopicDetailResponse response = topicQueryService.findById(id); + public ResponseEntity findById(AuthMember member, @PathVariable Long id) { + TopicDetailResponse response = topicQueryService.findById(member, id); return ResponseEntity.ok(response); } @GetMapping("/best") - public ResponseEntity> findBests(@RequestBody TopicFindBestRequest request) { - List responses = topicQueryService.findBests(request); + public ResponseEntity> findBests( + AuthMember member, + @RequestBody TopicFindBestRequest request + ) { + List responses = topicQueryService.findBests(member, request); return ResponseEntity.ok(responses); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java index 9405df5e5..8b5f5f601 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java @@ -1,6 +1,7 @@ package com.mapbefine.mapbefine.service; import com.mapbefine.mapbefine.config.auth.AuthMember; +import com.mapbefine.mapbefine.config.auth.AuthTopic; import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicMergeRequest; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; @@ -35,14 +36,16 @@ public TopicCommandService( this.memberRepository = memberRepository; } - public long createNew(AuthMember authMember, TopicCreateRequest request) { + public long createNew(AuthMember member, TopicCreateRequest request) { + member.canTopicCreate(); + Topic topic = new Topic( request.name(), request.description(), request.image(), request.publicity(), request.permission(), - findCreatorByAuthMember(authMember) + findCreatorByAuthMember(member) ); topicRepository.save(topic); @@ -56,8 +59,8 @@ public long createNew(AuthMember authMember, TopicCreateRequest request) { return topic.getId(); } - private Member findCreatorByAuthMember(final AuthMember authMember) { - return memberRepository.findById(authMember.getMemberId()) + private Member findCreatorByAuthMember(AuthMember member) { + return memberRepository.findById(member.getMemberId()) .orElseThrow(NoSuchElementException::new); } @@ -73,9 +76,12 @@ private List duplicateUserPins(List pins, Topic topic) { .collect(Collectors.toList()); } - public long createMerge(AuthMember authMember, TopicMergeRequest request) { + public long createMerge(AuthMember member, TopicMergeRequest request) { List topicIds = request.topics(); - List topics = topicRepository.findAllById(topicIds); + List topics = topicRepository.findAllById(topicIds) + .stream() + .filter(topic -> member.canRead(AuthTopic.from(topic))) // TODO : 일단, 이렇게 Merge 하기 이전에 canRead 한 놈들만 골라낼 수 있도록 했어요. + .toList(); validateExist(topicIds.size(), topics.size()); @@ -85,8 +91,9 @@ public long createMerge(AuthMember authMember, TopicMergeRequest request) { request.image(), request.publicity(), request.permission(), - findCreatorByAuthMember(authMember) + findCreatorByAuthMember(member) ); + topicRepository.save(topic); List original = topics.stream() @@ -99,16 +106,18 @@ public long createMerge(AuthMember authMember, TopicMergeRequest request) { return topic.getId(); } - public void update(Long id, TopicUpdateRequest request) { + public void update(AuthMember member, Long id, TopicUpdateRequest request) { Topic topic = topicRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); + member.canTopicUpdate(AuthTopic.from(topic)); topic.update(request.name(), request.description(), request.image()); } - public void delete(Long id) { + public void delete(AuthMember member, Long id) { Topic topic = topicRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); + member.canDelete(AuthTopic.from(topic)); pinRepository.deleteAllByTopicId(id); topicRepository.deleteById(id); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index 8a059fd53..9b7604d3e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -3,6 +3,8 @@ import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; +import com.mapbefine.mapbefine.config.auth.AuthMember; +import com.mapbefine.mapbefine.config.auth.AuthTopic; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; @@ -32,32 +34,28 @@ public TopicQueryService(final TopicRepository topicRepository, LocationReposito this.locationRepository = locationRepository; } - public List findAll() { - return topicRepository.findAll() - .stream() + public List findAll(AuthMember member) { + return topicRepository.findAll().stream() + .filter(topic -> member.canRead(AuthTopic.from(topic))) .map(TopicResponse::from) .toList(); } -// public List findAll(AuthMember member) { -// return topicRepository.findAll().stream() -// .filter(topic -> member.canRead(AuthTopic.from(topic))) -// .map(TopicResponse::from) -// .toList(); -// } - - public TopicDetailResponse findById(Long id) { + public TopicDetailResponse findById(AuthMember member, Long id) { Topic topic = topicRepository.findById(id) + .stream() + .filter(presentTopic -> member.canRead(AuthTopic.from(presentTopic))) + .findFirst() .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); return TopicDetailResponse.from(topic); } - public List findBests(TopicFindBestRequest request) { + public List findBests(AuthMember member, TopicFindBestRequest request) { List locations = findLocationsInRectangle(request); Map topicCounts = countTopicsInLocations(locations); - return sortTopicsByCounts(topicCounts); + return sortTopicsByCounts(topicCounts, member); } private List findLocationsInRectangle(TopicFindBestRequest request) { @@ -75,8 +73,9 @@ private Map countTopicsInLocations(List locations) { .collect(groupingBy(Pin::getTopic, counting())); } - private List sortTopicsByCounts(Map topicCounts) { + private List sortTopicsByCounts(Map topicCounts, AuthMember member) { return topicCounts.entrySet().stream() + .filter(topicEntry -> member.canRead(AuthTopic.from(topicEntry.getKey()))) // TODO : 볼 수 있는 토픽만 걸러내는 과정 .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .map(Map.Entry::getKey) .map(TopicResponse::from) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java index 39265443d..61dad4560 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java @@ -3,8 +3,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import com.mapbefine.mapbefine.config.MemberArgumentResolver; -import com.mapbefine.mapbefine.config.auth.Admin; import com.mapbefine.mapbefine.dto.PinResponse; import com.mapbefine.mapbefine.dto.TopicCreateRequest; import com.mapbefine.mapbefine.dto.TopicDetailResponse; @@ -21,7 +19,6 @@ import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -34,10 +31,6 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Imag @MockBean private TopicQueryService topicQueryService; - @MockBean - private MemberArgumentResolver memberArgumentResolver; - - @Test @DisplayName("토픽 새로 생성") void create() throws Exception { @@ -115,7 +108,7 @@ void findAll() throws Exception { 5, LocalDateTime.now() )); - given(topicQueryService.findAll()).willReturn(responses); + given(topicQueryService.findAll(any())).willReturn(responses); mockMvc.perform( MockMvcRequestBuilders.get("/topics") @@ -150,7 +143,7 @@ void findById() throws Exception { ) ) ); - given(topicQueryService.findById(any())).willReturn(topicDetailResponse); + given(topicQueryService.findById(any(), any())).willReturn(topicDetailResponse); mockMvc.perform( MockMvcRequestBuilders.get("/topics/1") @@ -174,7 +167,7 @@ void findBests() throws Exception { LocalDateTime.now() )); TopicFindBestRequest topicFindBestRequest = new TopicFindBestRequest("37", "127"); - given(topicQueryService.findBests(any())).willReturn(responses); + given(topicQueryService.findBests(any(), any())).willReturn(responses); mockMvc.perform( MockMvcRequestBuilders.get("/topics/best") diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java index a0f8e1e07..d7f256e95 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java @@ -176,6 +176,7 @@ void updateTopic_Success() { ); ExtractableResponse response = RestAssured .given().log().all() + .header(AUTHORIZATION, member.getEmail()) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(송파_데이트코스) .when().put("/topics/{id}", topicId) @@ -206,6 +207,7 @@ void deleteTopic_Success() { // when ExtractableResponse response = RestAssured .given().log().all() + .header(AUTHORIZATION, member.getEmail()) .contentType(MediaType.APPLICATION_JSON_VALUE) .when().delete("/topics/{id}", topicId) .then().log().all() diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java index b61657bda..775b8014f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java @@ -7,6 +7,7 @@ import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.annotation.ServiceTest; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.TopicUpdateRequest; import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; @@ -37,10 +38,13 @@ class TopicCommandServiceTest { private TopicCommandService topicCommandService; private Topic TOPIC_WITH_TWO_PINS; + private Member member; + private AuthMember authMember; @BeforeEach void setup() { - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authMember = AuthMember.from(member); TOPIC_WITH_TWO_PINS = TopicFixture.createByName("준팍의 또간집", member); Location location = LocationFixture.create(); @@ -62,7 +66,7 @@ void update() { String name = "준팍의 안갈 집"; String description = "다시는 안갈 집"; String imageUrl = "https://map-befine-official.github.io/favicon.png"; - topicCommandService.update(id, new TopicUpdateRequest(name, imageUrl, description)); + topicCommandService.update(authMember, id, new TopicUpdateRequest(name, imageUrl, description)); //then Topic topic = topicRepository.findById(id).get(); @@ -78,7 +82,7 @@ void delete() { Long id = TOPIC_WITH_TWO_PINS.getId(); //when - topicCommandService.delete(id); + topicCommandService.delete(authMember, id); //then Topic deletedTopic = topicRepository.findById(id).get(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java index b1fe450b7..c2d007a7d 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java @@ -7,6 +7,7 @@ import com.mapbefine.mapbefine.PinFixture; import com.mapbefine.mapbefine.TopicFixture; import com.mapbefine.mapbefine.annotation.ServiceTest; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.TopicDetailResponse; import com.mapbefine.mapbefine.dto.TopicFindBestRequest; import com.mapbefine.mapbefine.dto.TopicResponse; @@ -43,10 +44,12 @@ class TopicQueryServiceTest { private Topic TOPIC_BEST_1ST; private Location ALL_PINS_LOCATION; private Member member; + private AuthMember authMember; @BeforeEach void setup() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authMember = AuthMember.from(member); ALL_PINS_LOCATION = LocationFixture.createByCoordinate(35.0, 127.0); locationRepository.save(ALL_PINS_LOCATION); @@ -68,7 +71,7 @@ private Topic createAndSaveByNameAndPinCounts(String topicName, int pinCounts) { void findAll() { // given // when - List topics = topicQueryService.findAll(); + List topics = topicQueryService.findAll(authMember); // then assertThat(topics).contains(TopicResponse.from(TOPIC_BEST_3RD)); @@ -79,7 +82,7 @@ void findAll() { void findById() { // given // when - TopicDetailResponse actual = topicQueryService.findById(TOPIC_BEST_3RD.getId()); + TopicDetailResponse actual = topicQueryService.findById(authMember, TOPIC_BEST_3RD.getId()); // then assertThat(actual).isEqualTo(TopicDetailResponse.from(TOPIC_BEST_3RD)); @@ -96,7 +99,7 @@ void findBests() { ); // when - List currentTopics = topicQueryService.findBests(currentLocation); + List currentTopics = topicQueryService.findBests(authMember, currentLocation); // then assertThat(currentTopics.get(0)).isEqualTo(TopicResponse.from(TOPIC_BEST_1ST)); From 471a8269c0cbbda951037f262cd0cbdd965c589b Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 15:56:59 +0900 Subject: [PATCH 13/88] =?UTF-8?q?fix:=20Converter=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EA=B0=92=20=EC=9D=B4=EC=83=81=EC=9C=BC=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/config/StringToPermissionConverter.java | 8 ++++---- .../mapbefine/config/StringToPublicityConverter.java | 2 -- .../java/com/mapbefine/mapbefine/config/WebMvcConfig.java | 4 ++-- .../java/com/mapbefine/mapbefine/config/auth/User.java | 1 - .../mapbefine/mapbefine/service/TopicCommandService.java | 1 + 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java index eff8a063a..07bdb7ab7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java @@ -1,13 +1,13 @@ package com.mapbefine.mapbefine.config; -import com.mapbefine.mapbefine.entity.topic.Publicity; +import com.mapbefine.mapbefine.entity.topic.Permission; import org.springframework.core.convert.converter.Converter; -public class StringToPermissionConverter implements Converter { +public class StringToPermissionConverter implements Converter { @Override - public Publicity convert(String input) { - return Publicity.from(input); + public Permission convert(String input) { + return Permission.from(input); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java index be3c34236..6d61d5481 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java @@ -2,9 +2,7 @@ import com.mapbefine.mapbefine.entity.topic.Publicity; import org.springframework.core.convert.converter.Converter; -import org.springframework.stereotype.Component; -@Component public class StringToPublicityConverter implements Converter { @Override diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java index fb5a25910..754dab2a8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java @@ -13,7 +13,7 @@ public class WebMvcConfig implements WebMvcConfigurer { private final MemberRepository memberRepository; - public WebMvcConfig(final MemberRepository memberRepository) { + public WebMvcConfig(MemberRepository memberRepository) { this.memberRepository = memberRepository; } @@ -31,7 +31,7 @@ public void addArgumentResolvers(List resolvers) } @Override - public void addFormatters(final FormatterRegistry registry) { + public void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringToPermissionConverter()); registry.addConverter(new StringToPublicityConverter()); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index 9aa01b37f..b326bc7c5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -1,7 +1,6 @@ package com.mapbefine.mapbefine.config.auth; import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; import java.util.List; public class User extends AuthMember { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java index 8b5f5f601..041f56e8b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java @@ -37,6 +37,7 @@ public TopicCommandService( } public long createNew(AuthMember member, TopicCreateRequest request) { + System.out.println(request); member.canTopicCreate(); Topic topic = new Topic( From 5075d4b711e53665afb29afa08445a5fa010d95d Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 16:26:49 +0900 Subject: [PATCH 14/88] =?UTF-8?q?feat:=20Pin=20=EA=B8=B0=EB=8A=A5=EC=97=90?= =?UTF-8?q?=20=EA=B6=8C=ED=95=9C=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/config/auth/AuthMember.java | 9 ------ .../mapbefine/controller/PinController.java | 25 +++++++++------ .../mapbefine/service/PinCommandService.java | 25 +++++++++++---- .../mapbefine/service/PinQueryService.java | 8 +++-- .../service/TopicCommandService.java | 1 - .../mapbefine/service/TopicQueryService.java | 2 -- .../controller/PinControllerTest.java | 6 ++-- .../integration/PinIntegrationTest.java | 6 ++++ .../service/PinCommandServiceTest.java | 31 +++++++++++-------- .../service/PinQueryServiceTest.java | 12 ++++--- 10 files changed, 74 insertions(+), 51 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index be03ad29b..cad5a8f50 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -70,13 +70,4 @@ protected boolean isPrivate(Publicity publicity) { return publicity == Publicity.PRIVATE; } - @Override - public String toString() { - return "AuthMember{" + - "memberId=" + memberId + - ", createdTopic=" + createdTopic + - ", topicsWithPermission=" + topicsWithPermission + - '}'; - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java index 46aea4f68..ba9e68f6f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.controller; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; @@ -33,15 +34,19 @@ public PinController(PinCommandService pinCommandService, PinQueryService pinQue } @PostMapping - public ResponseEntity add(@RequestBody PinCreateRequest request) { - Long savedId = pinCommandService.save(request); + public ResponseEntity add(AuthMember member, @RequestBody PinCreateRequest request) { + Long savedId = pinCommandService.save(member, request); return ResponseEntity.created(URI.create("/pins/" + savedId)).build(); } @PutMapping("/{pinId}") - public ResponseEntity update(@PathVariable Long pinId, @RequestBody PinUpdateRequest request) { - pinCommandService.update(pinId, request); + public ResponseEntity update( + AuthMember member, + @PathVariable Long pinId, + @RequestBody PinUpdateRequest request + ) { + pinCommandService.update(member, pinId, request); return ResponseEntity.ok() .header("Location", "/pins/" + pinId) @@ -49,22 +54,22 @@ public ResponseEntity update(@PathVariable Long pinId, @RequestBody PinUpd } @DeleteMapping("/{pinId}") - public ResponseEntity delete(@PathVariable Long pinId) { - pinCommandService.removeById(pinId); + public ResponseEntity delete(AuthMember member, @PathVariable Long pinId) { + pinCommandService.removeById(member, pinId); return ResponseEntity.noContent().build(); } @GetMapping("/{pinId}") - public ResponseEntity findById(@PathVariable Long pinId) { - PinDetailResponse response = pinQueryService.findById(pinId); + public ResponseEntity findById(AuthMember member, @PathVariable Long pinId) { + PinDetailResponse response = pinQueryService.findById(member, pinId); return ResponseEntity.ok(response); } @GetMapping - public ResponseEntity> findAll() { - List allResponses = pinQueryService.findAll(); + public ResponseEntity> findAll(AuthMember member) { + List allResponses = pinQueryService.findAll(member); return ResponseEntity.ok(allResponses); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java index 4e93b3750..9bdf0763c 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java @@ -1,5 +1,7 @@ package com.mapbefine.mapbefine.service; +import com.mapbefine.mapbefine.config.auth.AuthMember; +import com.mapbefine.mapbefine.config.auth.AuthTopic; import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinUpdateRequest; import com.mapbefine.mapbefine.entity.pin.Coordinate; @@ -32,10 +34,11 @@ public PinCommandService( this.topicRepository = topicRepository; } - public Long save(PinCreateRequest request) { + public Long save(AuthMember member, PinCreateRequest request) { Coordinate coordinate = Coordinate.from(request.latitude(), request.longitude()); Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); + member.canPinCreateOrUpdate(AuthTopic.from(topic)); Location pinLocation = locationRepository.findAllByRectangle( coordinate.getLatitude(), @@ -73,19 +76,29 @@ private Location saveLocation(PinCreateRequest pinCreateRequest, Coordinate coor return locationRepository.save(location); } - public void update(Long pinId, PinUpdateRequest request) { - Pin pin = pinRepository.findById(pinId).orElseThrow(NoSuchElementException::new); + public void update( + AuthMember member, + Long pinId, + PinUpdateRequest request + ) { + Pin pin = pinRepository.findById(pinId) + .orElseThrow(NoSuchElementException::new); + member.canPinCreateOrUpdate(AuthTopic.from(pin.getTopic())); pin.update(request.name(), request.description()); pinRepository.save(pin); } - public void removeById(Long pinId) { + public void removeById(AuthMember member, Long pinId) { + Pin pin = pinRepository.findById(pinId) + .orElseThrow(NoSuchElementException::new); + member.canDelete(AuthTopic.from(pin.getTopic())); pinRepository.deleteById(pinId); } - public void removeAllByTopicId(Long topicId) { - pinRepository.deleteAllByTopicId(topicId); + public void removeAllByTopicId(Long topicId) { // TODO : pinCommandService 에는 필요없는 메서드 인 것 같음 +// pinRepository.deleteAllByTopicId(topicId); } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java index 2b3f020df..e633294b7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java @@ -1,5 +1,7 @@ package com.mapbefine.mapbefine.service; +import com.mapbefine.mapbefine.config.auth.AuthMember; +import com.mapbefine.mapbefine.config.auth.AuthTopic; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; import com.mapbefine.mapbefine.entity.pin.Pin; @@ -18,15 +20,17 @@ public PinQueryService(PinRepository pinRepository) { this.pinRepository = pinRepository; } - public List findAll() { + public List findAll(AuthMember member) { return pinRepository.findAll() .stream() + .filter(pin -> member.canRead(AuthTopic.from(pin.getTopic()))) .map(PinResponse::from) .toList(); } - public PinDetailResponse findById(Long pinId) { + public PinDetailResponse findById(AuthMember member, Long pinId) { Pin pin = pinRepository.findById(pinId) + .filter(optionalPin -> member.canRead(AuthTopic.from(optionalPin.getTopic()))) .orElseThrow(NoSuchElementException::new); return PinDetailResponse.from(pin); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java index 041f56e8b..8b5f5f601 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java @@ -37,7 +37,6 @@ public TopicCommandService( } public long createNew(AuthMember member, TopicCreateRequest request) { - System.out.println(request); member.canTopicCreate(); Topic topic = new Topic( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index 9b7604d3e..c422e8472 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -43,9 +43,7 @@ public List findAll(AuthMember member) { public TopicDetailResponse findById(AuthMember member, Long id) { Topic topic = topicRepository.findById(id) - .stream() .filter(presentTopic -> member.canRead(AuthTopic.from(presentTopic))) - .findFirst() .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); return TopicDetailResponse.from(topic); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java index c595b576b..1ee7f895e 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java @@ -32,7 +32,7 @@ class PinControllerTest extends RestDocsIntegration { @Test @DisplayName("핀 추가") void add() throws Exception { - given(pinCommandService.save(any())).willReturn(1L); + given(pinCommandService.save(any(), any())).willReturn(1L); PinCreateRequest pinCreateRequest = new PinCreateRequest( 1L, @@ -93,7 +93,7 @@ void findById() throws Exception { BASE_IMAGES ); - given(pinQueryService.findById(any())).willReturn(pinDetailResponse); + given(pinQueryService.findById(any(), any())).willReturn(pinDetailResponse); mockMvc.perform( MockMvcRequestBuilders.get("/pins/1") @@ -123,7 +123,7 @@ void findAll() throws Exception { ) ); - given(pinQueryService.findAll()).willReturn(pinResponses); + given(pinQueryService.findAll(any())).willReturn(pinResponses); mockMvc.perform( MockMvcRequestBuilders.get("/pins") diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java index 7ac91a45b..478991b54 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java @@ -5,6 +5,7 @@ import com.mapbefine.mapbefine.LocationFixture; import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.TopicFixture; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; @@ -25,10 +26,13 @@ public class PinIntegrationTest extends IntegrationTest { + private static final String AUTHORIZATION = "Authorization"; private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); + private Topic topic; private Location location; private Member member; + private AuthMember authMember; @Autowired private MemberRepository memberRepository; @@ -42,6 +46,7 @@ public class PinIntegrationTest extends IntegrationTest { @BeforeEach void saveTopicAndLocation() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authMember = AuthMember.from(member); topic = topicRepository.save(TopicFixture.createByName("PinIntegration 토픽", member)); location = locationRepository.save(LocationFixture.createByCoordinate(37.5152933, 127.1029866)); } @@ -71,6 +76,7 @@ void addIfExistDuplicateLocation_Success() { private ExtractableResponse createPin(PinCreateRequest request) { return RestAssured.given().log().all() + .header(AUTHORIZATION, member.getEmail()) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/pins") diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java index 6ff9b0dc0..ce96e79b8 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.mapbefine.mapbefine.MemberFixture; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinUpdateRequest; @@ -32,6 +33,7 @@ @SpringBootTest class PinCommandServiceTest { // TODO : Custom Annotation 인 @ServiceTest 를 붙여서 동작시키면, 중복된 Location 을 전혀 찾아오지 못하는 문제가 발생 (터지는 테스트는 @DisplayName("핀을 저장하려는 위치(Location)가 존재하면 해당 위치에 핀을 저장한다." 이 테스트)) + private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); @Autowired @@ -55,11 +57,13 @@ class PinCommandServiceTest { private Topic topic; private Member member; + private AuthMember authMember; @BeforeEach void setUp() { locationRepository.deleteAll(); member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authMember = AuthMember.from(member); topic = topicRepository.save( new Topic( "topicName", @@ -93,10 +97,10 @@ void saveIfExistLocation_Success() { BASE_IMAGES ); - Long savedPinId = pinCommandService.save(request); + Long savedPinId = pinCommandService.save(authMember, request); // then - PinDetailResponse actual = pinQueryService.findById(savedPinId); + PinDetailResponse actual = pinQueryService.findById(authMember, savedPinId); PinDetailResponse expected = new PinDetailResponse( savedPinId, "name", @@ -144,10 +148,10 @@ void saveIfNotExistLocation_Success() { longitude.toString(), BASE_IMAGES ); - Long savedPinId = pinCommandService.save(request); + Long savedPinId = pinCommandService.save(authMember, request); // then - PinDetailResponse actual = pinQueryService.findById(savedPinId); + PinDetailResponse actual = pinQueryService.findById(authMember, savedPinId); PinDetailResponse expected = new PinDetailResponse( savedPinId, "name", @@ -189,7 +193,7 @@ void update_Success() { longitude.toString(), BASE_IMAGES ); - Long savedPinId = pinCommandService.save(createRequest); + Long savedPinId = pinCommandService.save(authMember, createRequest); // when PinUpdateRequest updateRequest = new PinUpdateRequest( @@ -197,10 +201,10 @@ void update_Success() { "updatedDescription", BASE_IMAGES ); - pinCommandService.update(savedPinId, updateRequest); + pinCommandService.update(authMember, savedPinId, updateRequest); // then - PinDetailResponse actual = pinQueryService.findById(savedPinId); + PinDetailResponse actual = pinQueryService.findById(authMember, savedPinId); PinDetailResponse expected = new PinDetailResponse( savedPinId, "updatedName", @@ -236,11 +240,11 @@ void update_Fail() { longitude.toString(), BASE_IMAGES ); - Long savedPinId = pinCommandService.save(createRequest); + Long savedPinId = pinCommandService.save(authMember, createRequest); // when then PinUpdateRequest updateRequest = new PinUpdateRequest("", "updatedDescription", BASE_IMAGES); - assertThatThrownBy(() -> pinCommandService.update(savedPinId, updateRequest)) + assertThatThrownBy(() -> pinCommandService.update(authMember, savedPinId, updateRequest)) .isInstanceOf(IllegalArgumentException.class); } @@ -263,13 +267,13 @@ void removeById_Success() { longitude.toString(), BASE_IMAGES ); - Long savedPinId = pinCommandService.save(createRequest); + Long savedPinId = pinCommandService.save(authMember, createRequest); // when Pin pin = pinRepository.findById(savedPinId).get(); assertThat(pin.isDeleted()).isFalse(); - pinCommandService.removeById(savedPinId); + pinCommandService.removeById(authMember, savedPinId); // then Pin deletedPin = pinRepository.findById(savedPinId).get(); @@ -298,14 +302,15 @@ void removeAllByTopicId_Success() { ); for (int i = 0; i < 10; i++) { - pinCommandService.save(createRequest); + pinCommandService.save(authMember, createRequest); } // when Topic findTopicBeforeDeleting = topicRepository.findById(topic.getId()).get(); assertThat(findTopicBeforeDeleting.getPins()).extractingResultOf("isDeleted") .doesNotContain(true); - pinCommandService.removeAllByTopicId(topic.getId()); +// pinCommandService.removeAllByTopicId(topic.getId()); // TODO : 이 메서드는 현재 테스트에서만 사용되고 있는 메서드 ?? + pinRepository.deleteAllByTopicId(topic.getId()); // then Topic findTopicAfterDeleting = topicRepository.findById(topic.getId()).get(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java index f305c67f8..588c1bf23 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java @@ -2,9 +2,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.annotation.ServiceTest; +import com.mapbefine.mapbefine.config.auth.AuthMember; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; import com.mapbefine.mapbefine.entity.member.Member; @@ -20,7 +22,6 @@ import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.PinRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import jakarta.transaction.Transactional; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -29,7 +30,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; @ServiceTest class PinQueryServiceTest { @@ -56,6 +56,7 @@ class PinQueryServiceTest { private Topic topic; private Member member; + private AuthMember authMember; @BeforeEach void setUp() { @@ -64,6 +65,7 @@ void setUp() { coordinate = new Coordinate(latitude, longitude); location = saveLocation(coordinate); member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authMember = AuthMember.from(member); topic = topicRepository.save( new Topic( "topicName", @@ -95,7 +97,7 @@ void findAll_Success() { } // when - List responses = pinQueryService.findAll(); + List responses = pinQueryService.findAll(authMember); // then assertThat(responses).usingRecursiveComparison() @@ -121,7 +123,7 @@ void findById_Success() { null, BASE_IMAGES ); - PinDetailResponse actual = pinQueryService.findById(savedId); + PinDetailResponse actual = pinQueryService.findById(authMember, savedId); // then assertThat(actual).usingRecursiveComparison() @@ -133,7 +135,7 @@ void findById_Success() { @DisplayName("존재하지 않는 핀의 Id 를 넘기면 예외를 발생시킨다.") void findById_Fail() { // given when then - assertThatThrownBy(() -> pinQueryService.findById(1L)) + assertThatThrownBy(() -> pinQueryService.findById(authMember, 1L)) .isInstanceOf(NoSuchElementException.class); } From 30a97f787bc437587202e48ee87fd2da5dc36c26 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Sat, 29 Jul 2023 16:40:10 +0900 Subject: [PATCH 15/88] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EB=AC=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20=EC=A0=91=EA=B7=BC=20=EC=A0=9C=EC=96=B4?= =?UTF-8?q?=EC=9E=90=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/mapbefine/config/auth/AuthMember.java | 1 - .../com/mapbefine/mapbefine/config/auth/User.java | 2 +- .../mapbefine/controller/PinController.java | 6 ++---- .../mapbefine/mapbefine/entity/member/Member.java | 10 ---------- .../mapbefine/mapbefine/entity/pin/Location.java | 11 ----------- .../com/mapbefine/mapbefine/entity/pin/Pin.java | 13 ------------- .../mapbefine/repository/LocationRepository.java | 2 ++ .../mapbefine/repository/MemberRepository.java | 1 + .../mapbefine/repository/PinRepository.java | 1 + .../mapbefine/service/TopicCommandService.java | 5 ++--- .../mapbefine/service/TopicQueryService.java | 3 +-- .../java/com/mapbefine/mapbefine/MemberFixture.java | 3 --- .../mapbefine/mapbefine/annotation/ServiceTest.java | 2 -- .../mapbefine/controller/PinControllerTest.java | 13 ++++++------- .../mapbefine/integration/IntegrationTest.java | 2 +- .../mapbefine/integration/PinIntegrationTest.java | 13 ++++++------- .../mapbefine/integration/TopicIntegrationTest.java | 5 ++--- .../mapbefine/repository/PinRepositoryTest.java | 6 ++++-- .../mapbefine/service/PinQueryServiceTest.java | 1 - 19 files changed, 29 insertions(+), 71 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java index cad5a8f50..145d32256 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java @@ -5,7 +5,6 @@ import com.mapbefine.mapbefine.entity.topic.Publicity; import com.mapbefine.mapbefine.entity.topic.Topic; import java.util.List; -import java.util.function.Predicate; import lombok.Getter; @Getter diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java index b326bc7c5..c4e77a4ca 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java @@ -30,7 +30,7 @@ public void canDelete(AuthTopic authTopic) { } @Override - public void canTopicCreate() { + public void canTopicCreate() { // TODO : 이 부분은 로직을 작성할 필요 없어, @Override 없이 상속받은 메서드를 그냥 구현 없이 사용해도 될 것 같네용 } @Override diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java b/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java index ba9e68f6f..91a7e9f13 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java @@ -7,6 +7,8 @@ import com.mapbefine.mapbefine.dto.PinUpdateRequest; import com.mapbefine.mapbefine.service.PinCommandService; import com.mapbefine.mapbefine.service.PinQueryService; +import java.net.URI; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -17,10 +19,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; - -import java.net.URI; -import java.util.List; - @RestController @RequestMapping("/pins") public class PinController { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java index b7e30ebf8..efe0b4247 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java @@ -14,7 +14,6 @@ import jakarta.persistence.OneToMany; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import lombok.Getter; import lombok.NoArgsConstructor; @@ -71,15 +70,6 @@ public String getRoleKey() { return this.role.getKey(); } - public List getAllTopicsWithPermission() { - List allTopicsWithPermission = topicsWithPermission.stream() - .map(MemberTopicPermission::getTopic) - .collect(Collectors.toList()); - - allTopicsWithPermission.addAll(createdTopic); - return allTopicsWithPermission; - } - public boolean isAdmin() { return role == Role.ADMIN; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java index 6cfea14c1..02c94dc7a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java @@ -73,15 +73,4 @@ public BigDecimal getLongitude() { return coordinate.getLongitude(); } - @Override - public String toString() { - return "Location{" + - "id=" + id + - ", parcelBaseAddress='" + parcelBaseAddress + '\'' + - ", roadBaseAddress='" + roadBaseAddress + '\'' + - ", coordinate=" + coordinate + - ", legalDongCode='" + legalDongCode + '\'' + - '}'; - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java index 304b6b219..926a8a0df 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java @@ -128,17 +128,4 @@ public String getRoadBaseAddress() { return location.getRoadBaseAddress(); } - @Override - public String toString() { - return "Pin{" + - "id=" + id + - ", name='" + name + '\'' + - ", description='" + description + '\'' + - ", pinImages=" + pinImages + - ", location=" + location + - ", isDeleted=" + isDeleted + - ", topic=" + topic + - '}'; - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java index c439983eb..5c7ddbf17 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java @@ -10,6 +10,7 @@ @Repository public interface LocationRepository extends JpaRepository { + @Query( "select l " + "from Location l " @@ -21,4 +22,5 @@ List findAllByRectangle( @Param("currentLongitude") BigDecimal currentLongitude, @Param("distance") BigDecimal distance ); + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java index bdf269a6e..65e5c9c28 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java @@ -7,4 +7,5 @@ public interface MemberRepository extends JpaRepository { Optional findByEmail(String email); + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java index 0665f0162..febf6fc57 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java @@ -20,4 +20,5 @@ public interface PinRepository extends JpaRepository { void deleteById(@Param("pinId") Long pinId); List findAllByTopicId(Long topicId); + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java index 8b5f5f601..fb47c93f3 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java @@ -14,7 +14,6 @@ import java.util.Collection; import java.util.List; import java.util.NoSuchElementException; -import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -73,7 +72,7 @@ private void validateExist(int idCount, int existCount) { private List duplicateUserPins(List pins, Topic topic) { return pins.stream() .map(original -> original.copy(topic)) - .collect(Collectors.toList()); + .toList(); } public long createMerge(AuthMember member, TopicMergeRequest request) { @@ -99,7 +98,7 @@ public long createMerge(AuthMember member, TopicMergeRequest request) { List original = topics.stream() .map(Topic::getPins) .flatMap(Collection::stream) - .collect(Collectors.toList()); + .toList(); List pins = duplicateUserPins(original, topic); pinRepository.saveAll(pins); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java index c422e8472..d917e61f2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -77,7 +76,7 @@ private List sortTopicsByCounts(Map topicCounts, Aut .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .map(Map.Entry::getKey) .map(TopicResponse::from) - .collect(Collectors.toList()); + .toList(); } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java index c5f0d9b43..72e152953 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java @@ -2,9 +2,6 @@ import com.mapbefine.mapbefine.entity.member.Member; import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Topic; public class MemberFixture { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java index 4bf135738..508548362 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java @@ -4,7 +4,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.FilterType; @@ -19,6 +18,5 @@ type = FilterType.ANNOTATION, value = Service.class ) ) -//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public @interface ServiceTest { } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java index 1ee7f895e..effae9694 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java @@ -1,24 +1,23 @@ package com.mapbefine.mapbefine.controller; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + import com.mapbefine.mapbefine.dto.PinCreateRequest; import com.mapbefine.mapbefine.dto.PinDetailResponse; import com.mapbefine.mapbefine.dto.PinResponse; import com.mapbefine.mapbefine.dto.PinUpdateRequest; import com.mapbefine.mapbefine.service.PinCommandService; import com.mapbefine.mapbefine.service.PinQueryService; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; - class PinControllerTest extends RestDocsIntegration { private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java index 9890a13b3..43cc2dfcb 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java @@ -11,7 +11,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class IntegrationTest { @LocalServerPort - int port; + private int port; @BeforeEach public void setUp() { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java index 478991b54..3fbfb6e6f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java @@ -14,8 +14,9 @@ import com.mapbefine.mapbefine.repository.LocationRepository; import com.mapbefine.mapbefine.repository.MemberRepository; import com.mapbefine.mapbefine.repository.TopicRepository; -import io.restassured.*; -import io.restassured.response.*; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -24,7 +25,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -public class PinIntegrationTest extends IntegrationTest { +class PinIntegrationTest extends IntegrationTest { private static final String AUTHORIZATION = "Authorization"; private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); @@ -32,7 +33,6 @@ public class PinIntegrationTest extends IntegrationTest { private Topic topic; private Location location; private Member member; - private AuthMember authMember; @Autowired private MemberRepository memberRepository; @@ -46,7 +46,6 @@ public class PinIntegrationTest extends IntegrationTest { @BeforeEach void saveTopicAndLocation() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); - authMember = AuthMember.from(member); topic = topicRepository.save(TopicFixture.createByName("PinIntegration 토픽", member)); location = locationRepository.save(LocationFixture.createByCoordinate(37.5152933, 127.1029866)); } @@ -109,7 +108,7 @@ void addIfNotExistDuplicateLocation_Success() { @Test @DisplayName("핀 목록을 조회하면 저장된 Pin의 목록과 200을 반환한다.") - public void findAll_Success() { + void findAll_Success() { // given PinCreateRequest request1 = new PinCreateRequest( topic.getId(), @@ -153,7 +152,7 @@ public void findAll_Success() { @Test @DisplayName("핀 상세 조회를 하면 Pin 정보와 함께 200을 반환한다.") - public void findDetail_Success() { + void findDetail_Success() { // given PinCreateRequest request = new PinCreateRequest( topic.getId(), diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java index d7f256e95..16ab38d98 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java @@ -20,7 +20,6 @@ import io.restassured.response.Response; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -79,7 +78,7 @@ void createNewTopicWithPins_Success() { List pins = pinRepository.findAll(); List pinIds = pins.stream() .map(Pin::getId) - .collect(Collectors.toList()); + .toList(); TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( "준팍의 또간집", @@ -126,7 +125,7 @@ void createMergeTopic_Success() { List topics = topicRepository.findAll(); List topicIds = topics.stream() .map(Topic::getId) - .collect(Collectors.toList()); + .toList(); TopicMergeRequest 송파_데이트코스 = new TopicMergeRequest( "송파 데이트코스", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java index a41e9f41c..e5ef91e82 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java @@ -21,8 +21,10 @@ @DataJpaTest class PinRepositoryTest { - private static final Coordinate DEFAULT_COORDINATE = - new Coordinate(BigDecimal.valueOf(37.5152933), BigDecimal.valueOf(127.1029866)); + private static final Coordinate DEFAULT_COORDINATE = new Coordinate( + BigDecimal.valueOf(37.5152933), + BigDecimal.valueOf(127.1029866) + ); @Autowired private TopicRepository topicRepository; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java index 588c1bf23..55be0b23f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java @@ -2,7 +2,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; import com.mapbefine.mapbefine.MemberFixture; import com.mapbefine.mapbefine.annotation.ServiceTest; From 470fcb5a2c8469fa0963c9565e3ccbb93e423767 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 14:18:17 +0900 Subject: [PATCH 16/88] =?UTF-8?q?refactor:=20..=20=EC=A7=80=EC=86=A1;;^^?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 패키지 재분배 - AUTH 관련 기능 구현 - TopicController 및 LocationController 분리 Co-authored-by: jaeyeon kim --- .../mapbefine/MapbefineApplication.java | 8 +- .../auth/application/AuthService.java | 28 ++++ .../auth => auth/domain}/AuthMember.java | 33 ++-- .../mapbefine/auth/domain/AuthTopic.java | 39 +++++ .../mapbefine/auth/domain/member/Admin.java | 37 +++++ .../mapbefine/auth/domain/member/Guest.java | 38 +++++ .../mapbefine/auth/domain/member/User.java | 53 ++++++ .../mapbefine/auth/dto/AuthInfo.java | 6 + .../AuthorizationExtractor.java | 10 ++ .../BasicAuthorizationExtractor.java | 41 +++++ .../common/GlobalExceptionHandler.java | 7 + .../mapbefine/common/config/AuthConfig.java | 34 ++++ .../mapbefine/common/config/JpaConfig.java | 9 ++ .../mapbefine/common/config/WebConfig.java | 18 +++ .../entity/BaseTimeEntity.java} | 6 +- .../common/interceptor/AuthInterceptor.java | 48 ++++++ .../common/interceptor/LoginRequired.java | 11 ++ .../mapbefine/common/resolver/Auth.java | 11 ++ .../common/resolver/AuthArgumentResolver.java | 63 ++++++++ .../config/MemberArgumentResolver.java | 43 ----- .../config/StringToPermissionConverter.java | 13 -- .../config/StringToPublicityConverter.java | 13 -- .../mapbefine/config/WebMvcConfig.java | 39 ----- .../mapbefine/config/auth/Admin.java | 34 ---- .../mapbefine/config/auth/AuthTopic.java | 20 --- .../mapbefine/config/auth/Guest.java | 39 ----- .../mapbefine/mapbefine/config/auth/User.java | 66 -------- .../mapbefine/dto/TopicFindBestRequest.java | 7 - .../mapbefine/entity/topic/Permission.java | 33 ---- .../mapbefine/entity/topic/Publicity.java | 33 ---- .../application/LocationQueryService.java | 66 ++++++++ .../mapbefine/location/domain/Address.java | 39 +++++ .../pin => location/domain}/Coordinate.java | 19 +-- .../pin => location/domain}/Location.java | 47 +++--- .../domain}/LocationRepository.java | 3 +- .../location/dto/CoordinateRequest.java | 9 ++ .../presentation/LocationController.java | 34 ++++ .../application/MemberCommandService.java | 16 ++ .../application/MemberQueryService.java | 16 ++ .../member => member/domain}/Member.java | 8 +- .../domain}/MemberRepository.java | 5 +- .../domain}/MemberTopicPermission.java | 8 +- .../member => member/domain}/Role.java | 2 +- .../presentation}/MemberController.java | 2 +- .../{entity/pin => pin/Domain}/Pin.java | 80 ++++----- .../{entity/pin => pin/Domain}/PinImage.java | 2 +- .../mapbefine/pin/Domain/PinInfo.java | 64 ++++++++ .../Domain}/PinRepository.java | 3 +- .../application}/PinCommandService.java | 42 +++-- .../application}/PinQueryService.java | 14 +- .../dto/request}/PinCreateRequest.java | 7 +- .../dto/request}/PinUpdateRequest.java | 2 +- .../dto/response}/PinDetailResponse.java | 22 +-- .../dto/response}/PinResponse.java | 10 +- .../presentation}/PinController.java | 22 +-- .../mapbefine/service/TopicQueryService.java | 82 ---------- .../application}/TopicCommandService.java | 152 ++++++++++-------- .../topic/application/TopicQueryService.java | 39 +++++ .../mapbefine/topic/domain/Permission.java | 24 +++ .../mapbefine/topic/domain/Publicity.java | 25 +++ .../mapbefine/topic/domain/Topic.java | 104 ++++++++++++ .../domain/TopicInfo.java} | 79 ++------- .../domain}/TopicRepository.java | 3 +- .../mapbefine/topic/domain/TopicStatus.java | 77 +++++++++ .../dto/request}/TopicCreateRequest.java | 6 +- .../dto/request}/TopicMergeRequest.java | 6 +- .../dto/request}/TopicUpdateRequest.java | 2 +- .../dto/response}/TopicDetailResponse.java | 14 +- .../dto/response}/TopicResponse.java | 12 +- .../presentation}/TopicController.java | 39 ++--- .../mapbefine/mapbefine/LocationFixture.java | 17 -- .../com/mapbefine/mapbefine/PinFixture.java | 18 --- .../IntegrationTest.java | 4 +- .../RestDocsIntegration.java | 2 +- .../{ => common}/annotation/ServiceTest.java | 2 +- .../mapbefine/location/LocationFixture.java | 36 +++++ .../LocationQueryServiceTest.java} | 73 +++------ .../domain}/CoordinateTest.java | 23 ++- .../domain}/LocationRepositoryTest.java | 26 +-- .../presentation/LocationControllerTest.java | 50 ++++++ .../mapbefine/{ => member}/MemberFixture.java | 6 +- .../mapbefine/mapbefine/pin/PinFixture.java | 20 +++ .../PinIntegrationTest.java | 56 +++---- .../application}/PinCommandServiceTest.java | 93 ++++++----- .../application}/PinQueryServiceTest.java | 54 ++++--- .../domain}/PinRepositoryTest.java | 41 +++-- .../{entity => pin/domain}/PinTest.java | 51 +++--- .../presentation}/PinControllerTest.java | 23 +-- .../mapbefine/{ => topic}/TopicFixture.java | 10 +- .../TopicIntegrationTest.java | 34 ++-- .../application}/TopicCommandServiceTest.java | 42 ++--- .../application/TopicQueryServiceTest.java | 86 ++++++++++ .../presentation}/TopicControllerTest.java | 52 ++---- 93 files changed, 1751 insertions(+), 1114 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java rename backend/src/main/java/com/mapbefine/mapbefine/{config/auth => auth/domain}/AuthMember.java (64%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/dto/AuthInfo.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/AuthorizationExtractor.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/GlobalExceptionHandler.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/config/AuthConfig.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/config/JpaConfig.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/config/WebConfig.java rename backend/src/main/java/com/mapbefine/mapbefine/{entity/BaseEntity.java => common/entity/BaseTimeEntity.java} (87%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/LoginRequired.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/dto/TopicFindBestRequest.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/location/domain/Address.java rename backend/src/main/java/com/mapbefine/mapbefine/{entity/pin => location/domain}/Coordinate.java (89%) rename backend/src/main/java/com/mapbefine/mapbefine/{entity/pin => location/domain}/Location.java (59%) rename backend/src/main/java/com/mapbefine/mapbefine/{repository => location/domain}/LocationRepository.java (90%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java rename backend/src/main/java/com/mapbefine/mapbefine/{entity/member => member/domain}/Member.java (89%) rename backend/src/main/java/com/mapbefine/mapbefine/{repository => member/domain}/MemberRepository.java (68%) rename backend/src/main/java/com/mapbefine/mapbefine/{entity/member => member/domain}/MemberTopicPermission.java (78%) rename backend/src/main/java/com/mapbefine/mapbefine/{entity/member => member/domain}/Role.java (87%) rename backend/src/main/java/com/mapbefine/mapbefine/{controller => member/presentation}/MemberController.java (79%) rename backend/src/main/java/com/mapbefine/mapbefine/{entity/pin => pin/Domain}/Pin.java (55%) rename backend/src/main/java/com/mapbefine/mapbefine/{entity/pin => pin/Domain}/PinImage.java (95%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java rename backend/src/main/java/com/mapbefine/mapbefine/{repository => pin/Domain}/PinRepository.java (89%) rename backend/src/main/java/com/mapbefine/mapbefine/{service => pin/application}/PinCommandService.java (71%) rename backend/src/main/java/com/mapbefine/mapbefine/{service => pin/application}/PinQueryService.java (72%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => pin/dto/request}/PinCreateRequest.java (61%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => pin/dto/request}/PinUpdateRequest.java (74%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => pin/dto/response}/PinDetailResponse.java (58%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => pin/dto/response}/PinResponse.java (61%) rename backend/src/main/java/com/mapbefine/mapbefine/{controller => pin/presentation}/PinController.java (79%) delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java rename backend/src/main/java/com/mapbefine/mapbefine/{service => topic/application}/TopicCommandService.java (55%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Permission.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Publicity.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java rename backend/src/main/java/com/mapbefine/mapbefine/{entity/topic/Topic.java => topic/domain/TopicInfo.java} (53%) rename backend/src/main/java/com/mapbefine/mapbefine/{repository => topic/domain}/TopicRepository.java (84%) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java rename backend/src/main/java/com/mapbefine/mapbefine/{dto => topic/dto/request}/TopicCreateRequest.java (57%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => topic/dto/request}/TopicMergeRequest.java (57%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => topic/dto/request}/TopicUpdateRequest.java (68%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => topic/dto/response}/TopicDetailResponse.java (62%) rename backend/src/main/java/com/mapbefine/mapbefine/{dto => topic/dto/response}/TopicResponse.java (57%) rename backend/src/main/java/com/mapbefine/mapbefine/{controller => topic/presentation}/TopicController.java (73%) delete mode 100644 backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java delete mode 100644 backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java rename backend/src/test/java/com/mapbefine/mapbefine/{integration => common}/IntegrationTest.java (88%) rename backend/src/test/java/com/mapbefine/mapbefine/{controller => common}/RestDocsIntegration.java (97%) rename backend/src/test/java/com/mapbefine/mapbefine/{ => common}/annotation/ServiceTest.java (93%) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java rename backend/src/test/java/com/mapbefine/mapbefine/{service/TopicQueryServiceTest.java => location/application/LocationQueryServiceTest.java} (51%) rename backend/src/test/java/com/mapbefine/mapbefine/{entity => location/domain}/CoordinateTest.java (73%) rename backend/src/test/java/com/mapbefine/mapbefine/{repository => location/domain}/LocationRepositoryTest.java (85%) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java rename backend/src/test/java/com/mapbefine/mapbefine/{ => member}/MemberFixture.java (62%) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java rename backend/src/test/java/com/mapbefine/mapbefine/{integration => pin}/PinIntegrationTest.java (79%) rename backend/src/test/java/com/mapbefine/mapbefine/{service => pin/application}/PinCommandServiceTest.java (82%) rename backend/src/test/java/com/mapbefine/mapbefine/{service => pin/application}/PinQueryServiceTest.java (74%) rename backend/src/test/java/com/mapbefine/mapbefine/{repository => pin/domain}/PinRepositoryTest.java (71%) rename backend/src/test/java/com/mapbefine/mapbefine/{entity => pin/domain}/PinTest.java (74%) rename backend/src/test/java/com/mapbefine/mapbefine/{controller => pin/presentation}/PinControllerTest.java (85%) rename backend/src/test/java/com/mapbefine/mapbefine/{ => topic}/TopicFixture.java (55%) rename backend/src/test/java/com/mapbefine/mapbefine/{integration => topic}/TopicIntegrationTest.java (91%) rename backend/src/test/java/com/mapbefine/mapbefine/{service => topic/application}/TopicCommandServiceTest.java (62%) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java rename backend/src/test/java/com/mapbefine/mapbefine/{controller => topic/presentation}/TopicControllerTest.java (74%) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/MapbefineApplication.java b/backend/src/main/java/com/mapbefine/mapbefine/MapbefineApplication.java index 0b456f61d..5f934815f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/MapbefineApplication.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/MapbefineApplication.java @@ -2,14 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication -@EnableJpaAuditing public class MapbefineApplication { - public static void main(String[] args) { - SpringApplication.run(MapbefineApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(MapbefineApplication.class, args); + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java new file mode 100644 index 000000000..b1bade36d --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java @@ -0,0 +1,28 @@ +package com.mapbefine.mapbefine.auth.application; + +import com.mapbefine.mapbefine.auth.dto.AuthInfo; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +public class AuthService { + + private final MemberRepository memberRepository; + + public AuthService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + public boolean isMember(AuthInfo authInfo) { + return memberRepository.existsByEmail(authInfo.email()); + } + + public Member checkLoginMember(AuthInfo authInfo) { + return memberRepository.findByEmail(authInfo.email()) + .orElseThrow(() -> new IllegalArgumentException("해당 유저가 존재하지 않습니다.")); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java similarity index 64% rename from backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java rename to backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java index 145d32256..6647865e6 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java @@ -1,13 +1,13 @@ -package com.mapbefine.mapbefine.config.auth; - -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.MemberTopicPermission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; +package com.mapbefine.mapbefine.auth.domain; + +import com.mapbefine.mapbefine.auth.domain.member.Admin; +import com.mapbefine.mapbefine.auth.domain.member.Guest; +import com.mapbefine.mapbefine.auth.domain.member.User; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import com.mapbefine.mapbefine.topic.domain.Topic; import java.util.List; -import lombok.Getter; -@Getter public abstract class AuthMember { protected Long memberId; @@ -53,20 +53,13 @@ private static List getCreatedTopics(Member member) { public abstract boolean canRead(AuthTopic authTopic); - public abstract void canDelete(AuthTopic authTopic); - - public abstract void canTopicCreate(); + public abstract boolean canDelete(AuthTopic authTopic); - public abstract void canTopicUpdate(AuthTopic authTopic); + public abstract boolean canTopicUpdate(AuthTopic authTopic); - public abstract void canPinCreateOrUpdate(AuthTopic authTopic); + public abstract boolean canPinCreateOrUpdate(AuthTopic authTopic); - protected boolean isPublic(Publicity publicity) { - return publicity == Publicity.PUBLIC; + public Long getMemberId() { + return memberId; } - - protected boolean isPrivate(Publicity publicity) { - return publicity == Publicity.PRIVATE; - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java new file mode 100644 index 000000000..572cec631 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java @@ -0,0 +1,39 @@ +package com.mapbefine.mapbefine.auth.domain; + +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicStatus; + +public class AuthTopic { + + private final Long topicId; + private final TopicStatus topicStatus; + + private AuthTopic(Long topicId, TopicStatus topicStatus) { + this.topicId = topicId; + this.topicStatus = topicStatus; + } + + public static AuthTopic from(Topic topic) { + return new AuthTopic(topic.getId(), topic.getTopicStatus()); + } + + public boolean isPublic() { + return topicStatus.isPublic(); + } + + public boolean isPrivate() { + return topicStatus.isPrivate(); + } + + public boolean isAllMembers() { + return topicStatus.isAllMembers(); + } + + public boolean isGroupOnly() { + return topicStatus.isGroupOnly(); + } + + public Long getTopicId() { + return topicId; + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java new file mode 100644 index 000000000..1ef7a8812 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java @@ -0,0 +1,37 @@ +package com.mapbefine.mapbefine.auth.domain.member; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import java.util.Collections; + +public class Admin extends AuthMember { + + public Admin(Long memberId) { + super( + memberId, + Collections.emptyList(), + Collections.emptyList() + ); + } + + @Override + public boolean canRead(AuthTopic authTopic) { + return true; + } + + @Override + public boolean canDelete(AuthTopic authTopic) { + return true; + } + + @Override + public boolean canTopicUpdate(AuthTopic authTopic) { + return true; + } + + @Override + public boolean canPinCreateOrUpdate(AuthTopic authTopic) { + return true; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java new file mode 100644 index 000000000..bbb124ef1 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java @@ -0,0 +1,38 @@ +package com.mapbefine.mapbefine.auth.domain.member; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import java.util.Collections; + +public class Guest extends AuthMember { + + + public Guest() { + super( + null, + Collections.emptyList(), + Collections.emptyList() + ); + } + + @Override + public boolean canRead(AuthTopic authTopic) { + return authTopic.isPublic(); + } + + @Override + public boolean canDelete(AuthTopic authTopic) { + return false; + } + + @Override + public boolean canTopicUpdate(AuthTopic authTopic) { + return false; + } + + @Override + public boolean canPinCreateOrUpdate(AuthTopic authTopic) { + return false; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java new file mode 100644 index 000000000..1c284aa68 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java @@ -0,0 +1,53 @@ +package com.mapbefine.mapbefine.auth.domain.member; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import java.util.List; + +public class User extends AuthMember { + + public User( + Long memberId, + List createdTopic, + List topicsWithPermission + ) { + super( + memberId, + createdTopic, + topicsWithPermission + ); + } + + @Override + public boolean canRead(AuthTopic authTopic) { + return authTopic.isPublic() || isGroup(authTopic.getTopicId()); + } + + @Override + public boolean canDelete(AuthTopic authTopic) { + return authTopic.isPrivate() && isCreator(authTopic.getTopicId()); + } + + @Override + public boolean canTopicUpdate(AuthTopic authTopic) { + return isCreator(authTopic.getTopicId()); + } + + @Override + public boolean canPinCreateOrUpdate(AuthTopic authTopic) { + return authTopic.isAllMembers() || hasPermission(authTopic.getTopicId()); + } + + private boolean isCreator(Long topicId) { + return createdTopic.contains(topicId); + } + + private boolean isGroup(Long topicId) { + return isCreator(topicId) || hasPermission(topicId); + } + + private boolean hasPermission(Long topicId) { + return topicsWithPermission.contains(topicId); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/dto/AuthInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/dto/AuthInfo.java new file mode 100644 index 000000000..c6f6ab341 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/dto/AuthInfo.java @@ -0,0 +1,6 @@ +package com.mapbefine.mapbefine.auth.dto; + +public record AuthInfo( + String email +) { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/AuthorizationExtractor.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/AuthorizationExtractor.java new file mode 100644 index 000000000..98c9b27b8 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/AuthorizationExtractor.java @@ -0,0 +1,10 @@ +package com.mapbefine.mapbefine.auth.infrastructure; + + +import jakarta.servlet.http.HttpServletRequest; + +public interface AuthorizationExtractor { + + T extract(HttpServletRequest request); + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java new file mode 100644 index 000000000..896af86bf --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java @@ -0,0 +1,41 @@ +package com.mapbefine.mapbefine.auth.infrastructure; + + +import static org.springframework.http.HttpHeaders.AUTHORIZATION; +import static org.springframework.util.StringUtils.hasText; + +import com.mapbefine.mapbefine.auth.dto.AuthInfo; +import jakarta.servlet.http.HttpServletRequest; +import org.apache.tomcat.util.codec.binary.Base64; +import org.springframework.stereotype.Component; + +@Component +public class BasicAuthorizationExtractor implements AuthorizationExtractor { + + private static final String BASIC_TYPE = "Basic"; + + @Override + public AuthInfo extract(final HttpServletRequest request) { + String authorization = request.getHeader(AUTHORIZATION); + validateAuthorization(authorization); + + return new AuthInfo(decode(authorization)); + } + + private void validateAuthorization(final String authorization) { + if (!hasText(authorization)) { + throw new IllegalArgumentException("로그인 유저가 아닙니다"); + } + if (!authorization.toLowerCase().startsWith(BASIC_TYPE.toLowerCase())) { + throw new IllegalArgumentException("잘못된 인증방법입니다."); + } + } + + private String decode(String authorization) { + String authHeaderValue = authorization.substring(BASIC_TYPE.length()).trim(); + byte[] decodedBytes = Base64.decodeBase64(authHeaderValue); + + return new String(decodedBytes); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/GlobalExceptionHandler.java b/backend/src/main/java/com/mapbefine/mapbefine/common/GlobalExceptionHandler.java new file mode 100644 index 000000000..a3e5da0ee --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/GlobalExceptionHandler.java @@ -0,0 +1,7 @@ +package com.mapbefine.mapbefine.common; + +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/config/AuthConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/common/config/AuthConfig.java new file mode 100644 index 000000000..02cb0062f --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/config/AuthConfig.java @@ -0,0 +1,34 @@ +package com.mapbefine.mapbefine.common.config; + +import com.mapbefine.mapbefine.common.interceptor.AuthInterceptor; +import com.mapbefine.mapbefine.common.resolver.AuthArgumentResolver; +import java.util.List; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private final AuthInterceptor authInterceptor; + private final AuthArgumentResolver authArgumentResolver; + + public AuthConfig( + AuthInterceptor authInterceptor, + AuthArgumentResolver authArgumentResolver + ) { + this.authInterceptor = authInterceptor; + this.authArgumentResolver = authArgumentResolver; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(authInterceptor); + } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(authArgumentResolver); + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/config/JpaConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/common/config/JpaConfig.java new file mode 100644 index 000000000..a14788c2c --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/config/JpaConfig.java @@ -0,0 +1,9 @@ +package com.mapbefine.mapbefine.common.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@Configuration +@EnableJpaAuditing +public class JpaConfig { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/config/WebConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/common/config/WebConfig.java new file mode 100644 index 000000000..1e0a70726 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/config/WebConfig.java @@ -0,0 +1,18 @@ +package com.mapbefine.mapbefine.common.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedMethods("*") + .exposedHeaders("Location"); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/BaseEntity.java b/backend/src/main/java/com/mapbefine/mapbefine/common/entity/BaseTimeEntity.java similarity index 87% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/BaseEntity.java rename to backend/src/main/java/com/mapbefine/mapbefine/common/entity/BaseTimeEntity.java index 6d48be7ca..f8a145e23 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/BaseEntity.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/entity/BaseTimeEntity.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.common.entity; import static lombok.AccessLevel.PROTECTED; @@ -15,14 +15,14 @@ @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = PROTECTED) @Getter -public abstract class BaseEntity { +public abstract class BaseTimeEntity { @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; - protected BaseEntity( + protected BaseTimeEntity( LocalDateTime createdAt, LocalDateTime updatedAt ) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java new file mode 100644 index 000000000..cd12c1a6a --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java @@ -0,0 +1,48 @@ +package com.mapbefine.mapbefine.common.interceptor; + +import com.mapbefine.mapbefine.auth.application.AuthService; +import com.mapbefine.mapbefine.auth.dto.AuthInfo; +import com.mapbefine.mapbefine.auth.infrastructure.AuthorizationExtractor; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Objects; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class AuthInterceptor implements HandlerInterceptor { + + private final AuthorizationExtractor authorizationExtractor; + private final AuthService authService; + + public AuthInterceptor(AuthorizationExtractor authorizationExtractor, AuthService authService) { + this.authorizationExtractor = authorizationExtractor; + this.authService = authService; + } + + @Override + public boolean preHandle( + HttpServletRequest request, + HttpServletResponse response, + Object handler + ) throws Exception { + if (isLoginRequired((HandlerMethod) handler)) { + return isMember(request); + } + return true; + } + + private boolean isLoginRequired(HandlerMethod handlerMethod) { + LoginRequired loginRequired = handlerMethod.getMethodAnnotation(LoginRequired.class); + + return !Objects.isNull(loginRequired); + } + + private boolean isMember(HttpServletRequest request) { + AuthInfo authInfo = authorizationExtractor.extract(request); + + return authService.isMember(authInfo); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/LoginRequired.java b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/LoginRequired.java new file mode 100644 index 000000000..7f0adeb23 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/LoginRequired.java @@ -0,0 +1,11 @@ +package com.mapbefine.mapbefine.common.interceptor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface LoginRequired { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java new file mode 100644 index 000000000..2b1ceaaf5 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java @@ -0,0 +1,11 @@ +package com.mapbefine.mapbefine.common.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface Auth { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java new file mode 100644 index 000000000..17abfd406 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java @@ -0,0 +1,63 @@ +package com.mapbefine.mapbefine.common.resolver; + +import com.mapbefine.mapbefine.auth.application.AuthService; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.dto.AuthInfo; +import com.mapbefine.mapbefine.auth.infrastructure.AuthorizationExtractor; +import com.mapbefine.mapbefine.member.domain.Member; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +@Component +public class AuthArgumentResolver implements HandlerMethodArgumentResolver { + + private final AuthorizationExtractor authorizationExtractor; + private final AuthService authService; + + public AuthArgumentResolver( + AuthorizationExtractor authorizationExtractor, + AuthService authService + ) { + this.authorizationExtractor = authorizationExtractor; + this.authService = authService; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + boolean isAuthMemberAnnotation = parameter.hasParameterAnnotation(Auth.class); + boolean isAuthMemberClass = AuthMember.class.equals(parameter.getParameterType()); + + return isAuthMemberAnnotation && isAuthMemberClass; + } + + @Override + public Object resolveArgument( + MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory + ) throws Exception { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + validateRequest(request); + + return createAuthMember(request); + } + + private void validateRequest(HttpServletRequest request) { + if (request == null) { + throw new IllegalArgumentException("로그인 유저가 아닙니다"); + } + } + + private AuthMember createAuthMember(HttpServletRequest request) { + AuthInfo authInfo = authorizationExtractor.extract(request); + Member member = authService.checkLoginMember(authInfo); + + return AuthMember.from(member); + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java deleted file mode 100644 index f2b1ce82e..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/MemberArgumentResolver.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.mapbefine.mapbefine.config; - -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.repository.MemberRepository; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.core.MethodParameter; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -public class MemberArgumentResolver implements HandlerMethodArgumentResolver { - - private static final String AUTHORIZATION = "Authorization"; - - private final MemberRepository memberRepository; - - public MemberArgumentResolver(MemberRepository memberRepository) { - this.memberRepository = memberRepository; - } - - @Override - public boolean supportsParameter(MethodParameter parameter) { - return parameter.getParameterType() - .equals(AuthMember.class); - } - - @Override - public Object resolveArgument( - MethodParameter parameter, - ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, - WebDataBinderFactory binderFactory - ) throws Exception { - HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); - String memberEmail = request.getHeader(AUTHORIZATION); - Member member = memberRepository.findByEmail(memberEmail) - .orElse(null); - - return AuthMember.from(member); - } -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java deleted file mode 100644 index 07bdb7ab7..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPermissionConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mapbefine.mapbefine.config; - -import com.mapbefine.mapbefine.entity.topic.Permission; -import org.springframework.core.convert.converter.Converter; - -public class StringToPermissionConverter implements Converter { - - @Override - public Permission convert(String input) { - return Permission.from(input); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java b/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java deleted file mode 100644 index 6d61d5481..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/StringToPublicityConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mapbefine.mapbefine.config; - -import com.mapbefine.mapbefine.entity.topic.Publicity; -import org.springframework.core.convert.converter.Converter; - -public class StringToPublicityConverter implements Converter { - - @Override - public Publicity convert(String input) { - return Publicity.from(input); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java b/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java deleted file mode 100644 index 754dab2a8..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/WebMvcConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mapbefine.mapbefine.config; - -import com.mapbefine.mapbefine.repository.MemberRepository; -import java.util.List; -import org.springframework.context.annotation.Configuration; -import org.springframework.format.FormatterRegistry; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@Configuration -public class WebMvcConfig implements WebMvcConfigurer { - - private final MemberRepository memberRepository; - - public WebMvcConfig(MemberRepository memberRepository) { - this.memberRepository = memberRepository; - } - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins("http://localhost:3000") - .allowedMethods("*") - .exposedHeaders("Location"); - } - - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(new MemberArgumentResolver(memberRepository)); - } - - @Override - public void addFormatters(FormatterRegistry registry) { - registry.addConverter(new StringToPermissionConverter()); - registry.addConverter(new StringToPublicityConverter()); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java deleted file mode 100644 index 3473acdf0..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Admin.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.mapbefine.mapbefine.config.auth; - -public class Admin extends AuthMember { - - public Admin(Long memberId) { // TODO : 준팍 여기에 memberId 는 넣어야지 찾을 수 있더라고요 - super( - memberId, - null, - null - ); - } - - @Override - public boolean canRead(AuthTopic authTopic) { - return true; - } - - @Override - public void canDelete(AuthTopic authTopic) { - } - - @Override - public void canTopicCreate() { - } - - @Override - public void canTopicUpdate(AuthTopic authTopic) { - } - - @Override - public void canPinCreateOrUpdate(AuthTopic authTopic) { - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java deleted file mode 100644 index 8ff62e9e7..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/AuthTopic.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.mapbefine.mapbefine.config.auth; - -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; - -public record AuthTopic( - Long topicId, - Publicity publicity, - Permission permission - -) { - public static AuthTopic from(Topic topic) { - return new AuthTopic( - topic.getId(), - topic.getPublicity(), - topic.getPermission() - ); - } -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java deleted file mode 100644 index da43ff6bd..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/Guest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mapbefine.mapbefine.config.auth; - -public class Guest extends AuthMember { - - - public Guest() { - super( - null, - null, - null - ); - } - - @Override - public boolean canRead(AuthTopic authTopic) { - return isPublic(authTopic.publicity()); - } - - @Override - public void canDelete(AuthTopic authTopic) { - throw new IllegalArgumentException("권한이 없습니다."); - } - - @Override - public void canTopicCreate() { - throw new IllegalArgumentException("권한이 없습니다."); - } - - @Override - public void canTopicUpdate(AuthTopic authTopic) { - throw new IllegalArgumentException("권한이 없습니다."); - } - - @Override - public void canPinCreateOrUpdate(AuthTopic authTopic) { - throw new IllegalArgumentException("권한이 없습니다."); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java b/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java deleted file mode 100644 index c4e77a4ca..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/config/auth/User.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.mapbefine.mapbefine.config.auth; - -import com.mapbefine.mapbefine.entity.topic.Permission; -import java.util.List; - -public class User extends AuthMember { - - public User( - Long memberId, - List createdTopic, - List topicsWithPermission - ) { - super( - memberId, - createdTopic, - topicsWithPermission - ); - } - - @Override - public boolean canRead(AuthTopic authTopic) { - return isPublic(authTopic.publicity()) || isGroup(authTopic.topicId()); - } - - @Override - public void canDelete(AuthTopic authTopic) { - if (isPrivate(authTopic.publicity()) && isCreator(authTopic.topicId())) { - throw new IllegalArgumentException("권한이 없습니다."); - } - } - - @Override - public void canTopicCreate() { // TODO : 이 부분은 로직을 작성할 필요 없어, @Override 없이 상속받은 메서드를 그냥 구현 없이 사용해도 될 것 같네용 - } - - @Override - public void canTopicUpdate(AuthTopic authTopic) { - if (isCreator(authTopic.topicId())) { - throw new IllegalArgumentException("권한이 없습니다."); - } - } - - @Override - public void canPinCreateOrUpdate(AuthTopic authTopic) { - if (isAllMembers(authTopic) || hasPermission(authTopic.topicId())) { - throw new IllegalArgumentException("권한이 없습니다."); - } - } - - private boolean isAllMembers(final AuthTopic authTopic) { - return authTopic.permission() == Permission.ALL_MEMBERS; - } - - private boolean isGroup(Long topicId) { - return isCreator(topicId) || hasPermission(topicId); - } - - private boolean hasPermission(Long topicId) { - return topicsWithPermission.contains(topicId); - } - - private boolean isCreator(Long topicId) { - return createdTopic.contains(topicId); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicFindBestRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicFindBestRequest.java deleted file mode 100644 index 4f35b94b7..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicFindBestRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.mapbefine.mapbefine.dto; - -public record TopicFindBestRequest( - String latitude, - String longitude -) { -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java deleted file mode 100644 index fe77ddb14..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Permission.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.mapbefine.mapbefine.entity.topic; - -import com.fasterxml.jackson.annotation.JsonCreator; -import java.util.Arrays; -import java.util.NoSuchElementException; -import lombok.Getter; - -@Getter -public enum Permission { - - ALL_MEMBERS("모든 회원"), - GROUP_ONLY("소속 회원"); - - private final String title; - - Permission(String title) { - this.title = title; - } - - @JsonCreator - public static Permission from(String input) { - return Arrays.stream(values()) - .filter(permission -> isSameName(input, permission)) - .findFirst() - .orElseThrow(NoSuchElementException::new); - } - - private static boolean isSameName(String input, Permission permission) { - return permission.name() - .equalsIgnoreCase(input); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java b/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java deleted file mode 100644 index 842f145d4..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Publicity.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.mapbefine.mapbefine.entity.topic; - -import com.fasterxml.jackson.annotation.JsonCreator; -import java.util.Arrays; -import java.util.NoSuchElementException; -import lombok.Getter; - -@Getter -public enum Publicity { - - PUBLIC("같이 볼 지도"), - PRIVATE("혼자 볼 지도"); - - private final String title; - - Publicity(String title) { - this.title = title; - } - - @JsonCreator - public static Publicity from(String input) { - return Arrays.stream(values()) - .filter(publicity -> isSameName(input, publicity)) - .findFirst() - .orElseThrow(NoSuchElementException::new); - } - - private static boolean isSameName(String input, Publicity publicity) { - return publicity.name() - .equalsIgnoreCase(input); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java new file mode 100644 index 000000000..49fa84294 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java @@ -0,0 +1,66 @@ +package com.mapbefine.mapbefine.location.application; + +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.location.dto.CoordinateRequest; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +public class LocationQueryService { + + private final LocationRepository locationRepository; + + public LocationQueryService(LocationRepository locationRepository) { + this.locationRepository = locationRepository; + } + + + public List findBests(AuthMember member, CoordinateRequest request) { + List locations = findLocationsInRectangle(request); + Map topicCounts = countTopicsInLocations(locations); + + return sortTopicsByCounts(topicCounts, member); + } + + private List findLocationsInRectangle(CoordinateRequest request) { + BigDecimal distance = BigDecimal.valueOf(0.03); + return locationRepository.findAllByRectangle( + request.latitude(), + request.longitude(), + distance + ); + } + + private Map countTopicsInLocations(List locations) { + return locations.stream() + .map(Location::getPins) + .flatMap(Collection::stream) + .collect(groupingBy(Pin::getTopic, counting())); + } + + private List sortTopicsByCounts(Map topicCounts, AuthMember member) { + return topicCounts.entrySet().stream() + .filter(topicEntry -> member.canRead(AuthTopic.from(topicEntry.getKey()))) // TODO : 볼 수 있는 토픽만 걸러내는 과정 + .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) + .map(Map.Entry::getKey) + .map(TopicResponse::from) + .toList(); + } + + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Address.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Address.java new file mode 100644 index 000000000..2764dc74d --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Address.java @@ -0,0 +1,39 @@ +package com.mapbefine.mapbefine.location.domain; + + +import static lombok.AccessLevel.PROTECTED; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = PROTECTED) +@Getter +public class Address { + + @Column(nullable = false) + private String parcelBaseAddress; + + @Column(nullable = false) + private String roadBaseAddress; + + @Column(nullable = false) + private String legalDongCode; + + public Address( + String parcelBaseAddress, + String roadBaseAddress, + String legalDongCode + ) { + this.parcelBaseAddress = parcelBaseAddress; + this.roadBaseAddress = roadBaseAddress; + this.legalDongCode = legalDongCode; + } + + public boolean isSameAddress(String otherAddress) { + return roadBaseAddress.equals(otherAddress) || parcelBaseAddress.equals(otherAddress); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Coordinate.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java similarity index 89% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Coordinate.java rename to backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java index 8d2721823..16a8509f2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Coordinate.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.entity.pin; +package com.mapbefine.mapbefine.location.domain; import static lombok.AccessLevel.PROTECTED; @@ -30,27 +30,24 @@ public class Coordinate { @Column(precision = 18, scale = 15) private BigDecimal longitude; - public Coordinate(BigDecimal latitude, BigDecimal longitude) { - validateRange(latitude, longitude); - + private Coordinate(BigDecimal latitude, BigDecimal longitude) { this.latitude = latitude; this.longitude = longitude; } - public static Coordinate from(String latitude, String longitude) { - return new Coordinate( - new BigDecimal(latitude), - new BigDecimal(longitude) - ); + public static Coordinate of(BigDecimal latitude, BigDecimal longitude) { + validateRange(latitude, longitude); + + return new Coordinate(latitude, longitude); } - private void validateRange(BigDecimal latitude, BigDecimal longitude) { + private static void validateRange(BigDecimal latitude, BigDecimal longitude) { if (isNotInRange(latitude, longitude)) { throw new IllegalArgumentException("한국 내의 좌표만 입력해주세요."); } } - private boolean isNotInRange(BigDecimal latitude, BigDecimal longitude) { + private static boolean isNotInRange(BigDecimal latitude, BigDecimal longitude) { return LATITUDE_LOWER_BOUND.compareTo(latitude) > 0 || LATITUDE_UPPER_BOUND.compareTo(latitude) < 0 || LONGITUDE_LOWER_BOUND.compareTo(longitude) > 0 || diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java similarity index 59% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java rename to backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java index 02c94dc7a..a1d2a7183 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Location.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java @@ -1,9 +1,9 @@ -package com.mapbefine.mapbefine.entity.pin; +package com.mapbefine.mapbefine.location.domain; import static lombok.AccessLevel.PROTECTED; -import com.mapbefine.mapbefine.entity.BaseEntity; -import jakarta.persistence.Column; +import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; +import com.mapbefine.mapbefine.pin.Domain.Pin; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -19,37 +19,44 @@ @Entity @NoArgsConstructor(access = PROTECTED) @Getter -public class Location extends BaseEntity { +public class Location extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) - private String parcelBaseAddress; - - @Column(nullable = false) - private String roadBaseAddress; + @Embedded + private Address address; @Embedded private Coordinate coordinate; - @Column(nullable = false) - private String legalDongCode; - @OneToMany(mappedBy = "location") private List pins = new ArrayList<>(); - public Location( + public Location(Address address, Coordinate coordinate) { + this.address = address; + this.coordinate = coordinate; + } + + public static Location of( String parcelBaseAddress, String roadBaseAddress, - Coordinate coordinate, - String legalDongCode + String legalDongCode, + BigDecimal latitude, + BigDecimal longitude ) { - this.parcelBaseAddress = parcelBaseAddress; - this.roadBaseAddress = roadBaseAddress; - this.coordinate = coordinate; - this.legalDongCode = legalDongCode; + return new Location( + new Address( + parcelBaseAddress, + roadBaseAddress, + legalDongCode + ), + Coordinate.of( + latitude, + longitude + ) + ); } public void addPin(Pin pin) { @@ -61,7 +68,7 @@ public boolean isDuplicateCoordinate(Coordinate otherCoordinate) { } public boolean isSameAddress(String otherAddress) { - return roadBaseAddress.equals(otherAddress); + return address.isSameAddress(otherAddress); } public BigDecimal getLatitude() { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java similarity index 90% rename from backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java rename to backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java index 5c7ddbf17..d22dd9c4b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/LocationRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java @@ -1,6 +1,5 @@ -package com.mapbefine.mapbefine.repository; +package com.mapbefine.mapbefine.location.domain; -import com.mapbefine.mapbefine.entity.pin.Location; import java.math.BigDecimal; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java new file mode 100644 index 000000000..8bb3f2a87 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java @@ -0,0 +1,9 @@ +package com.mapbefine.mapbefine.location.dto; + +import java.math.BigDecimal; + +public record CoordinateRequest( + BigDecimal latitude, + BigDecimal longitude +) { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java b/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java new file mode 100644 index 000000000..9ec96351e --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java @@ -0,0 +1,34 @@ +package com.mapbefine.mapbefine.location.presentation; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.location.application.LocationQueryService; +import com.mapbefine.mapbefine.location.dto.CoordinateRequest; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; +import java.util.List; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/Location") +public class LocationController { + + private final LocationQueryService locationQueryService; + + public LocationController(LocationQueryService locationQueryService) { + this.locationQueryService = locationQueryService; + } + + @GetMapping("/best") + public ResponseEntity> findBests( + AuthMember member, + @RequestBody CoordinateRequest request + ) { + List responses = locationQueryService.findBests(member, request); + + return ResponseEntity.ok(responses); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java new file mode 100644 index 000000000..a8b0cecc8 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -0,0 +1,16 @@ +package com.mapbefine.mapbefine.member.application; + +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class MemberCommandService { + + private final MemberRepository memberRepository; + + public MemberCommandService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java new file mode 100644 index 000000000..eb27532de --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -0,0 +1,16 @@ +package com.mapbefine.mapbefine.member.application; + +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +public class MemberQueryService { + + private final MemberRepository memberRepository; + + public MemberQueryService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java similarity index 89% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java rename to backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index efe0b4247..697c6fc9d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -1,9 +1,9 @@ -package com.mapbefine.mapbefine.entity.member; +package com.mapbefine.mapbefine.member.domain; import static lombok.AccessLevel.PROTECTED; -import com.mapbefine.mapbefine.entity.BaseEntity; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; +import com.mapbefine.mapbefine.topic.domain.Topic; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -20,7 +20,7 @@ @Entity @NoArgsConstructor(access = PROTECTED) @Getter -public class Member extends BaseEntity { +public class Member extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java similarity index 68% rename from backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java rename to backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index 65e5c9c28..a09fbfc27 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -1,6 +1,5 @@ -package com.mapbefine.mapbefine.repository; +package com.mapbefine.mapbefine.member.domain; -import com.mapbefine.mapbefine.entity.member.Member; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; @@ -8,4 +7,6 @@ public interface MemberRepository extends JpaRepository { Optional findByEmail(String email); + boolean existsByEmail(String email); + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/MemberTopicPermission.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java similarity index 78% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/member/MemberTopicPermission.java rename to backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java index 2b8bbc12f..6d1cf8297 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/MemberTopicPermission.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java @@ -1,9 +1,9 @@ -package com.mapbefine.mapbefine.entity.member; +package com.mapbefine.mapbefine.member.domain; import static lombok.AccessLevel.PROTECTED; -import com.mapbefine.mapbefine.entity.BaseEntity; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; +import com.mapbefine.mapbefine.topic.domain.Topic; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -16,7 +16,7 @@ @Entity @NoArgsConstructor(access = PROTECTED) @Getter -public class MemberTopicPermission extends BaseEntity { +public class MemberTopicPermission extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Role.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java similarity index 87% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/member/Role.java rename to backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java index 0f75f4196..abf162920 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/member/Role.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.entity.member; +package com.mapbefine.mapbefine.member.domain; import lombok.Getter; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java similarity index 79% rename from backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java rename to backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 485c5f5ac..10e0ec0c7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.controller; +package com.mapbefine.mapbefine.member.presentation; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java similarity index 55% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java index 926a8a0df..7218d3615 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java @@ -1,17 +1,19 @@ -package com.mapbefine.mapbefine.entity.pin; +package com.mapbefine.mapbefine.pin.Domain; import static lombok.AccessLevel.PROTECTED; -import com.mapbefine.mapbefine.entity.BaseEntity; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.topic.domain.Topic; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; -import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import java.math.BigDecimal; @@ -24,7 +26,7 @@ @Entity @NoArgsConstructor(access = PROTECTED) @Getter -public class Pin extends BaseEntity { +public class Pin extends BaseTimeEntity { private static final int MAX_DESCRIPTION_LENGTH = 1000; private static final int MAX_NAME_LENGTH = 50; @@ -33,12 +35,8 @@ public class Pin extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false, length = 50) - private String name; - - @Lob - @Column(nullable = false, length = 1000) - private String description; + @Embedded + private PinInfo pinInfo; @OneToMany(mappedBy = "pin", cascade = CascadeType.PERSIST) private List pinImages = new ArrayList<>(); @@ -47,25 +45,20 @@ public class Pin extends BaseEntity { @JoinColumn(name = "location_id", nullable = false) private Location location; - @Column(nullable = false) - @ColumnDefault(value = "false") - private boolean isDeleted = false; - @ManyToOne @JoinColumn(name = "topic_id", nullable = false) private Topic topic; + @Column(nullable = false) + @ColumnDefault(value = "false") + private boolean isDeleted = false; + private Pin( - String name, - String description, + PinInfo pinInfo, Location location, Topic topic ) { - validateName(name); - validateDescription(description); - - this.name = name; - this.description = description; + this.pinInfo = pinInfo; this.location = location; this.topic = topic; } @@ -76,40 +69,28 @@ public static Pin createPinAssociatedWithLocationAndTopic( Location location, Topic topic ) { - Pin pin = new Pin(name, description, location, topic); + PinInfo pinInfo = PinInfo.of(name, description); + Pin pin = new Pin( + pinInfo, + location, + topic + ); location.addPin(pin); topic.addPin(pin); return pin; } - private void validateName(String name) { - if (name == null) { - throw new IllegalArgumentException("name null"); - } - if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { - throw new IllegalArgumentException("이름 길이 이상"); - } - } - - private void validateDescription(String description) { - if (description == null) { - throw new IllegalArgumentException("description null"); - } - if (description.isBlank() || description.length() > MAX_DESCRIPTION_LENGTH) { - throw new IllegalArgumentException("description 길이 이상"); - } + public void updatePinInfo(String name, String description) { + pinInfo.update(name, description); } public Pin copy(Topic topic) { - return Pin.createPinAssociatedWithLocationAndTopic(name, description, location, topic); - } - - public void update(String name, String description) { - validateName(name); - validateDescription(description); - - this.name = name; - this.description = description; + return Pin.createPinAssociatedWithLocationAndTopic( + pinInfo.getName(), + pinInfo.getDescription(), + location, + topic + ); } public void addPinImage(PinImage pinImage) { @@ -125,7 +106,8 @@ public BigDecimal getLongitude() { } public String getRoadBaseAddress() { - return location.getRoadBaseAddress(); + Address address = location.getAddress(); + return address.getRoadBaseAddress(); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/PinImage.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java similarity index 95% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/pin/PinImage.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java index b2c753d92..f87234406 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/pin/PinImage.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.entity.pin; +package com.mapbefine.mapbefine.pin.Domain; import jakarta.persistence.Column; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java new file mode 100644 index 000000000..aac5b7512 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java @@ -0,0 +1,64 @@ +package com.mapbefine.mapbefine.pin.Domain; + +import static lombok.AccessLevel.PROTECTED; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Lob; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = PROTECTED) +@Getter +public class PinInfo { + + private static final int MAX_DESCRIPTION_LENGTH = 1000; + private static final int MAX_NAME_LENGTH = 50; + + @Column(nullable = false, length = 50) + private String name; + + @Lob + @Column(nullable = false, length = 1000) + private String description; + + private PinInfo(String name, String description) { + this.name = name; + this.description = description; + } + + public static PinInfo of(String name, String description) { + validateName(name); + validateDescription(description); + + return new PinInfo(name, description); + } + + + private static void validateName(String name) { + if (name == null) { + throw new IllegalArgumentException("name null"); + } + if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException("이름 길이 이상"); + } + } + + private static void validateDescription(String description) { + if (description == null) { + throw new IllegalArgumentException("description null"); + } + if (description.isBlank() || description.length() > MAX_DESCRIPTION_LENGTH) { + throw new IllegalArgumentException("description 길이 이상"); + } + } + + public void update(String name, String description) { + validateName(name); + validateDescription(description); + + this.name = name; + this.description = description; + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java similarity index 89% rename from backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java index febf6fc57..50379fd4d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java @@ -1,6 +1,5 @@ -package com.mapbefine.mapbefine.repository; +package com.mapbefine.mapbefine.pin.Domain; -import com.mapbefine.mapbefine.entity.pin.Pin; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java similarity index 71% rename from backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java index 9bdf0763c..170d19e32 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java @@ -1,17 +1,18 @@ -package com.mapbefine.mapbefine.service; - -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.config.auth.AuthTopic; -import com.mapbefine.mapbefine.dto.PinCreateRequest; -import com.mapbefine.mapbefine.dto.PinUpdateRequest; -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.pin.PinImage; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.PinRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; +package com.mapbefine.mapbefine.pin.application; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Coordinate; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinImage; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -35,7 +36,7 @@ public PinCommandService( } public Long save(AuthMember member, PinCreateRequest request) { - Coordinate coordinate = Coordinate.from(request.latitude(), request.longitude()); + Coordinate coordinate = Coordinate.of(request.latitude(), request.longitude()); Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); member.canPinCreateOrUpdate(AuthTopic.from(topic)); @@ -66,13 +67,14 @@ public Long save(AuthMember member, PinCreateRequest request) { } private Location saveLocation(PinCreateRequest pinCreateRequest, Coordinate coordinate) { - Location location = new Location( + Address address = new Address( pinCreateRequest.address(), pinCreateRequest.address(), - coordinate, pinCreateRequest.legalDongCode() ); + Location location = new Location(address, coordinate); + return locationRepository.save(location); } @@ -85,7 +87,7 @@ public void update( .orElseThrow(NoSuchElementException::new); member.canPinCreateOrUpdate(AuthTopic.from(pin.getTopic())); - pin.update(request.name(), request.description()); + pin.updatePinInfo(request.name(), request.description()); pinRepository.save(pin); } @@ -97,8 +99,4 @@ public void removeById(AuthMember member, Long pinId) { pinRepository.deleteById(pinId); } - public void removeAllByTopicId(Long topicId) { // TODO : pinCommandService 에는 필요없는 메서드 인 것 같음 -// pinRepository.deleteAllByTopicId(topicId); - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java similarity index 72% rename from backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java index e633294b7..7b07df20c 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/PinQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java @@ -1,11 +1,11 @@ -package com.mapbefine.mapbefine.service; +package com.mapbefine.mapbefine.pin.application; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.config.auth.AuthTopic; -import com.mapbefine.mapbefine.dto.PinDetailResponse; -import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.repository.PinRepository; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import java.util.List; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java similarity index 61% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/PinCreateRequest.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java index 0661a9f74..64edfe124 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinCreateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java @@ -1,5 +1,6 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.pin.dto.request; +import java.math.BigDecimal; import java.util.List; public record PinCreateRequest( @@ -8,8 +9,8 @@ public record PinCreateRequest( String description, String address, String legalDongCode, - String latitude, - String longitude, + BigDecimal latitude, + BigDecimal longitude, List images ) { } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinUpdateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinUpdateRequest.java similarity index 74% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/PinUpdateRequest.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinUpdateRequest.java index 080295449..1a42ff019 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinUpdateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinUpdateRequest.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.pin.dto.request; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java similarity index 58% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java index 1027b08f4..e5a48e9c5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java @@ -1,7 +1,9 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.pin.dto.response; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.pin.PinImage; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinImage; +import com.mapbefine.mapbefine.pin.Domain.PinInfo; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -10,8 +12,8 @@ public record PinDetailResponse( String name, String address, String description, - String latitude, - String longitude, + BigDecimal latitude, + BigDecimal longitude, LocalDateTime updatedAt, List images ) { @@ -20,13 +22,15 @@ public static PinDetailResponse from(Pin pin) { .map(PinImage::getImageUrl) .toList(); + PinInfo pinInfo = pin.getPinInfo(); + return new PinDetailResponse( pin.getId(), - pin.getName(), + pinInfo.getName(), pin.getRoadBaseAddress(), - pin.getDescription(), - pin.getLatitude().toString(), - pin.getLongitude().toString(), + pinInfo.getDescription(), + pin.getLatitude(), + pin.getLongitude(), pin.getUpdatedAt(), images ); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java similarity index 61% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java index aa22d8445..76b812f69 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/PinResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java @@ -1,6 +1,7 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.pin.dto.response; -import com.mapbefine.mapbefine.entity.pin.Pin; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinInfo; public record PinResponse( Long id, @@ -11,11 +12,12 @@ public record PinResponse( String longitude ) { public static PinResponse from(Pin pin) { + PinInfo pinInfo = pin.getPinInfo(); return new PinResponse( pin.getId(), - pin.getName(), + pinInfo.getName(), pin.getRoadBaseAddress(), - pin.getDescription(), + pinInfo.getDescription(), pin.getLatitude().toString(), pin.getLongitude().toString() ); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/presentation/PinController.java similarity index 79% rename from backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/presentation/PinController.java index 91a7e9f13..563b0a914 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/PinController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/presentation/PinController.java @@ -1,12 +1,13 @@ -package com.mapbefine.mapbefine.controller; - -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.PinCreateRequest; -import com.mapbefine.mapbefine.dto.PinDetailResponse; -import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.dto.PinUpdateRequest; -import com.mapbefine.mapbefine.service.PinCommandService; -import com.mapbefine.mapbefine.service.PinQueryService; +package com.mapbefine.mapbefine.pin.presentation; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.interceptor.LoginRequired; +import com.mapbefine.mapbefine.pin.application.PinCommandService; +import com.mapbefine.mapbefine.pin.application.PinQueryService; +import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; +import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import java.net.URI; import java.util.List; import org.springframework.http.ResponseEntity; @@ -31,6 +32,7 @@ public PinController(PinCommandService pinCommandService, PinQueryService pinQue this.pinQueryService = pinQueryService; } + @LoginRequired @PostMapping public ResponseEntity add(AuthMember member, @RequestBody PinCreateRequest request) { Long savedId = pinCommandService.save(member, request); @@ -38,6 +40,7 @@ public ResponseEntity add(AuthMember member, @RequestBody PinCreateRequest return ResponseEntity.created(URI.create("/pins/" + savedId)).build(); } + @LoginRequired @PutMapping("/{pinId}") public ResponseEntity update( AuthMember member, @@ -51,6 +54,7 @@ public ResponseEntity update( .build(); } + @LoginRequired @DeleteMapping("/{pinId}") public ResponseEntity delete(AuthMember member, @PathVariable Long pinId) { pinCommandService.removeById(member, pinId); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java deleted file mode 100644 index d917e61f2..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicQueryService.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.mapbefine.mapbefine.service; - -import static java.util.stream.Collectors.counting; -import static java.util.stream.Collectors.groupingBy; - -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.config.auth.AuthTopic; -import com.mapbefine.mapbefine.dto.TopicDetailResponse; -import com.mapbefine.mapbefine.dto.TopicFindBestRequest; -import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; -import java.math.BigDecimal; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@Transactional(readOnly = true) -public class TopicQueryService { - - private final TopicRepository topicRepository; - private final LocationRepository locationRepository; - - public TopicQueryService(final TopicRepository topicRepository, LocationRepository locationRepository) { - this.topicRepository = topicRepository; - this.locationRepository = locationRepository; - } - - public List findAll(AuthMember member) { - return topicRepository.findAll().stream() - .filter(topic -> member.canRead(AuthTopic.from(topic))) - .map(TopicResponse::from) - .toList(); - } - - public TopicDetailResponse findById(AuthMember member, Long id) { - Topic topic = topicRepository.findById(id) - .filter(presentTopic -> member.canRead(AuthTopic.from(presentTopic))) - .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); - - return TopicDetailResponse.from(topic); - } - - public List findBests(AuthMember member, TopicFindBestRequest request) { - List locations = findLocationsInRectangle(request); - Map topicCounts = countTopicsInLocations(locations); - - return sortTopicsByCounts(topicCounts, member); - } - - private List findLocationsInRectangle(TopicFindBestRequest request) { - return locationRepository.findAllByRectangle( - new BigDecimal(request.latitude()), - new BigDecimal(request.longitude()), - BigDecimal.valueOf(0.03) - ); - } - - private Map countTopicsInLocations(List locations) { - return locations.stream() - .map(Location::getPins) - .flatMap(Collection::stream) - .collect(groupingBy(Pin::getTopic, counting())); - } - - private List sortTopicsByCounts(Map topicCounts, AuthMember member) { - return topicCounts.entrySet().stream() - .filter(topicEntry -> member.canRead(AuthTopic.from(topicEntry.getKey()))) // TODO : 볼 수 있는 토픽만 걸러내는 과정 - .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) - .map(Map.Entry::getKey) - .map(TopicResponse::from) - .toList(); - } - -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java similarity index 55% rename from backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java index fb47c93f3..46ef78984 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/service/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java @@ -1,16 +1,16 @@ -package com.mapbefine.mapbefine.service; - -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.config.auth.AuthTopic; -import com.mapbefine.mapbefine.dto.TopicCreateRequest; -import com.mapbefine.mapbefine.dto.TopicMergeRequest; -import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.PinRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; +package com.mapbefine.mapbefine.topic.application; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicMergeRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicUpdateRequest; import java.util.Collection; import java.util.List; import java.util.NoSuchElementException; @@ -36,90 +36,112 @@ public TopicCommandService( } public long createNew(AuthMember member, TopicCreateRequest request) { - member.canTopicCreate(); - - Topic topic = new Topic( - request.name(), - request.description(), - request.image(), - request.publicity(), - request.permission(), - findCreatorByAuthMember(member) - ); - - topicRepository.save(topic); + Topic topic = createNewTopic(member, request); List pinIds = request.pins(); List original = pinRepository.findAllById(pinIds); validateExist(pinIds.size(), original.size()); - pinRepository.saveAll(duplicateUserPins(original, topic)); + pinRepository.saveAll(copyPins(original, topic)); return topic.getId(); } - private Member findCreatorByAuthMember(AuthMember member) { - return memberRepository.findById(member.getMemberId()) - .orElseThrow(NoSuchElementException::new); + public long createMerge(AuthMember member, TopicMergeRequest request) { + List topicIds = request.topics(); + List topics = findTopicsByIds(member, topicIds); + + validateExist(topicIds.size(), topics.size()); + Topic topic = createMergeTopic(member, request); + + List original = getPinFromTopics(topics); + pinRepository.saveAll(copyPins(original, topic)); + + return topic.getId(); } - private void validateExist(int idCount, int existCount) { - if (idCount != existCount) { - throw new IllegalArgumentException("찾을 수 없는 ID가 포함되어 있습니다."); - } + public void updateTopicInfo( + AuthMember member, + Long id, + TopicUpdateRequest request + ) { + Topic topic = topicRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); + member.canTopicUpdate(AuthTopic.from(topic)); + + topic.updateTopicInfo( + request.name(), + request.description(), + request.image() + ); } - private List duplicateUserPins(List pins, Topic topic) { - return pins.stream() - .map(original -> original.copy(topic)) - .toList(); + public void delete(AuthMember member, Long id) { + Topic topic = topicRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); + member.canDelete(AuthTopic.from(topic)); + + pinRepository.deleteAllByTopicId(id); + topicRepository.deleteById(id); } - public long createMerge(AuthMember member, TopicMergeRequest request) { - List topicIds = request.topics(); - List topics = topicRepository.findAllById(topicIds) + private List findTopicsByIds(AuthMember member, List topicIds) { + return topicRepository.findAllById(topicIds) .stream() - .filter(topic -> member.canRead(AuthTopic.from(topic))) // TODO : 일단, 이렇게 Merge 하기 이전에 canRead 한 놈들만 골라낼 수 있도록 했어요. + .filter(topic -> member.canRead( + AuthTopic.from(topic))) // TODO : 일단, 이렇게 Merge 하기 이전에 canRead 한 놈들만 골라낼 수 있도록 했어요. .toList(); + } - validateExist(topicIds.size(), topics.size()); + private List getPinFromTopics(List topics) { + return topics.stream() + .map(Topic::getPins) + .flatMap(Collection::stream) + .toList(); + } - Topic topic = new Topic( + private Topic createMergeTopic(AuthMember member, TopicMergeRequest request) { + Member creator = findCreatorByAuthMember(member); + Topic topic = Topic.of( request.name(), request.description(), request.image(), request.publicity(), request.permission(), - findCreatorByAuthMember(member) + creator ); + return topicRepository.save(topic); - topicRepository.save(topic); - - List original = topics.stream() - .map(Topic::getPins) - .flatMap(Collection::stream) - .toList(); - List pins = duplicateUserPins(original, topic); - pinRepository.saveAll(pins); - - return topic.getId(); } - public void update(AuthMember member, Long id, TopicUpdateRequest request) { - Topic topic = topicRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); - member.canTopicUpdate(AuthTopic.from(topic)); + private Topic createNewTopic(AuthMember member, TopicCreateRequest request) { + Member creator = findCreatorByAuthMember(member); + Topic topic = Topic.of( + request.name(), + request.description(), + request.image(), + request.publicity(), + request.permission(), + creator + ); + return topicRepository.save(topic); + } - topic.update(request.name(), request.description(), request.image()); + private Member findCreatorByAuthMember(AuthMember member) { + return memberRepository.findById(member.getMemberId()) + .orElseThrow(NoSuchElementException::new); } - public void delete(AuthMember member, Long id) { - Topic topic = topicRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); - member.canDelete(AuthTopic.from(topic)); + private void validateExist(int idCount, int existCount) { + if (idCount != existCount) { + throw new IllegalArgumentException("찾을 수 없는 ID가 포함되어 있습니다."); + } + } - pinRepository.deleteAllByTopicId(id); - topicRepository.deleteById(id); + private List copyPins(List pins, Topic topic) { + return pins.stream() + .map(original -> original.copy(topic)) + .toList(); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java new file mode 100644 index 000000000..7a31808fb --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java @@ -0,0 +1,39 @@ +package com.mapbefine.mapbefine.topic.application; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.response.TopicDetailResponse; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +public class TopicQueryService { + + private final TopicRepository topicRepository; + + public TopicQueryService(final TopicRepository topicRepository, LocationRepository locationRepository) { + this.topicRepository = topicRepository; + } + + public List findAll(AuthMember member) { + return topicRepository.findAll().stream() + .filter(topic -> member.canRead(AuthTopic.from(topic))) + .map(TopicResponse::from) + .toList(); + } + + public TopicDetailResponse findById(AuthMember member, Long id) { + Topic topic = topicRepository.findById(id) + .filter(presentTopic -> member.canRead(AuthTopic.from(presentTopic))) + .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); + + return TopicDetailResponse.from(topic); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Permission.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Permission.java new file mode 100644 index 000000000..a5f0ac532 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Permission.java @@ -0,0 +1,24 @@ +package com.mapbefine.mapbefine.topic.domain; + +import lombok.Getter; + +@Getter +public enum Permission { + + ALL_MEMBERS("모든 회원"), + GROUP_ONLY("소속 회원"); + + private final String title; + + Permission(String title) { + this.title = title; + } + + public boolean isAllMembers() { + return this == ALL_MEMBERS; + } + + public boolean isGroupOnly() { + return this == GROUP_ONLY; + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Publicity.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Publicity.java new file mode 100644 index 000000000..b767a86bd --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Publicity.java @@ -0,0 +1,25 @@ +package com.mapbefine.mapbefine.topic.domain; + +import lombok.Getter; + +@Getter +public enum Publicity { + + PUBLIC("같이 볼 지도"), + PRIVATE("혼자 볼 지도"); + + private final String title; + + Publicity(String title) { + this.title = title; + } + + public boolean isPublic() { + return this == PUBLIC; + } + + public boolean isPrivate() { + return this == PRIVATE; + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java new file mode 100644 index 000000000..247bcbb1b --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -0,0 +1,104 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static lombok.AccessLevel.PROTECTED; + +import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; + +@Entity +@NoArgsConstructor(access = PROTECTED) +@Getter +public class Topic extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Embedded + private TopicInfo topicInfo; + + @Embedded + private TopicStatus topicStatus; + + @ManyToOne + @JoinColumn(name = "member_id") + private Member creator; + + @OneToMany(mappedBy = "topic", cascade = CascadeType.PERSIST) + private List pins = new ArrayList<>(); + + @Column(nullable = false) + @ColumnDefault(value = "false") + private boolean isDeleted = false; + + public Topic( + TopicInfo topicInfo, + TopicStatus topicStatus, + Member creator + ) { + this.topicInfo = topicInfo; + this.topicStatus = topicStatus; + this.creator = creator; + } + + public static Topic of( + String name, + String description, + String imageUrl, + Publicity publicity, + Permission permission, + Member creator + ) { + return new Topic( + TopicInfo.of( + name, + description, + imageUrl + ), + TopicStatus.of(publicity, permission), + creator + ); + + } + + public void updateTopicInfo( + String name, + String description, + String imageUrl + ) { + topicInfo.update( + name, + description, + imageUrl + ); + } + + public void updateTopicStatus(Publicity publicity, Permission permission) { + topicStatus.update(publicity, permission); + } + + public int countPins() { + return pins.size(); + } + + public void addPin(Pin pin) { + pins.add(pin); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java similarity index 53% rename from backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java index 1e404ffe2..a24ee4244 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/entity/topic/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java @@ -1,41 +1,22 @@ -package com.mapbefine.mapbefine.entity.topic; +package com.mapbefine.mapbefine.topic.domain; import static lombok.AccessLevel.PROTECTED; -import com.mapbefine.mapbefine.entity.BaseEntity; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.pin.Pin; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; +import jakarta.persistence.Embeddable; import jakarta.persistence.Lob; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import java.util.ArrayList; -import java.util.List; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; -@Entity +@Embeddable @NoArgsConstructor(access = PROTECTED) @Getter -public class Topic extends BaseEntity { +public class TopicInfo { private static final String DEFAULT_IMAGE_URL = "https://map-befine-official.github.io/favicon.png"; private static final int MAX_DESCRIPTION_LENGTH = 1000; private static final int MAX_NAME_LENGTH = 20; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @Column(nullable = false, length = 20) private String name; @@ -46,61 +27,29 @@ public class Topic extends BaseEntity { @Column(nullable = false, length = 2048) private String imageUrl = DEFAULT_IMAGE_URL; - @OneToMany(mappedBy = "topic", cascade = CascadeType.PERSIST) - private List pins = new ArrayList<>(); - - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private Publicity publicity; - - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private Permission permission; - - @ManyToOne - @JoinColumn(name = "member_id") - private Member creator; - - @Column(nullable = false) - @ColumnDefault(value = "false") - private boolean isDeleted = false; - - public Topic( + private TopicInfo( String name, String description, - String imageUrl, - Publicity publicity, - Permission permission, - Member creator + String imageUrl ) { this.name = name; this.description = description; this.imageUrl = imageUrl; - this.publicity = publicity; - this.permission = permission; - this.creator = creator; } - public static Topic of( + public static TopicInfo of( String name, String description, - String imageUrl, - Publicity publicity, - Permission permission, - Member creator + String imageUrl ) { validateName(name); validateDescription(description); - return new Topic( + return new TopicInfo( name, description, - validateImageUrl(imageUrl), - publicity, - permission, - creator + validateImageUrl(imageUrl) ); - } private static void validateName(String name) { @@ -141,12 +90,4 @@ public void update( this.imageUrl = validateImageUrl(imageUrl); } - public int countPins() { - return pins.size(); - } - - public void addPin(Pin pin) { - pins.add(pin); - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java similarity index 84% rename from backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java index cdd567426..98e867bde 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/repository/TopicRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java @@ -1,6 +1,5 @@ -package com.mapbefine.mapbefine.repository; +package com.mapbefine.mapbefine.topic.domain; -import com.mapbefine.mapbefine.entity.topic.Topic; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java new file mode 100644 index 000000000..984c065f7 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java @@ -0,0 +1,77 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static lombok.AccessLevel.PROTECTED; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = PROTECTED) +@Getter +public class TopicStatus { + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private Publicity publicity; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private Permission permission; + + private TopicStatus(Publicity publicity, Permission permission) { + this.publicity = publicity; + this.permission = permission; + } + + public static TopicStatus of(Publicity publicity, Permission permission) { + validateTopicStatus(publicity, permission); + + return new TopicStatus(publicity, permission); + } + + private static void validateTopicStatus(Publicity publicity, Permission permission) { + if (publicity.isPublic() && permission.isAllMembers()) { + throw new IllegalArgumentException("멤버 공개일 때는, 권한 설정이 소속 회원이어야합니다."); + } + } + + public void update(Publicity publicity, Permission permission) { + validatePublicity(publicity, permission); + validatePermission(permission); + + this.publicity = publicity; + this.permission = permission; + } + + private void validatePublicity(Publicity publicity, Permission permission) { + if (permission.isAllMembers() && publicity.isPrivate()) { + throw new IllegalArgumentException("권한 범위가 모든 멤버인 경우, 공개 범위를 혼자 볼 지도로 설정할 수 없습니다."); + } + } + + private void validatePermission(Permission permission) { + if (permission.isGroupOnly()) { + throw new IllegalArgumentException("권한 범위는 줄어들 수 없습니다."); + } + } + + public boolean isPublic() { + return publicity.isPublic(); + } + + public boolean isPrivate() { + return publicity.isPrivate(); + } + + public boolean isAllMembers() { + return permission.isAllMembers(); + } + + public boolean isGroupOnly() { + return permission.isGroupOnly(); + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicCreateRequest.java similarity index 57% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicCreateRequest.java index cad728e33..873d46c40 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicCreateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicCreateRequest.java @@ -1,7 +1,7 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.topic.dto.request; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; import java.util.List; public record TopicCreateRequest( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicMergeRequest.java similarity index 57% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicMergeRequest.java index 48158c4d8..18d468ace 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicMergeRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicMergeRequest.java @@ -1,7 +1,7 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.topic.dto.request; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; import java.util.List; public record TopicMergeRequest( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicUpdateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicUpdateRequest.java similarity index 68% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/TopicUpdateRequest.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicUpdateRequest.java index 56da737b8..13b9c6215 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicUpdateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/request/TopicUpdateRequest.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.topic.dto.request; public record TopicUpdateRequest( String name, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/response/TopicDetailResponse.java similarity index 62% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/dto/response/TopicDetailResponse.java index 5e584a7d5..48f8fe0bc 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/response/TopicDetailResponse.java @@ -1,6 +1,8 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.topic.dto.response; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicInfo; import java.time.LocalDateTime; import java.util.List; @@ -18,11 +20,13 @@ public static TopicDetailResponse from(Topic topic) { .map(PinResponse::from) .toList(); + TopicInfo topicInfo = topic.getTopicInfo(); + return new TopicDetailResponse( topic.getId(), - topic.getName(), - topic.getDescription(), - topic.getImageUrl(), + topicInfo.getName(), + topicInfo.getDescription(), + topicInfo.getImageUrl(), topic.countPins(), topic.getUpdatedAt(), pinResponses diff --git a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/response/TopicResponse.java similarity index 57% rename from backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/dto/response/TopicResponse.java index 3f7ae2b22..9d6f6e598 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/dto/TopicResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/dto/response/TopicResponse.java @@ -1,6 +1,7 @@ -package com.mapbefine.mapbefine.dto; +package com.mapbefine.mapbefine.topic.dto.response; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicInfo; import java.time.LocalDateTime; public record TopicResponse( @@ -11,10 +12,13 @@ public record TopicResponse( LocalDateTime updatedAt ) { public static TopicResponse from(Topic topic) { + + TopicInfo topicInfo = topic.getTopicInfo(); + return new TopicResponse( topic.getId(), - topic.getName(), - topic.getImageUrl(), + topicInfo.getName(), + topicInfo.getImageUrl(), topic.countPins(), topic.getUpdatedAt() ); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java similarity index 73% rename from backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java rename to backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java index 455e0de7b..0029f56c3 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/controller/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java @@ -1,14 +1,14 @@ -package com.mapbefine.mapbefine.controller; - -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.TopicCreateRequest; -import com.mapbefine.mapbefine.dto.TopicDetailResponse; -import com.mapbefine.mapbefine.dto.TopicFindBestRequest; -import com.mapbefine.mapbefine.dto.TopicMergeRequest; -import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.service.TopicCommandService; -import com.mapbefine.mapbefine.service.TopicQueryService; +package com.mapbefine.mapbefine.topic.presentation; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.interceptor.LoginRequired; +import com.mapbefine.mapbefine.topic.application.TopicCommandService; +import com.mapbefine.mapbefine.topic.application.TopicQueryService; +import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicMergeRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicUpdateRequest; +import com.mapbefine.mapbefine.topic.dto.response.TopicDetailResponse; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.net.URI; import java.util.List; import org.springframework.http.ResponseEntity; @@ -33,6 +33,7 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic this.topicQueryService = topicQueryService; } + @LoginRequired @PostMapping("/new") public ResponseEntity create(AuthMember member, @RequestBody TopicCreateRequest request) { long topicId = topicCommandService.createNew(member, request); @@ -41,6 +42,7 @@ public ResponseEntity create(AuthMember member, @RequestBody TopicCreateRe .build(); } + @LoginRequired @PostMapping("/merge") public ResponseEntity mergeAndCreate(AuthMember member, @RequestBody TopicMergeRequest request) { long topicId = topicCommandService.createMerge(member, request); @@ -49,17 +51,19 @@ public ResponseEntity mergeAndCreate(AuthMember member, @RequestBody Topic .build(); } + @LoginRequired @PutMapping("/{topicId}") public ResponseEntity update( AuthMember member, @PathVariable Long topicId, @RequestBody TopicUpdateRequest request ) { - topicCommandService.update(member, topicId, request); + topicCommandService.updateTopicInfo(member, topicId, request); return ResponseEntity.ok().build(); } + @LoginRequired @DeleteMapping("/{topicId}") public ResponseEntity delete(AuthMember member, @PathVariable Long topicId) { topicCommandService.delete(member, topicId); @@ -68,7 +72,7 @@ public ResponseEntity delete(AuthMember member, @PathVariable Long topicId } @GetMapping - public ResponseEntity> findAll(AuthMember member) { + public ResponseEntity> findAll(AuthMember member) { List topics = topicQueryService.findAll(member); return ResponseEntity.ok(topics); @@ -81,13 +85,4 @@ public ResponseEntity findById(AuthMember member, @PathVari return ResponseEntity.ok(response); } - @GetMapping("/best") - public ResponseEntity> findBests( - AuthMember member, - @RequestBody TopicFindBestRequest request - ) { - List responses = topicQueryService.findBests(member, request); - - return ResponseEntity.ok(responses); - } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java deleted file mode 100644 index 7950fe8b8..000000000 --- a/backend/src/test/java/com/mapbefine/mapbefine/LocationFixture.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.mapbefine.mapbefine; - -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; -import java.math.BigDecimal; - -public class LocationFixture { - - public static Location create() { - return new Location("지번주소", "도로명주소", new Coordinate(BigDecimal.valueOf(35), BigDecimal.valueOf(127)), "111000"); - } - - public static Location createByCoordinate(double latitude, double longitude) { - return new Location("지번주소", "도로명주소", - new Coordinate(BigDecimal.valueOf(latitude), BigDecimal.valueOf(longitude)), "111000"); - } -} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java deleted file mode 100644 index 511522e1c..000000000 --- a/backend/src/test/java/com/mapbefine/mapbefine/PinFixture.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.mapbefine.mapbefine; - -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Topic; - -public class PinFixture { - - public static Pin create(Location location, Topic topic) { - return Pin.createPinAssociatedWithLocationAndTopic( - topic.getName() + "의 핀", - "위도: " + location.getCoordinate().getLatitude() + ", 경도: " + location.getCoordinate().getLongitude(), - location, - topic - ); - } - -} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java similarity index 88% rename from backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java index 43cc2dfcb..fc621332c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/IntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java @@ -1,6 +1,6 @@ -package com.mapbefine.mapbefine.integration; +package com.mapbefine.mapbefine.common; -import io.restassured.RestAssured; +import io.restassured.*; import org.junit.jupiter.api.BeforeEach; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/RestDocsIntegration.java b/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java similarity index 97% rename from backend/src/test/java/com/mapbefine/mapbefine/controller/RestDocsIntegration.java rename to backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java index 57dd92a0b..3a3a7111f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/RestDocsIntegration.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.controller; +package com.mapbefine.mapbefine.common; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/common/annotation/ServiceTest.java similarity index 93% rename from backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/common/annotation/ServiceTest.java index 508548362..fb28a2f0f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/annotation/ServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/annotation/ServiceTest.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.annotation; +package com.mapbefine.mapbefine.common.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java new file mode 100644 index 000000000..47a65589f --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java @@ -0,0 +1,36 @@ +package com.mapbefine.mapbefine.location; + +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Coordinate; +import com.mapbefine.mapbefine.location.domain.Location; +import java.math.BigDecimal; + +public class LocationFixture { + + public static Location create() { + return new Location( + new Address( + "지번주소", + "도로명주소", + "111000" + ), + Coordinate.of( + BigDecimal.valueOf(35), + BigDecimal.valueOf(127) + ) + ); + } + + public static Location createByCoordinate(double latitude, double longitude) { + return new Location( + new Address( + "지번주소", + "도로명주소", + "111000" + ), + Coordinate.of( + BigDecimal.valueOf(latitude), + BigDecimal.valueOf(longitude)) + ); + } +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java similarity index 51% rename from backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java index c2d007a7d..12afb573b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java @@ -1,23 +1,22 @@ -package com.mapbefine.mapbefine.service; +package com.mapbefine.mapbefine.location.application; import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.LocationFixture; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.PinFixture; -import com.mapbefine.mapbefine.TopicFixture; -import com.mapbefine.mapbefine.annotation.ServiceTest; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.TopicDetailResponse; -import com.mapbefine.mapbefine.dto.TopicFindBestRequest; -import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.location.dto.CoordinateRequest; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -25,16 +24,16 @@ import org.springframework.beans.factory.annotation.Autowired; @ServiceTest -class TopicQueryServiceTest { +class LocationQueryServiceTest { @Autowired - private MemberRepository memberRepository; + private LocationRepository locationRepository; @Autowired - private LocationRepository locationRepository; + private LocationQueryService locationQueryService; @Autowired - private TopicQueryService topicQueryService; + private MemberRepository memberRepository; @Autowired private TopicRepository topicRepository; @@ -43,6 +42,7 @@ class TopicQueryServiceTest { private Topic TOPIC_BEST_2ND; private Topic TOPIC_BEST_1ST; private Location ALL_PINS_LOCATION; + private Member member; private AuthMember authMember; @@ -66,45 +66,22 @@ private Topic createAndSaveByNameAndPinCounts(String topicName, int pinCounts) { return topicRepository.save(topic); } - @Test - @DisplayName("모든 Topic 목록을 조회한다.") - void findAll() { - // given - // when - List topics = topicQueryService.findAll(authMember); - - // then - assertThat(topics).contains(TopicResponse.from(TOPIC_BEST_3RD)); - } - - @Test - @DisplayName("해당 ID를 가진 Topic을 조회한다.") - void findById() { - // given - // when - TopicDetailResponse actual = topicQueryService.findById(authMember, TOPIC_BEST_3RD.getId()); - - // then - assertThat(actual).isEqualTo(TopicDetailResponse.from(TOPIC_BEST_3RD)); - } - @Test @DisplayName("주어진 좌표 3KM 이내의 Topic들을 Pin 개수 순서대로 조회한다.") void findBests() { // given - TopicFindBestRequest currentLocation = new TopicFindBestRequest( - ALL_PINS_LOCATION.getLatitude().toString(), - ALL_PINS_LOCATION.getLongitude().toString() + CoordinateRequest currentLocation = new CoordinateRequest( + ALL_PINS_LOCATION.getLatitude(), + ALL_PINS_LOCATION.getLongitude() ); // when - List currentTopics = topicQueryService.findBests(authMember, currentLocation); + List currentTopics = locationQueryService.findBests(authMember, currentLocation); // then assertThat(currentTopics.get(0)).isEqualTo(TopicResponse.from(TOPIC_BEST_1ST)); assertThat(currentTopics.get(1)).isEqualTo(TopicResponse.from(TOPIC_BEST_2ND)); assertThat(currentTopics.get(2)).isEqualTo(TopicResponse.from(TOPIC_BEST_3RD)); } - } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java similarity index 73% rename from backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java index c5d8b87a9..3af677b12 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/entity/CoordinateTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java @@ -1,10 +1,9 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.location.domain; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.mapbefine.mapbefine.entity.pin.Coordinate; import java.math.BigDecimal; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -21,7 +20,7 @@ class CoordinateTest { void createCoordinate_FailByInvalidLatitude(String input) { BigDecimal latitude = new BigDecimal(input); - assertThatThrownBy(() -> new Coordinate(latitude, BigDecimal.valueOf(127))) + assertThatThrownBy(() -> Coordinate.of(latitude, BigDecimal.valueOf(127))) .isInstanceOf(IllegalArgumentException.class) .hasMessage("한국 내의 좌표만 입력해주세요."); } @@ -32,7 +31,7 @@ void createCoordinate_FailByInvalidLatitude(String input) { void createLatitude_Success(String input) { BigDecimal latitude = new BigDecimal(input); - assertDoesNotThrow(() -> new Coordinate(latitude, BigDecimal.valueOf(127))); + assertDoesNotThrow(() -> Coordinate.of(latitude, BigDecimal.valueOf(127))); } @ParameterizedTest @@ -41,7 +40,7 @@ void createLatitude_Success(String input) { void createLongitude_Success(String input) { BigDecimal longitude = new BigDecimal(input); - assertDoesNotThrow(() -> new Coordinate(BigDecimal.valueOf(37), longitude)); + assertDoesNotThrow(() -> Coordinate.of(BigDecimal.valueOf(37), longitude)); } @ParameterizedTest @@ -50,7 +49,7 @@ void createLongitude_Success(String input) { void createCoordinate_FailByInvalidLongitude(String input) { BigDecimal longitude = new BigDecimal(input); - assertThatThrownBy(() -> new Coordinate(BigDecimal.valueOf(37), longitude)) + assertThatThrownBy(() -> Coordinate.of(BigDecimal.valueOf(37), longitude)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("한국 내의 좌표만 입력해주세요."); } @@ -69,20 +68,20 @@ void calculateDistance(Coordinate coordinate, Coordinate other, BigDecimal under static Stream calculateDistanceProvider() { return Stream.of( Arguments.of( - new Coordinate(BigDecimal.valueOf(37.6273677), BigDecimal.valueOf(127.0447364)), - new Coordinate(BigDecimal.valueOf(37.6273438), BigDecimal.valueOf(127.0447853)), + Coordinate.of(BigDecimal.valueOf(37.6273677), BigDecimal.valueOf(127.0447364)), + Coordinate.of(BigDecimal.valueOf(37.6273438), BigDecimal.valueOf(127.0447853)), BigDecimal.valueOf(500 * 0.98), BigDecimal.valueOf(500 * 1.02) ), Arguments.of( - new Coordinate(BigDecimal.valueOf(37.5909374), BigDecimal.valueOf(127.1537482)), - new Coordinate(BigDecimal.valueOf(37.610454), BigDecimal.valueOf(127.2050749)), + Coordinate.of(BigDecimal.valueOf(37.5909374), BigDecimal.valueOf(127.1537482)), + Coordinate.of(BigDecimal.valueOf(37.610454), BigDecimal.valueOf(127.2050749)), BigDecimal.valueOf(500000 * 0.98), BigDecimal.valueOf(500000 * 1.02) ), Arguments.of( - new Coordinate(BigDecimal.valueOf(37.6273677), BigDecimal.valueOf(127.0447364)), - new Coordinate(BigDecimal.valueOf(37.6273777), BigDecimal.valueOf(127.0447364)), + Coordinate.of(BigDecimal.valueOf(37.6273677), BigDecimal.valueOf(127.0447364)), + Coordinate.of(BigDecimal.valueOf(37.6273777), BigDecimal.valueOf(127.0447364)), BigDecimal.valueOf(111 * 0.98), BigDecimal.valueOf(111 * 1.02)) ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java similarity index 85% rename from backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java index 8dcd75ecf..a4e511320 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/LocationRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java @@ -1,9 +1,7 @@ -package com.mapbefine.mapbefine.repository; +package com.mapbefine.mapbefine.location.domain; import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; import java.math.BigDecimal; import java.util.List; import java.util.stream.Stream; @@ -26,13 +24,16 @@ class LocationRepositoryTest { void findAllByRectangle_Success(BigDecimal latitude, BigDecimal longitude) { // given BigDecimal distance = BigDecimal.valueOf(0.0001); - Coordinate coordinate = new Coordinate(latitude, longitude); - Location location = new Location( + Coordinate coordinate = Coordinate.of(latitude, longitude); + Address address = new Address( "parcel", "road", - coordinate, "legalDongCode" ); + Location location = new Location( + address, + coordinate + ); locationRepository.save(location); // when @@ -61,12 +62,15 @@ static Stream coordinates_Success() { void findAllByRectangle_Fail(BigDecimal latitude, BigDecimal longitude) { // given BigDecimal distance = BigDecimal.valueOf(0.0001); - Coordinate coordinate = new Coordinate(latitude, longitude); + Coordinate coordinate = Coordinate.of(latitude, longitude); + Address address = new Address( + "지번주소", + "도로명주소", + "111000" + ); Location location = new Location( - "parcel", - "road", - coordinate, - "legalDongCode" + address, + coordinate ); locationRepository.save(location); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java new file mode 100644 index 000000000..aa20b70ca --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java @@ -0,0 +1,50 @@ +package com.mapbefine.mapbefine.location.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.location.application.LocationQueryService; +import com.mapbefine.mapbefine.location.dto.CoordinateRequest; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +class LocationControllerTest extends RestDocsIntegration { + + @MockBean + private LocationQueryService locationQueryService; + + + @Test + @DisplayName("현재 위치를 기준 토픽의 핀 개수로 나열한다.") + void findBests() throws Exception { + List responses = List.of(new TopicResponse( + 1L, + "준팍의 또 토픽", + "https://map-befine-official.github.io/favicon.png", + 5, + LocalDateTime.now() + ), new TopicResponse( + 2L, + "준팍의 두번째 토픽", + "https://map-befine-official.github.io/favicon.png", + 3, + LocalDateTime.now() + )); + CoordinateRequest coordinateRequest = new CoordinateRequest(BigDecimal.valueOf(37), BigDecimal.valueOf(127)); + given(locationQueryService.findBests(any(), any())).willReturn(responses); + + mockMvc.perform( + MockMvcRequestBuilders.get("/location/best") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(coordinateRequest)) + ).andDo(restDocs.document()); + } +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java similarity index 62% rename from backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java rename to backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java index 72e152953..8cab2465b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/MemberFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java @@ -1,7 +1,7 @@ -package com.mapbefine.mapbefine; +package com.mapbefine.mapbefine.member; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.Role; public class MemberFixture { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java new file mode 100644 index 000000000..47bf2721e --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java @@ -0,0 +1,20 @@ +package com.mapbefine.mapbefine.pin; + +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicInfo; + +public class PinFixture { + + public static Pin create(Location location, Topic topic) { + TopicInfo topicInfo = topic.getTopicInfo(); + return Pin.createPinAssociatedWithLocationAndTopic( + topicInfo.getName() + "의 핀", + "위도: " + location.getCoordinate().getLatitude() + ", 경도: " + location.getCoordinate().getLongitude(), + location, + topic + ); + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java similarity index 79% rename from backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java index 3fbfb6e6f..fb3cc67ca 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java @@ -1,22 +1,23 @@ -package com.mapbefine.mapbefine.integration; +package com.mapbefine.mapbefine.pin; import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.LocationFixture; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.TopicFixture; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.PinCreateRequest; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; -import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; +import com.mapbefine.mapbefine.common.IntegrationTest; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import io.restassured.*; +import io.restassured.response.*; +import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -54,14 +55,15 @@ void saveTopicAndLocation() { @DisplayName("핀을 생성하면 저장된 Pin의 Location과 201을 반환한다.") void addIfExistDuplicateLocation_Success() { //given + Address address = location.getAddress(); PinCreateRequest request = new PinCreateRequest( topic.getId(), "pin", "description", - location.getRoadBaseAddress(), + address.getRoadBaseAddress(), "legalDongCode", - "37.5152933", - "127.1029866", + new BigDecimal("37.5152933"), + new BigDecimal("127.1029866"), BASE_IMAGES ); @@ -93,8 +95,8 @@ void addIfNotExistDuplicateLocation_Success() { "description", "기존에 없는 주소", "legalDongCode", - "37", - "126", + new BigDecimal("37"), + new BigDecimal("126"), BASE_IMAGES ); @@ -116,8 +118,8 @@ void findAll_Success() { "description", "기존에 없는 주소", "legalDongCode", - "37", - "126", + new BigDecimal("37"), + new BigDecimal("126"), BASE_IMAGES ); @@ -127,8 +129,8 @@ void findAll_Success() { "description", "기존에 없는 주소", "legalDongCode", - "37.12345", - "126.12345", + new BigDecimal("37.12345"), + new BigDecimal("126.12345"), BASE_IMAGES ); @@ -160,8 +162,8 @@ void findDetail_Success() { "description", "기존에 없는 주소", "legalDongCode", - "37", - "126", + new BigDecimal("37"), + new BigDecimal("126"), BASE_IMAGES ); ExtractableResponse createResponse = createPin(request); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java similarity index 82% rename from backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java index ce96e79b8..0c07afec2 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java @@ -1,25 +1,26 @@ -package com.mapbefine.mapbefine.service; +package com.mapbefine.mapbefine.pin.application; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.PinCreateRequest; -import com.mapbefine.mapbefine.dto.PinDetailResponse; -import com.mapbefine.mapbefine.dto.PinUpdateRequest; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.PinRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Coordinate; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; +import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -65,7 +66,7 @@ void setUp() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); authMember = AuthMember.from(member); topic = topicRepository.save( - new Topic( + Topic.of( "topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png", @@ -82,7 +83,7 @@ void saveIfExistLocation_Success() { // given BigDecimal latitude = BigDecimal.valueOf(37.123456); BigDecimal longitude = BigDecimal.valueOf(127.123456); - Coordinate coordinate = new Coordinate(latitude, longitude); + Coordinate coordinate = Coordinate.of(latitude, longitude); Location location = saveLocation(coordinate); // when @@ -92,8 +93,8 @@ void saveIfExistLocation_Success() { "description", "road", "legalDongCode", - latitude.toString(), - longitude.toString(), + latitude, + longitude, BASE_IMAGES ); @@ -106,8 +107,8 @@ void saveIfExistLocation_Success() { "name", "road", "description", - latitude.toString(), - longitude.toString(), + latitude, + longitude, null, BASE_IMAGES ); @@ -120,13 +121,17 @@ void saveIfExistLocation_Success() { } private Location saveLocation(Coordinate coordinate) { - Location location = new Location( + Address address = new Address( "parcel", "road", - coordinate, "legalDongCode" ); + Location location = new Location( + address, + coordinate + ); + return locationRepository.save(location); } @@ -144,8 +149,8 @@ void saveIfNotExistLocation_Success() { "description", "address", "legalDongCode", - latitude.toString(), - longitude.toString(), + latitude, + longitude, BASE_IMAGES ); Long savedPinId = pinCommandService.save(authMember, request); @@ -157,8 +162,8 @@ void saveIfNotExistLocation_Success() { "name", "address", "description", - latitude.toString(), - longitude.toString(), + latitude, + longitude, null, BASE_IMAGES ); @@ -180,7 +185,7 @@ void update_Success() { // given BigDecimal latitude = BigDecimal.valueOf(37.123456); BigDecimal longitude = BigDecimal.valueOf(127.123456); - Coordinate coordinate = new Coordinate(latitude, longitude); + Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); PinCreateRequest createRequest = new PinCreateRequest( @@ -189,8 +194,8 @@ void update_Success() { "description", "address", "legalDongCode", - latitude.toString(), - longitude.toString(), + latitude, + longitude, BASE_IMAGES ); Long savedPinId = pinCommandService.save(authMember, createRequest); @@ -210,8 +215,8 @@ void update_Success() { "updatedName", "address", "updatedDescription", - latitude.toString(), - longitude.toString(), + latitude, + longitude, null, BASE_IMAGES ); @@ -227,7 +232,7 @@ void update_Fail() { // given BigDecimal latitude = BigDecimal.valueOf(37.123456); BigDecimal longitude = BigDecimal.valueOf(127.123456); - Coordinate coordinate = new Coordinate(latitude, longitude); + Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); PinCreateRequest createRequest = new PinCreateRequest( @@ -236,8 +241,8 @@ void update_Fail() { "description", "address", "legalDongCode", - latitude.toString(), - longitude.toString(), + latitude, + longitude, BASE_IMAGES ); Long savedPinId = pinCommandService.save(authMember, createRequest); @@ -254,7 +259,7 @@ void removeById_Success() { // given BigDecimal latitude = BigDecimal.valueOf(37.123456); BigDecimal longitude = BigDecimal.valueOf(127.123456); - Coordinate coordinate = new Coordinate(latitude, longitude); + Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); PinCreateRequest createRequest = new PinCreateRequest( @@ -263,8 +268,8 @@ void removeById_Success() { "description", "address", "legalDongCode", - latitude.toString(), - longitude.toString(), + latitude, + longitude, BASE_IMAGES ); Long savedPinId = pinCommandService.save(authMember, createRequest); @@ -287,7 +292,7 @@ void removeAllByTopicId_Success() { // given BigDecimal latitude = BigDecimal.valueOf(37.123456); BigDecimal longitude = BigDecimal.valueOf(127.123456); - Coordinate coordinate = new Coordinate(latitude, longitude); + Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); PinCreateRequest createRequest = new PinCreateRequest( @@ -296,8 +301,8 @@ void removeAllByTopicId_Success() { "description", "address", "legalDongCode", - latitude.toString(), - longitude.toString(), + latitude, + longitude, BASE_IMAGES ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java similarity index 74% rename from backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index 55be0b23f..a5811f693 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -1,26 +1,27 @@ -package com.mapbefine.mapbefine.service; +package com.mapbefine.mapbefine.pin.application; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.annotation.ServiceTest; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.PinDetailResponse; -import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.pin.PinImage; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.PinRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Coordinate; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinImage; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -61,12 +62,12 @@ class PinQueryServiceTest { void setUp() { BigDecimal latitude = BigDecimal.valueOf(37.123456); BigDecimal longitude = BigDecimal.valueOf(127.123456); - coordinate = new Coordinate(latitude, longitude); + coordinate = Coordinate.of(latitude, longitude); location = saveLocation(coordinate); member = memberRepository.save(MemberFixture.create(Role.ADMIN)); authMember = AuthMember.from(member); topic = topicRepository.save( - new Topic( + Topic.of( "topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png", @@ -117,8 +118,8 @@ void findById_Success() { "name", "road", "description", - coordinate.getLatitude().toString(), - coordinate.getLongitude().toString(), + coordinate.getLatitude(), + coordinate.getLongitude(), null, BASE_IMAGES ); @@ -140,12 +141,15 @@ void findById_Fail() { private Location saveLocation(Coordinate coordinate) { - Location location = new Location( + Address address = new Address( "parcel", "road", - coordinate, "legalDongCode" ); + Location location = new Location( + address, + coordinate + ); return locationRepository.save(location); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java similarity index 71% rename from backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java index e5ef91e82..809a49bf1 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/repository/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java @@ -1,17 +1,20 @@ -package com.mapbefine.mapbefine.repository; +package com.mapbefine.mapbefine.pin.domain; import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.TopicFixture; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Coordinate; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -21,7 +24,7 @@ @DataJpaTest class PinRepositoryTest { - private static final Coordinate DEFAULT_COORDINATE = new Coordinate( + private static final Coordinate DEFAULT_COORDINATE = Coordinate.of( BigDecimal.valueOf(37.5152933), BigDecimal.valueOf(127.1029866) ); @@ -44,12 +47,15 @@ void deleteById_Success() { // given Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); Topic topic = TopicFixture.createByName("name", member); - Location location = new Location( + Address address = new Address( "parcel", "road", - DEFAULT_COORDINATE, "legalDongCode" ); + Location location = new Location( + address, + DEFAULT_COORDINATE + ); topicRepository.save(topic); locationRepository.save(location); @@ -71,12 +77,15 @@ void deleteAllByTopicId_Success() { // given Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); Topic topic = TopicFixture.createByName("name", member); - Location location = new Location( + Address address = new Address( "parcel", "road", - DEFAULT_COORDINATE, "legalDongCode" ); + Location location = new Location( + address, + DEFAULT_COORDINATE + ); for (int i = 0; i < 10; i++) { Pin.createPinAssociatedWithLocationAndTopic("name", "description", location, topic); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java similarity index 74% rename from backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java index 532789eed..723ccefdc 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/entity/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java @@ -1,17 +1,19 @@ -package com.mapbefine.mapbefine.entity; +package com.mapbefine.mapbefine.pin.domain; -import static com.mapbefine.mapbefine.entity.pin.Pin.createPinAssociatedWithLocationAndTopic; +import static com.mapbefine.mapbefine.pin.Domain.Pin.createPinAssociatedWithLocationAndTopic; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Coordinate; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.location.domain.Address; +import com.mapbefine.mapbefine.location.domain.Coordinate; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinInfo; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; +import com.mapbefine.mapbefine.topic.domain.Topic; import java.math.BigDecimal; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -22,15 +24,17 @@ class PinTest { private static final Location location = new Location( - "parcel", - "road", - new Coordinate( + new Address( + "parcel", + "road", + "legalDongCode" + ), + Coordinate.of( BigDecimal.valueOf(38.123456), BigDecimal.valueOf(127.123456) - ), - "legalDongCode" + ) ); - private static final Topic topic = new Topic( + private static final Topic topic = Topic.of( "topicName", "topicDescription", null, @@ -46,9 +50,11 @@ void createPinAssociatedWithLocationAndTopic_Success(String name, String descrip // given Pin pin = createPinAssociatedWithLocationAndTopic(name, description, location, topic); + PinInfo pinInfo = pin.getPinInfo(); + // when - String actualName = pin.getName(); - String actualDescription = pin.getDescription(); + String actualName = pinInfo.getName(); + String actualDescription = pinInfo.getDescription(); // then assertThat(actualName).isEqualTo(name); @@ -72,9 +78,10 @@ void update_Success(String name, String description) { Pin pin = createPinAssociatedWithLocationAndTopic("name", "description", location, topic); // when - pin.update(name, description); - String actualName = pin.getName(); - String actualDescription = pin.getDescription(); + pin.updatePinInfo(name, description); + PinInfo pinInfo = pin.getPinInfo(); + String actualName = pinInfo.getName(); + String actualDescription = pinInfo.getDescription(); // then assertThat(actualName).isEqualTo(name); @@ -103,7 +110,7 @@ void update_Fail(String name, String description) { ); // when then - assertThatThrownBy(() -> pin.update(name, description)) + assertThatThrownBy(() -> pin.updatePinInfo(name, description)) .isInstanceOf(IllegalArgumentException.class); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java similarity index 85% rename from backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java index effae9694..ae8228151 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java @@ -1,14 +1,15 @@ -package com.mapbefine.mapbefine.controller; +package com.mapbefine.mapbefine.pin.presentation; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import com.mapbefine.mapbefine.dto.PinCreateRequest; -import com.mapbefine.mapbefine.dto.PinDetailResponse; -import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.dto.PinUpdateRequest; -import com.mapbefine.mapbefine.service.PinCommandService; -import com.mapbefine.mapbefine.service.PinQueryService; +import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.pin.application.PinCommandService; +import com.mapbefine.mapbefine.pin.application.PinQueryService; +import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; +import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -39,8 +40,8 @@ void add() throws Exception { "매튜가 사랑하는 산스장", "지번 주소", "법정동 코드", - "37", - "127", + new BigDecimal("37"), + new BigDecimal("127"), BASE_IMAGES ); @@ -86,8 +87,8 @@ void findById() throws Exception { "매튜의 산스장", "지번 주소", "매튜가 사랑하는 산스장", - new BigDecimal(37).toString(), - new BigDecimal(127).toString(), + new BigDecimal(37), + new BigDecimal(127), LocalDateTime.now(), BASE_IMAGES ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java similarity index 55% rename from backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java rename to backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java index ed6cf1d22..eeb70519e 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/TopicFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java @@ -1,10 +1,10 @@ -package com.mapbefine.mapbefine; +package com.mapbefine.mapbefine.topic; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; +import com.mapbefine.mapbefine.topic.domain.Topic; public class TopicFixture { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java similarity index 91% rename from backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java index 16ab38d98..43c31bae1 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/integration/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java @@ -1,23 +1,23 @@ -package com.mapbefine.mapbefine.integration; +package com.mapbefine.mapbefine.topic; import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.dto.TopicCreateRequest; -import com.mapbefine.mapbefine.dto.TopicMergeRequest; -import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.PinRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; -import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; +import com.mapbefine.mapbefine.common.IntegrationTest; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicMergeRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicUpdateRequest; +import io.restassured.*; +import io.restassured.response.*; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java similarity index 62% rename from backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java index 775b8014f..3b99c64aa 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/service/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java @@ -1,22 +1,23 @@ -package com.mapbefine.mapbefine.service; +package com.mapbefine.mapbefine.topic.application; import static org.assertj.core.api.Assertions.assertThat; -import com.mapbefine.mapbefine.LocationFixture; -import com.mapbefine.mapbefine.MemberFixture; -import com.mapbefine.mapbefine.PinFixture; -import com.mapbefine.mapbefine.TopicFixture; -import com.mapbefine.mapbefine.annotation.ServiceTest; -import com.mapbefine.mapbefine.config.auth.AuthMember; -import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.member.Member; -import com.mapbefine.mapbefine.entity.member.Role; -import com.mapbefine.mapbefine.entity.pin.Location; -import com.mapbefine.mapbefine.entity.pin.Pin; -import com.mapbefine.mapbefine.entity.topic.Topic; -import com.mapbefine.mapbefine.repository.LocationRepository; -import com.mapbefine.mapbefine.repository.MemberRepository; -import com.mapbefine.mapbefine.repository.TopicRepository; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicInfo; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.request.TopicUpdateRequest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -66,13 +67,14 @@ void update() { String name = "준팍의 안갈 집"; String description = "다시는 안갈 집"; String imageUrl = "https://map-befine-official.github.io/favicon.png"; - topicCommandService.update(authMember, id, new TopicUpdateRequest(name, imageUrl, description)); + topicCommandService.updateTopicInfo(authMember, id, new TopicUpdateRequest(name, imageUrl, description)); //then Topic topic = topicRepository.findById(id).get(); - assertThat(topic.getName()).isEqualTo(name); - assertThat(topic.getDescription()).isEqualTo(description); - assertThat(topic.getImageUrl()).isEqualTo(imageUrl); + TopicInfo topicInfo = topic.getTopicInfo(); + assertThat(topicInfo.getName()).isEqualTo(name); + assertThat(topicInfo.getDescription()).isEqualTo(description); + assertThat(topicInfo.getImageUrl()).isEqualTo(imageUrl); } @Test diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java new file mode 100644 index 000000000..7e745b539 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java @@ -0,0 +1,86 @@ +package com.mapbefine.mapbefine.topic.application; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.response.TopicDetailResponse; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@ServiceTest +class TopicQueryServiceTest { + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private LocationRepository locationRepository; + + @Autowired + private TopicQueryService topicQueryService; + + @Autowired + private TopicRepository topicRepository; + + private Topic topic; + private Location ALL_PINS_LOCATION; + private Member member; + private AuthMember authMember; + + @BeforeEach + void setup() { + member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authMember = AuthMember.from(member); + ALL_PINS_LOCATION = LocationFixture.createByCoordinate(35.0, 127.0); + locationRepository.save(ALL_PINS_LOCATION); + + topic = createAndSaveByNameAndPinCounts("준팍의 또간집", 1); + } + + private Topic createAndSaveByNameAndPinCounts(String topicName, int pinCounts) { + Topic topic = TopicFixture.createByName(topicName, member); + for (int i = 0; i < pinCounts; i++) { + PinFixture.create(ALL_PINS_LOCATION, topic); + } + return topicRepository.save(topic); + } + + @Test + @DisplayName("모든 Topic 목록을 조회한다.") + void findAll() { + // given + // when + List topics = topicQueryService.findAll(authMember); + + // then + assertThat(topics).contains(TopicResponse.from(topic)); + } + + @Test + @DisplayName("해당 ID를 가진 Topic을 조회한다.") + void findById() { + // given + // when + TopicDetailResponse actual = topicQueryService.findById(authMember, topic.getId()); + + // then + assertThat(actual).isEqualTo(TopicDetailResponse.from(topic)); + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java similarity index 74% rename from backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java rename to backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java index 61dad4560..6d1390df3 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/controller/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java @@ -1,19 +1,19 @@ -package com.mapbefine.mapbefine.controller; +package com.mapbefine.mapbefine.topic.presentation; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import com.mapbefine.mapbefine.dto.PinResponse; -import com.mapbefine.mapbefine.dto.TopicCreateRequest; -import com.mapbefine.mapbefine.dto.TopicDetailResponse; -import com.mapbefine.mapbefine.dto.TopicFindBestRequest; -import com.mapbefine.mapbefine.dto.TopicMergeRequest; -import com.mapbefine.mapbefine.dto.TopicResponse; -import com.mapbefine.mapbefine.dto.TopicUpdateRequest; -import com.mapbefine.mapbefine.entity.topic.Permission; -import com.mapbefine.mapbefine.entity.topic.Publicity; -import com.mapbefine.mapbefine.service.TopicCommandService; -import com.mapbefine.mapbefine.service.TopicQueryService; +import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; +import com.mapbefine.mapbefine.topic.application.TopicCommandService; +import com.mapbefine.mapbefine.topic.application.TopicQueryService; +import com.mapbefine.mapbefine.topic.domain.Permission; +import com.mapbefine.mapbefine.topic.domain.Publicity; +import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicMergeRequest; +import com.mapbefine.mapbefine.topic.dto.request.TopicUpdateRequest; +import com.mapbefine.mapbefine.topic.dto.response.TopicDetailResponse; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -75,7 +75,8 @@ void mergeAndCreate() throws Exception { @Test @DisplayName("토픽 수정") void update() throws Exception { - TopicUpdateRequest topicUpdateRequest = new TopicUpdateRequest("준팍의 안갈집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 다시 안갈집"); + TopicUpdateRequest topicUpdateRequest = new TopicUpdateRequest("준팍의 안갈집", + "https://map-befine-official.github.io/favicon.png", "준팍이 두번 다시 안갈집"); mockMvc.perform( MockMvcRequestBuilders.put("/topics/1") @@ -150,29 +151,4 @@ void findById() throws Exception { ).andDo(restDocs.document()); } - @Test - @DisplayName("현재 위치를 기준 토픽의 핀 개수로 나열한다.") - void findBests() throws Exception { - List responses = List.of(new TopicResponse( - 1L, - "준팍의 또 토픽", - "https://map-befine-official.github.io/favicon.png", - 5, - LocalDateTime.now() - ), new TopicResponse( - 2L, - "준팍의 두번째 토픽", - "https://map-befine-official.github.io/favicon.png", - 3, - LocalDateTime.now() - )); - TopicFindBestRequest topicFindBestRequest = new TopicFindBestRequest("37", "127"); - given(topicQueryService.findBests(any(), any())).willReturn(responses); - - mockMvc.perform( - MockMvcRequestBuilders.get("/topics/best") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(topicFindBestRequest)) - ).andDo(restDocs.document()); - } } From 9b588307a4ef25fd9dfd2df814869abadb93683d Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:01:25 +0900 Subject: [PATCH 17/88] =?UTF-8?q?refactor:=20TopicStatus=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20LocationC?= =?UTF-8?q?ontroller=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/location/presentation/LocationController.java | 2 +- .../java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java b/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java index 9ec96351e..2678811bd 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/Location") +@RequestMapping("/location") public class LocationController { private final LocationQueryService locationQueryService; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java index 984c065f7..012799c00 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java @@ -34,7 +34,7 @@ public static TopicStatus of(Publicity publicity, Permission permission) { } private static void validateTopicStatus(Publicity publicity, Permission permission) { - if (publicity.isPublic() && permission.isAllMembers()) { + if (publicity.isPrivate() && permission.isAllMembers()) { throw new IllegalArgumentException("멤버 공개일 때는, 권한 설정이 소속 회원이어야합니다."); } } From 80d7e9f478e8a0ca5916b37f5ed2b4d0a7ac0116 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:02:02 +0900 Subject: [PATCH 18/88] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=83=81=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java index 7218d3615..fb990772e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java @@ -28,9 +28,6 @@ @Getter public class Pin extends BaseTimeEntity { - private static final int MAX_DESCRIPTION_LENGTH = 1000; - private static final int MAX_NAME_LENGTH = 50; - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; From 939964c02160c0fa1536aba548cef02c7ce6a17b Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:03:52 +0900 Subject: [PATCH 19/88] =?UTF-8?q?refactor:=20PinResponse=20=EC=9E=90?= =?UTF-8?q?=EB=A3=8C=ED=98=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/pin/dto/response/PinResponse.java | 10 ++++++---- .../mapbefine/pin/application/PinQueryServiceTest.java | 4 ++-- .../mapbefine/pin/presentation/PinControllerTest.java | 8 ++++---- .../topic/presentation/TopicControllerTest.java | 8 ++++---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java index 76b812f69..dc565f3f2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java @@ -2,24 +2,26 @@ import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinInfo; +import java.math.BigDecimal; public record PinResponse( Long id, String name, String address, String description, - String latitude, - String longitude + BigDecimal latitude, + BigDecimal longitude ) { public static PinResponse from(Pin pin) { PinInfo pinInfo = pin.getPinInfo(); + return new PinResponse( pin.getId(), pinInfo.getName(), pin.getRoadBaseAddress(), pinInfo.getDescription(), - pin.getLatitude().toString(), - pin.getLongitude().toString() + pin.getLatitude(), + pin.getLongitude() ); } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index a5811f693..37bca2132 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -91,8 +91,8 @@ void findAll_Success() { "name", "road", "description", - coordinate.getLatitude().toString(), - coordinate.getLongitude().toString() + coordinate.getLatitude(), + coordinate.getLongitude() )); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java index ae8228151..af0f8a2b8 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java @@ -111,15 +111,15 @@ void findAll() throws Exception { "매튜의 산스장", "지번 주소", "매튜가 사랑하는 산스장", - new BigDecimal(37).toString(), - new BigDecimal(127).toString() + new BigDecimal(37), + new BigDecimal(127) ), new PinResponse( 2L, "매튜의 안갈집", "지번 주소", "매튜가 두번은 안 갈 집", - new BigDecimal(37).toString(), - new BigDecimal(127).toString() + new BigDecimal(37), + new BigDecimal(127) ) ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java index 6d1390df3..45bfca6ec 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java @@ -132,15 +132,15 @@ void findById() throws Exception { "매튜의 산스장", "지번 주소", "매튜가 사랑하는 산스장", - new BigDecimal(37).toString(), - new BigDecimal(127).toString() + new BigDecimal(37), + new BigDecimal(127) ), new PinResponse( 2L, "매튜의 안갈집", "지번 주소", "매튜가 두번은 안 갈 집", - new BigDecimal(37).toString(), - new BigDecimal(127).toString() + new BigDecimal(37), + new BigDecimal(127) ) ) ); From 12e83b4f53abbaae70162eafe059796880846538 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:04:32 +0900 Subject: [PATCH 20/88] =?UTF-8?q?feat:=20Image=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/common/entity/Image.java | 38 +++++++++++++++++++ .../mapbefine/common/util/RegexUtil.java | 12 ++++++ .../mapbefine/pin/Domain/PinImage.java | 14 ++++--- .../pin/dto/response/PinDetailResponse.java | 4 +- .../mapbefine/topic/domain/Topic.java | 2 +- .../mapbefine/topic/domain/TopicInfo.java | 25 +++++++----- 6 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/entity/Image.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/util/RegexUtil.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/entity/Image.java b/backend/src/main/java/com/mapbefine/mapbefine/common/entity/Image.java new file mode 100644 index 000000000..517da89ec --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/entity/Image.java @@ -0,0 +1,38 @@ +package com.mapbefine.mapbefine.common.entity; + +import static lombok.AccessLevel.PROTECTED; + +import com.mapbefine.mapbefine.common.util.RegexUtil; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.validation.constraints.Pattern; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = PROTECTED) +@Getter +public class Image { + + private static final String VALID_IMAGE_URL_REGEX = "(http(s?):)([/|.|\\w|\\s|-])*\\.(?:jpg|gif|png)"; + + @Pattern(regexp = VALID_IMAGE_URL_REGEX) + @Column(nullable = false, length = 2048) + private String imageUrl; + + private Image(String imageUrl) { + this.imageUrl = imageUrl; + } + + public static Image of(String imageUrl) { + validateUrl(imageUrl); + return new Image(imageUrl); + } + + private static void validateUrl(String imageUrl) { + if (!RegexUtil.matches(VALID_IMAGE_URL_REGEX, imageUrl)) { + throw new IllegalArgumentException("잘못된 형식의 URL입니다."); + } + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/util/RegexUtil.java b/backend/src/main/java/com/mapbefine/mapbefine/common/util/RegexUtil.java new file mode 100644 index 000000000..e4fa5787d --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/util/RegexUtil.java @@ -0,0 +1,12 @@ +package com.mapbefine.mapbefine.common.util; + +import java.util.regex.Pattern; + +public class RegexUtil { + + public static boolean matches(String regex, String input) { + Pattern pattern = Pattern.compile(regex); + return pattern.matcher(input).matches(); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java index f87234406..5e3e27741 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java @@ -1,6 +1,7 @@ package com.mapbefine.mapbefine.pin.Domain; -import jakarta.persistence.Column; +import com.mapbefine.mapbefine.common.entity.Image; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -20,20 +21,21 @@ public class PinImage { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false, length = 2048) - private String imageUrl; + @Embedded + private Image image; @ManyToOne @JoinColumn(name = "pin_id") private Pin pin; - private PinImage(String imageUrl, Pin pin) { - this.imageUrl = imageUrl; + + private PinImage(Image image, Pin pin) { + this.image = image; this.pin = pin; } public static PinImage createPinImageAssociatedWithPin(String imageUrl, Pin pin) { - PinImage pinImage = new PinImage(imageUrl, pin); + PinImage pinImage = new PinImage(Image.of(imageUrl), pin); pin.addPinImage(pinImage); return pinImage; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java index e5a48e9c5..1f1ce37de 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.pin.dto.response; +import com.mapbefine.mapbefine.common.entity.Image; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinImage; import com.mapbefine.mapbefine.pin.Domain.PinInfo; @@ -19,7 +20,8 @@ public record PinDetailResponse( ) { public static PinDetailResponse from(Pin pin) { List images = pin.getPinImages().stream() - .map(PinImage::getImageUrl) + .map(PinImage::getImage) + .map(Image::getImageUrl) .toList(); PinInfo pinInfo = pin.getPinInfo(); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java index 247bcbb1b..9eab1dc81 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -47,7 +47,7 @@ public class Topic extends BaseTimeEntity { @ColumnDefault(value = "false") private boolean isDeleted = false; - public Topic( + private Topic( TopicInfo topicInfo, TopicStatus topicStatus, Member creator diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java index a24ee4244..d4d2bf002 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java @@ -2,8 +2,10 @@ import static lombok.AccessLevel.PROTECTED; +import com.mapbefine.mapbefine.common.entity.Image; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; import jakarta.persistence.Lob; import lombok.Getter; import lombok.NoArgsConstructor; @@ -13,7 +15,7 @@ @Getter public class TopicInfo { - private static final String DEFAULT_IMAGE_URL = "https://map-befine-official.github.io/favicon.png"; + private static final Image DEFAULT_IMAGE = Image.of("https://map-befine-official.github.io/favicon.png"); private static final int MAX_DESCRIPTION_LENGTH = 1000; private static final int MAX_NAME_LENGTH = 20; @@ -24,17 +26,17 @@ public class TopicInfo { @Column(nullable = false, length = 1000) private String description; - @Column(nullable = false, length = 2048) - private String imageUrl = DEFAULT_IMAGE_URL; + @Embedded + private Image image; private TopicInfo( String name, String description, - String imageUrl + Image image ) { this.name = name; this.description = description; - this.imageUrl = imageUrl; + this.image = image; } public static TopicInfo of( @@ -70,11 +72,11 @@ private static void validateDescription(String description) { } } - private static String validateImageUrl(String imageUrl) { - if (imageUrl == null) { // TODO: 2023/07/28 URL 검증 - return DEFAULT_IMAGE_URL; + private static Image validateImageUrl(String imageUrl) { + if (imageUrl == null) { + return DEFAULT_IMAGE; } - return imageUrl; + return Image.of(imageUrl); } public void update( @@ -87,7 +89,10 @@ public void update( this.name = name; this.description = description; - this.imageUrl = validateImageUrl(imageUrl); + this.image = validateImageUrl(imageUrl); } + public String getImageUrl() { + return image.getImageUrl(); + } } From 8c869a19b6c7c439b9e76db2715ecc29ca2a3ba8 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:05:37 +0900 Subject: [PATCH 21/88] =?UTF-8?q?feat:=20LocationRepository=EC=97=90=20?= =?UTF-8?q?=ED=95=98=EB=B2=84=EC=82=AC=EC=9D=B8=EC=9D=84=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20find=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../location/domain/LocationRepository.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java index d22dd9c4b..83c8b09c1 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java @@ -22,4 +22,19 @@ List findAllByRectangle( @Param("distance") BigDecimal distance ); + @Query( + value = "SELECT l FROM Location l " + + "WHERE ( 6371000 * acos( cos( radians(:#{#current_coordinate.latitude}) ) " + + " * cos( radians( l.coordinate.latitude ) ) " + + " * cos( radians( l.coordinate.longitude ) - radians(:#{#current_coordinate.longitude}) ) " + + " + sin( radians(:latitude) ) " + + " * sin( radians( l.coordinate.latitude ) ) ) ) <= :distance", + nativeQuery = true + ) + List findAllByCoordinateAndDistanceInMeters( + @Param("current_coordinate") Coordinate coordinate, + @Param("distance") double distance + ); + + } From 7bdea8a2691c0742f7fcc84126eb56a82e8019f8 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:17:46 +0900 Subject: [PATCH 22/88] =?UTF-8?q?refactor:=20LocationController=EC=9D=98?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/location/presentation/LocationController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java b/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java index 2678811bd..9751f6315 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/presentation/LocationController.java @@ -22,7 +22,7 @@ public LocationController(LocationQueryService locationQueryService) { } @GetMapping("/best") - public ResponseEntity> findBests( + public ResponseEntity> findNearbyTopicsSortedByPinCount( AuthMember member, @RequestBody CoordinateRequest request ) { From 5cf431873e9404dfd8d9da9b2f0cd63aaebb3d6e Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:18:27 +0900 Subject: [PATCH 23/88] =?UTF-8?q?refactor:=20getTopicsWithPermission?= =?UTF-8?q?=EC=9D=98=20=EB=B0=98=ED=99=98=EA=B0=92=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapbefine/mapbefine/auth/domain/AuthMember.java | 2 -- .../java/com/mapbefine/mapbefine/member/domain/Member.java | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java index 6647865e6..b10df29e3 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java @@ -4,7 +4,6 @@ import com.mapbefine.mapbefine.auth.domain.member.Guest; import com.mapbefine.mapbefine.auth.domain.member.User; import com.mapbefine.mapbefine.member.domain.Member; -import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; import com.mapbefine.mapbefine.topic.domain.Topic; import java.util.List; @@ -39,7 +38,6 @@ public static AuthMember from(Member member) { private static List getTopicsWithPermission(Member member) { return member.getTopicsWithPermission() .stream() - .map(MemberTopicPermission::getTopic) .map(Topic::getId) .toList(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 697c6fc9d..57cfa60f6 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -78,4 +78,10 @@ public boolean isUser() { return role == Role.USER; } + public List getTopicsWithPermission() { + return topicsWithPermission.stream() + .map(MemberTopicPermission::getTopic) + .toList(); + } + } From cc4c0c4393c5f91e590c67ae7180f05836ba2ccf Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 20:18:57 +0900 Subject: [PATCH 24/88] =?UTF-8?q?style:=20=EB=B6=88=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EA=B3=B5=EB=B0=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java index aac5b7512..225bd12ef 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java @@ -35,7 +35,6 @@ public static PinInfo of(String name, String description) { return new PinInfo(name, description); } - private static void validateName(String name) { if (name == null) { throw new IllegalArgumentException("name null"); From b45f3b1b4a8591b24862ebd35621fe86b0008a32 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 21:29:42 +0900 Subject: [PATCH 25/88] =?UTF-8?q?refactor:=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/topic/domain/TopicStatus.java | 6 +- .../topic/domain/TopicStatusTest.java | 137 ++++++++++++++++++ 2 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicStatusTest.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java index 012799c00..c1df22d01 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicStatus.java @@ -35,7 +35,7 @@ public static TopicStatus of(Publicity publicity, Permission permission) { private static void validateTopicStatus(Publicity publicity, Permission permission) { if (publicity.isPrivate() && permission.isAllMembers()) { - throw new IllegalArgumentException("멤버 공개일 때는, 권한 설정이 소속 회원이어야합니다."); + throw new IllegalArgumentException("공개 범위가 혼자 볼 지도인 경우, 권한 설정이 소속 회원이어야합니다."); } } @@ -48,13 +48,13 @@ public void update(Publicity publicity, Permission permission) { } private void validatePublicity(Publicity publicity, Permission permission) { - if (permission.isAllMembers() && publicity.isPrivate()) { + if (publicity.isPrivate() && permission.isAllMembers()) { throw new IllegalArgumentException("권한 범위가 모든 멤버인 경우, 공개 범위를 혼자 볼 지도로 설정할 수 없습니다."); } } private void validatePermission(Permission permission) { - if (permission.isGroupOnly()) { + if (this.permission.isAllMembers() && permission.isGroupOnly()) { throw new IllegalArgumentException("권한 범위는 줄어들 수 없습니다."); } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicStatusTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicStatusTest.java new file mode 100644 index 000000000..9ffb28c14 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicStatusTest.java @@ -0,0 +1,137 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class TopicStatusTest { + + @Nested + class Validate { + + @Test + @DisplayName("공개 범위가 혼자 볼 지도일 때, 권한 설정이 전체 회원이면 예외가 발생한다.") + void fail() { + //given + Publicity publicity = Publicity.PRIVATE; + Permission permission = Permission.ALL_MEMBERS; + + //when + //then + assertThatThrownBy(() -> TopicStatus.of(publicity, permission)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("공개 범위가 혼자 볼 지도인 경우, 권한 설정이 소속 회원이어야합니다."); + } + + @Test + @DisplayName("공개 범위가 혼자 볼 지도일 때, 권한 설정이 소속 회원이면 정상적으로 동작한다") + void whenPrivateAndGroupOnly_thenSuccess() { + //given + Publicity publicity = Publicity.PRIVATE; + Permission permission = Permission.GROUP_ONLY; + + //when + TopicStatus topicStatus = TopicStatus.of(publicity, permission); + + //then + assertThat(topicStatus).isNotNull(); + assertThat(topicStatus.isPrivate()).isTrue(); + assertThat(topicStatus.isGroupOnly()).isTrue(); + } + + @Test + @DisplayName("공개 범위가 같이 볼 지도일 때, 권한 설정이 소속 회원이면 정상적으로 동작한다") + void whenPublicAndGroupOnly_thenSuccess() { + //given + Publicity publicity = Publicity.PUBLIC; + Permission permission = Permission.GROUP_ONLY; + + //when + TopicStatus topicStatus = TopicStatus.of(publicity, permission); + + //then + assertThat(topicStatus).isNotNull(); + assertThat(topicStatus.isPublic()).isTrue(); + assertThat(topicStatus.isGroupOnly()).isTrue(); + } + + @Test + @DisplayName("공개 범위가 같이 볼 지도일 때, 권한 설정이 소속 회원이면 정상적으로 동작한다") + void whenPublicAndAllMembers_thenSuccess() { + //given + Publicity publicity = Publicity.PUBLIC; + Permission permission = Permission.ALL_MEMBERS; + + //when + TopicStatus topicStatus = TopicStatus.of(publicity, permission); + + //then + assertThat(topicStatus).isNotNull(); + assertThat(topicStatus.isPublic()).isTrue(); + assertThat(topicStatus.isAllMembers()).isTrue(); + } + + } + + @Nested + class Update { + + @Test + @DisplayName("권한 범위가 모든 멤버이면, 공개 범위를 혼자 볼 지도로 설정할 때 예외가 발생한다") + void whenAllMembersAndPrivate_thenFail() { + //given + TopicStatus topicStatus = TopicStatus.of(Publicity.PUBLIC, Permission.ALL_MEMBERS); + + //when + //then + assertThatThrownBy(() -> topicStatus.update(Publicity.PRIVATE, Permission.ALL_MEMBERS)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("권한 범위가 모든 멤버인 경우, 공개 범위를 혼자 볼 지도로 설정할 수 없습니다."); + } + + @Test + @DisplayName("권한 범위를 GroupOnly로 변경할 경우, 예외가 발생한다") + void whenUpdateGroupOnly_thenFail() { + TopicStatus topicStatus = TopicStatus.of(Publicity.PUBLIC, Permission.ALL_MEMBERS); + + //when + //then + assertThatThrownBy(() -> topicStatus.update(Publicity.PUBLIC, Permission.GROUP_ONLY)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("권한 범위는 줄어들 수 없습니다."); + } + + @Test + @DisplayName("권한 범위가 GroupOnly일 때 private을 public으로 변경 가능하다") + void whenUpdatePublicityToPublic_thenSuccess() { + TopicStatus topicStatus = TopicStatus.of(Publicity.PRIVATE, Permission.GROUP_ONLY); + + //when + topicStatus.update(Publicity.PUBLIC, Permission.GROUP_ONLY); + + //then + assertThat(topicStatus).isNotNull(); + assertThat(topicStatus.isPublic()).isTrue(); + assertThat(topicStatus.isGroupOnly()).isTrue(); + } + + @Test + @DisplayName("권한 범위가 GroupOnly일 때 public을 private으로 변경 가능하다") + void whenUpdatePublicityToPrivate_thenSuccess() { + TopicStatus topicStatus = TopicStatus.of(Publicity.PUBLIC, Permission.GROUP_ONLY); + + //when + topicStatus.update(Publicity.PRIVATE, Permission.GROUP_ONLY); + + //then + assertThat(topicStatus).isNotNull(); + assertThat(topicStatus.isPrivate()).isTrue(); + assertThat(topicStatus.isGroupOnly()).isTrue(); + } + + } + +} From 0dec766e656c579818e20146773f45508a70d01d Mon Sep 17 00:00:00 2001 From: junpakPark Date: Mon, 31 Jul 2023 22:59:36 +0900 Subject: [PATCH 26/88] =?UTF-8?q?test:=20Topic=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/common/entity/ImageTest.java | 44 ++++ .../topic/domain/PermissionTest.java | 67 +++++ .../mapbefine/topic/domain/PublicityTest.java | 68 +++++ .../mapbefine/topic/domain/TopicInfoTest.java | 232 ++++++++++++++++++ .../mapbefine/topic/domain/TopicTest.java | 92 +++++++ 5 files changed, 503 insertions(+) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/common/entity/ImageTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PermissionTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PublicityTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java diff --git a/backend/src/test/java/com/mapbefine/mapbefine/common/entity/ImageTest.java b/backend/src/test/java/com/mapbefine/mapbefine/common/entity/ImageTest.java new file mode 100644 index 000000000..631fedf4c --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/entity/ImageTest.java @@ -0,0 +1,44 @@ +package com.mapbefine.mapbefine.common.entity; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class ImageTest { + + @Nested + class validate { + + @Test + @DisplayName("잘못된 형식의 URL을 입력하면 예외가 발생한다.") + void fail() { + //given + String validImageUrl = "https://example.com/image.jpg"; + + //when + Image image = Image.of(validImageUrl); + + //then + assertThat(image).isNotNull(); + assertThat(image.getImageUrl()).isEqualTo(validImageUrl); + } + + @Test + @DisplayName("정확한 URL을 입력하면 객체가 정상적으로 생성된다.") + void success() { + //given + String invalidImageUrl = "https://example.com/notimage"; + + //when + //then + assertThatThrownBy(() -> Image.of(invalidImageUrl)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 형식의 URL입니다."); + } + + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PermissionTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PermissionTest.java new file mode 100644 index 000000000..695d3bed3 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PermissionTest.java @@ -0,0 +1,67 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class PermissionTest { + + @Nested + @DisplayName("isAllMembers 메서드를 호출했을 때 ALL_MEMBER가 ") + class IsAllMembers { + + @Test + @DisplayName("아니면, false를 반환한다.") + void fail() { + //given + Permission groupOnly = Permission.GROUP_ONLY; + + //when + //then + assertThat(groupOnly.isAllMembers()).isFalse(); + } + + @Test + @DisplayName("맞으면 true를 반환한다.") + void success() { + //given + Permission allMembers = Permission.ALL_MEMBERS; + + //when + //then + assertThat(allMembers.isAllMembers()).isTrue(); + } + + } + + @Nested + @DisplayName("isGroupOnly 메서드를 호출했을 때, GROUP_ONLY가 ") + class IsGroupOnly { + + @Test + @DisplayName("아니면, false를 반환한다.") + void fail() { + //given + Permission allMembers = Permission.ALL_MEMBERS; + + //when + //then + assertThat(allMembers.isGroupOnly()).isFalse(); + } + + @Test + @DisplayName("맞으면 true를 반환한다.") + void success() { + //given + Permission groupOnly = Permission.GROUP_ONLY; + + //when + //then + assertThat(groupOnly.isGroupOnly()).isTrue(); + } + + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PublicityTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PublicityTest.java new file mode 100644 index 000000000..e8ad512cb --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/PublicityTest.java @@ -0,0 +1,68 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class PublicityTest { + + + @Nested + @DisplayName("isPublic 메서드를 호출했을 때 pulic이 ") + class IsPublic { + + @Test + @DisplayName("아니면, false를 반환한다.") + void fail() { + //given + Publicity aPrivate = Publicity.PRIVATE; + + //when + //then + assertThat(aPrivate.isPublic()).isFalse(); + } + + @Test + @DisplayName("맞으면 true를 반환한다.") + void success() { + //given + Publicity aPublic = Publicity.PUBLIC; + + //when + //then + assertThat(aPublic.isPublic()).isTrue(); + } + + } + + @Nested + @DisplayName("isPrivate 메서드를 호출했을 때, private가 ") + class IsPrivate { + + @Test + @DisplayName("아니면, false를 반환한다.") + void fail() { + //given + Publicity aPublic = Publicity.PUBLIC; + + //when + //then + assertThat(aPublic.isPrivate()).isFalse(); + } + + @Test + @DisplayName("맞으면 true를 반환한다.") + void success() { + //given + Publicity aPrivate = Publicity.PRIVATE; + + //when + //then + assertThat(aPrivate.isPrivate()).isTrue(); + } + + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java new file mode 100644 index 000000000..bdef9633e --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java @@ -0,0 +1,232 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +class TopicInfoTest { + + @Nested + class validate { + + @Test + @DisplayName("정확한 값을 입력하면 객체가 생성된다") + void success() { + //given + String validName = "매튜의 산스장"; + String validDescription = "매튜가 엄마 몰래 찾는 산스장"; + String validImageUrl = "https://example.com/image.jpg"; + + //when + TopicInfo topicInfo = TopicInfo.of( + validName, + validDescription, + validImageUrl + ); + + //then + assertThat(topicInfo).isNotNull(); + assertThat(topicInfo.getName()).isEqualTo(validName); + assertThat(topicInfo.getDescription()).isEqualTo(validDescription); + assertThat(topicInfo.getImageUrl()).isEqualTo(validImageUrl); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", "This name is definitely more than twenty characters long"}) + @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") + void whenNameIsInvalid_thenFail(String input) { + //given + String validDescription = "매튜가 엄마 몰래 찾는 산스장"; + String validImageUrl = "https://example.com/image.jpg"; + + //when + //then + assertThatThrownBy( + () -> TopicInfo.of( + input, + validDescription, + validImageUrl + ) + ) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @NullSource + @EmptySource + @DisplayName("유효한 설명이 아닌 경우 예외가 발생한다") + void whenDescriptionIsInvalid_thenFail(String input) { + //given + String validName = "매튜의 산스장"; + String validImageUrl = "https://example.com/image.jpg"; + + //when + //then + assertThatThrownBy( + () -> TopicInfo.of( + validName, + input, + validImageUrl + ) + ) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("설명의 길이가 1000자를 초과하는 경우 예외가 발생한다") + void whenDescriptionIsLongerThanThousand_thenFail() { + //given + String validName = "매튜의 산스장"; + String validDescription = "a".repeat(1001); + String validImageUrl = "https://example.com/image.jpg"; + + //when + //then + assertThatThrownBy( + () -> TopicInfo.of( + validName, + validDescription, + validImageUrl + ) + ) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("null 값을 입력할 경우, 기본 사진을 저장한다") + void whenImageNull_thenReturnDefault() { + //given + String validName = "매튜의 산스장"; + String validDescription = "매튜가 엄마 몰래 찾는 산스장"; + + //when + TopicInfo topicInfo = TopicInfo.of( + validName, + validDescription, + null + ); + + //then + assertThat(topicInfo).isNotNull(); + assertThat(topicInfo.getName()).isEqualTo(validName); + assertThat(topicInfo.getDescription()).isEqualTo(validDescription); + assertThat(topicInfo.getImageUrl()).isEqualTo("https://map-befine-official.github.io/favicon.png"); + } + + } + + @Nested + class update { + + private final String name = "쥬니의 안 갈 집"; + private final String description = "쥬니가 두 번은 안 갈 집"; + private final String imageUrl = "https://example.com/image.png"; + + private TopicInfo topicInfo; + + @BeforeEach + void setUp() { + topicInfo = TopicInfo.of( + "매튜의 산스장", + "매튜가 엄마 몰래 찾는 산스장", + "https://example.com/image.jpg" + ); + } + + @Test + @DisplayName("정확한 값을 입력하면 객체가 수정된다") + void success() { + //when + topicInfo.update( + name, + description, + imageUrl + ); + + //then + assertThat(topicInfo).isNotNull(); + assertThat(topicInfo.getName()).isEqualTo(name); + assertThat(topicInfo.getDescription()).isEqualTo(description); + assertThat(topicInfo.getImageUrl()).isEqualTo(imageUrl); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", "This name is definitely more than twenty characters long"}) + @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") + void whenNameIsInvalid_thenFail(String input) { + //when + //then + assertThatThrownBy( + () -> topicInfo.update( + input, + description, + imageUrl + ) + ) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @NullSource + @EmptySource + @DisplayName("유효한 설명이 아닌 경우 예외가 발생한다") + void whenDescriptionIsInvalid_thenFail(String input) { + //when + //then + assertThatThrownBy( + () -> TopicInfo.of( + name, + input, + imageUrl + ) + ) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("설명의 길이가 1000자를 초과하는 경우 예외가 발생한다") + void whenDescriptionIsLongerThanThousand_thenFail() { + //given + String updateDescription = "a".repeat(1001); + + //when + //then + assertThatThrownBy( + () -> TopicInfo.of( + name, + updateDescription, + imageUrl + ) + ) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("null 값을 입력할 경우, 기본 사진을 저장한다") + void whenImageNull_thenReturnDefault() { + //when + topicInfo.update( + name, + description, + null + ); + //then + assertThat(topicInfo).isNotNull(); + assertThat(topicInfo.getName()).isEqualTo(name); + assertThat(topicInfo.getDescription()).isEqualTo(description); + assertThat(topicInfo.getImageUrl()).isEqualTo("https://map-befine-official.github.io/favicon.png"); + } + + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java new file mode 100644 index 000000000..ffb9193f7 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java @@ -0,0 +1,92 @@ +package com.mapbefine.mapbefine.topic.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.PinFixture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TopicTest { + + private Topic topic; + private Pin pin; + + @BeforeEach + void setUp() { + topic = Topic.of( + "매튜의 산스장", + "매튜가 엄마 몰래 찾는 산스장", + "https://example.com/image.jpg", + Publicity.PUBLIC, + Permission.GROUP_ONLY, + MemberFixture.create(Role.USER) + ); + + pin = PinFixture.create(LocationFixture.create(), topic); + } + + @Test + void updateTopicInfo() { + //given + String name = "New Topic"; + String description = "New Description"; + String imageUrl = "https://example.com/image.png"; + + //when + topic.updateTopicInfo( + name, + description, + imageUrl + ); + TopicInfo topicInfo = topic.getTopicInfo(); + + //then + assertThat(topicInfo.getName()).isEqualTo(name); + assertThat(topicInfo.getDescription()).isEqualTo(description); + assertThat(topicInfo.getImageUrl()).isEqualTo(imageUrl); + } + + @Test + void updateTopicStatus() { + //given + Publicity publicity = Publicity.PRIVATE; + Permission permission = Permission.GROUP_ONLY; + + //when + topic.updateTopicStatus( + publicity, + permission + ); + TopicStatus topicStatus = topic.getTopicStatus(); + + //then + assertThat(topicStatus.getPublicity()).isEqualTo(publicity); + assertThat(topicStatus.getPermission()).isEqualTo(permission); + } + + @Test + void countPins() { + //given + topic.addPin(pin); + + //when + int pinCounts = topic.countPins(); + + //then + assertThat(pinCounts).isEqualTo(2); + // 핀이 처음 생성됐을 때, 연관관계 매핑으로 인해 하나 추가된 후 해당 메서드에서 하나 더 추가됌 + } + + @Test + void addPin() { + //when + topic.addPin(pin); + + //then + assertThat(topic.getPins()).contains(pin); + } +} From c45195826e345df1d0af398988ce202c9e06f907 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Tue, 1 Aug 2023 11:46:12 +0900 Subject: [PATCH 27/88] =?UTF-8?q?refactor:=20Auth=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81=20=EB=B0=8F=20TopicIntegra?= =?UTF-8?q?tionTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/AuthService.java | 36 ++++++- .../mapbefine/auth/domain/member/Guest.java | 1 - .../BasicAuthorizationExtractor.java | 12 +-- .../common/resolver/AuthArgumentResolver.java | 18 +++- .../topic/presentation/TopicController.java | 13 +-- .../mapbefine/topic/TopicIntegrationTest.java | 95 +++++++++++++------ 6 files changed, 124 insertions(+), 51 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java index b1bade36d..ed5d313a0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java @@ -1,8 +1,14 @@ package com.mapbefine.mapbefine.auth.application; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.member.Admin; +import com.mapbefine.mapbefine.auth.domain.member.Guest; +import com.mapbefine.mapbefine.auth.domain.member.User; import com.mapbefine.mapbefine.auth.dto.AuthInfo; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.topic.domain.Topic; +import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,9 +26,35 @@ public boolean isMember(AuthInfo authInfo) { return memberRepository.existsByEmail(authInfo.email()); } - public Member checkLoginMember(AuthInfo authInfo) { + public AuthMember findAuthMemberByEmail(AuthInfo authInfo) { return memberRepository.findByEmail(authInfo.email()) - .orElseThrow(() -> new IllegalArgumentException("해당 유저가 존재하지 않습니다.")); + .map(this::convertToAuthMember) + .orElseGet(Guest::new); } + private AuthMember convertToAuthMember(Member member) { + if (member.isUser()) { + return new User( + member.getId(), + getCreatedTopics(member), + getTopicsWithPermission(member) + ); + } + + return new Admin(member.getId()); + } + + private List getTopicsWithPermission(Member member) { + return member.getTopicsWithPermission() + .stream() + .map(Topic::getId) + .toList(); + } + + private List getCreatedTopics(Member member) { + return member.getCreatedTopic() + .stream() + .map(Topic::getId) + .toList(); + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java index bbb124ef1..26eb9279f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java @@ -6,7 +6,6 @@ public class Guest extends AuthMember { - public Guest() { super( null, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java index 896af86bf..046741275 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java @@ -16,10 +16,13 @@ public class BasicAuthorizationExtractor implements AuthorizationExtractor new AuthInfo("")); - return AuthMember.from(member); + return authService.findAuthMemberByEmail(authInfo); + } + + private Optional getAuthInfo(HttpServletRequest request) { + try { + return Optional.of(authorizationExtractor.extract(request)); + } catch (IllegalArgumentException e) { + return Optional.empty(); + } } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java index 0029f56c3..5aa8fdff7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java @@ -2,6 +2,7 @@ import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.common.interceptor.LoginRequired; +import com.mapbefine.mapbefine.common.resolver.Auth; import com.mapbefine.mapbefine.topic.application.TopicCommandService; import com.mapbefine.mapbefine.topic.application.TopicQueryService; import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; @@ -35,7 +36,7 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic @LoginRequired @PostMapping("/new") - public ResponseEntity create(AuthMember member, @RequestBody TopicCreateRequest request) { + public ResponseEntity create(@Auth AuthMember member, @RequestBody TopicCreateRequest request) { long topicId = topicCommandService.createNew(member, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) @@ -44,7 +45,7 @@ public ResponseEntity create(AuthMember member, @RequestBody TopicCreateRe @LoginRequired @PostMapping("/merge") - public ResponseEntity mergeAndCreate(AuthMember member, @RequestBody TopicMergeRequest request) { + public ResponseEntity mergeAndCreate(@Auth AuthMember member, @RequestBody TopicMergeRequest request) { long topicId = topicCommandService.createMerge(member, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) @@ -54,7 +55,7 @@ public ResponseEntity mergeAndCreate(AuthMember member, @RequestBody Topic @LoginRequired @PutMapping("/{topicId}") public ResponseEntity update( - AuthMember member, + @Auth AuthMember member, @PathVariable Long topicId, @RequestBody TopicUpdateRequest request ) { @@ -65,21 +66,21 @@ public ResponseEntity update( @LoginRequired @DeleteMapping("/{topicId}") - public ResponseEntity delete(AuthMember member, @PathVariable Long topicId) { + public ResponseEntity delete(@Auth AuthMember member, @PathVariable Long topicId) { topicCommandService.delete(member, topicId); return ResponseEntity.noContent().build(); } @GetMapping - public ResponseEntity> findAll(AuthMember member) { + public ResponseEntity> findAll(@Auth AuthMember member) { List topics = topicQueryService.findAll(member); return ResponseEntity.ok(topics); } @GetMapping("/{id}") - public ResponseEntity findById(AuthMember member, @PathVariable Long id) { + public ResponseEntity findById(@Auth AuthMember member, @PathVariable Long id) { TopicDetailResponse response = topicQueryService.findById(member, id); return ResponseEntity.ok(response); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java index 43c31bae1..d70ea9bac 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java @@ -20,6 +20,7 @@ import io.restassured.response.*; import java.util.Collections; import java.util.List; +import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,7 @@ class TopicIntegrationTest extends IntegrationTest { + private static final String BASIC_FORMAT = "Basic %s"; private static final String AUTHORIZATION = "Authorization"; @Autowired @@ -52,18 +54,22 @@ void createNewTopicWithoutPins_Success() { Collections.emptyList() ); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); + // when - ExtractableResponse response = createNewTopic(준팍의_또간집, member); + ExtractableResponse response = createNewTopic(준팍의_또간집, authHeader); // then assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); assertThat(response.header("Location")).isNotBlank(); } - private ExtractableResponse createNewTopic(TopicCreateRequest request, Member member) { + private ExtractableResponse createNewTopic(TopicCreateRequest request, String authHeader) { return RestAssured.given() .log().all() - .header(AUTHORIZATION, member.getEmail()) + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/topics/new") @@ -80,6 +86,10 @@ void createNewTopicWithPins_Success() { .map(Pin::getId) .toList(); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); + TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( "준팍의 또간집", "https://map-befine-official.github.io/favicon.png", @@ -90,7 +100,7 @@ void createNewTopicWithPins_Success() { ); // when - ExtractableResponse response = createNewTopic(준팍의_또간집, member); + ExtractableResponse response = createNewTopic(준팍의_또간집, authHeader); // then assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); @@ -102,26 +112,28 @@ void createNewTopicWithPins_Success() { void createMergeTopic_Success() { // given Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); - // TODO : 준팍! 해당 Merge Test 에는 topicRepository.findAll 을 통해서 이미 저장되어 있던 토픽들을 병합해주는 것으로 보이는데 - // TODO : 이러면 다른 테스트에 의존적이게 되지 않을까요? 일단은 의도가 있었을 수도 있을까봐 데이터를 추가하는 로직은 주석처리 해놓겠습니다. -// TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( -// "준팍의 또간집", -// "https://map-befine-official.github.io/favicon.png", -// "준팍이 2번 이상 간집 ", -// Publicity.PUBLIC, -// Permission.ALL_MEMBERS, -// Collections.emptyList() -// ); -// TopicCreateRequest 준팍의_또안간집 = new TopicCreateRequest( -// "준팍의 또안간집", -// "https://map-befine-official.github.io/favicon.png", -// "준팍이 2번 이상 안간집 ", -// Publicity.PUBLIC, -// Permission.ALL_MEMBERS, -// Collections.emptyList() -// ); -// createNewTopic(준팍의_또간집, member); -// createNewTopic(준팍의_또안간집, member); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); + + TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( + "준팍의 또간집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 2번 이상 간집 ", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + Collections.emptyList() + ); + TopicCreateRequest 준팍의_또안간집 = new TopicCreateRequest( + "준팍의 또안간집", + "https://map-befine-official.github.io/favicon.png", + "준팍이 2번 이상 안간집 ", + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + Collections.emptyList() + ); + createNewTopic(준팍의_또간집, authHeader); + createNewTopic(준팍의_또안간집, authHeader); List topics = topicRepository.findAll(); List topicIds = topics.stream() .map(Topic::getId) @@ -138,7 +150,7 @@ void createMergeTopic_Success() { // when ExtractableResponse response = RestAssured .given().log().all() - .header(AUTHORIZATION, member.getEmail()) + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(송파_데이트코스) .when().post("/topics/merge") @@ -154,6 +166,10 @@ void createMergeTopic_Success() { @DisplayName("Topic을 수정하면 200을 반환한다") void updateTopic_Success() { Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); + ExtractableResponse newTopic = createNewTopic( new TopicCreateRequest( "준팍의 또간집", @@ -163,7 +179,7 @@ void updateTopic_Success() { Permission.ALL_MEMBERS, Collections.emptyList() ), - member + authHeader ); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); @@ -175,7 +191,7 @@ void updateTopic_Success() { ); ExtractableResponse response = RestAssured .given().log().all() - .header(AUTHORIZATION, member.getEmail()) + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(송파_데이트코스) .when().put("/topics/{id}", topicId) @@ -190,6 +206,10 @@ void updateTopic_Success() { @DisplayName("Topic을 삭제하면 204를 반환한다") void deleteTopic_Success() { Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); ExtractableResponse newTopic = createNewTopic( new TopicCreateRequest( "준팍의 또간집", @@ -199,14 +219,14 @@ void deleteTopic_Success() { Permission.ALL_MEMBERS, Collections.emptyList() ), - member + authHeader ); long topicId = Long.parseLong(newTopic.header("Location").split("/")[2]); // when ExtractableResponse response = RestAssured .given().log().all() - .header(AUTHORIZATION, member.getEmail()) + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .when().delete("/topics/{id}", topicId) .then().log().all() @@ -219,9 +239,17 @@ void deleteTopic_Success() { @Test @DisplayName("Topic 목록을 조회하면 200을 반환한다") void findTopics_Success() { + //given + Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); + // when ExtractableResponse response = RestAssured .given().log().all() + .header(AUTHORIZATION, authHeader) .accept(MediaType.APPLICATION_JSON_VALUE) .when().get("/topics") .then().log().all() @@ -236,21 +264,26 @@ void findTopics_Success() { void findTopicDetail_Success() { //given Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); TopicCreateRequest request = new TopicCreateRequest( "topicName", - "image", + "https://map-befine-official.github.io/favicon.png", "description", Publicity.PUBLIC, Permission.ALL_MEMBERS, Collections.emptyList() ); - ExtractableResponse createResponse = createNewTopic(request, member); + ExtractableResponse createResponse = createNewTopic(request, authHeader); String locationHeader = createResponse.header("Location"); long topicId = Long.parseLong(locationHeader.split("/")[2]); // when ExtractableResponse response = RestAssured .given().log().all() + .header(AUTHORIZATION, authHeader) .accept(MediaType.APPLICATION_JSON_VALUE) .when().get("/topics/{id}", topicId) .then().log().all() From 24339350332f7a8cba393daaf9c210cd9a5ef82a Mon Sep 17 00:00:00 2001 From: junpakPark Date: Tue, 1 Aug 2023 11:55:12 +0900 Subject: [PATCH 28/88] =?UTF-8?q?refactor:=20auth=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapbefine/mapbefine/common/resolver/Auth.java | 11 ----------- .../common/resolver/AuthArgumentResolver.java | 5 +---- 2 files changed, 1 insertion(+), 15 deletions(-) delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java deleted file mode 100644 index 2b1ceaaf5..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/Auth.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.mapbefine.mapbefine.common.resolver; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -public @interface Auth { -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java index 09d38e60f..092c607b9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/resolver/AuthArgumentResolver.java @@ -29,10 +29,7 @@ public AuthArgumentResolver( @Override public boolean supportsParameter(MethodParameter parameter) { - boolean isAuthMemberAnnotation = parameter.hasParameterAnnotation(Auth.class); - boolean isAuthMemberClass = AuthMember.class.equals(parameter.getParameterType()); - - return isAuthMemberAnnotation && isAuthMemberClass; + return AuthMember.class.equals(parameter.getParameterType()); } @Override From 4383f25c0ea51494632e330ada30c027632b71e5 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Tue, 1 Aug 2023 11:56:25 +0900 Subject: [PATCH 29/88] =?UTF-8?q?test:=20AddressTest=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../topic/presentation/TopicController.java | 13 +++--- .../location/domain/AddressTest.java | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/location/domain/AddressTest.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java index 5aa8fdff7..0029f56c3 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/presentation/TopicController.java @@ -2,7 +2,6 @@ import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.common.interceptor.LoginRequired; -import com.mapbefine.mapbefine.common.resolver.Auth; import com.mapbefine.mapbefine.topic.application.TopicCommandService; import com.mapbefine.mapbefine.topic.application.TopicQueryService; import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; @@ -36,7 +35,7 @@ public TopicController(TopicCommandService topicCommandService, TopicQueryServic @LoginRequired @PostMapping("/new") - public ResponseEntity create(@Auth AuthMember member, @RequestBody TopicCreateRequest request) { + public ResponseEntity create(AuthMember member, @RequestBody TopicCreateRequest request) { long topicId = topicCommandService.createNew(member, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) @@ -45,7 +44,7 @@ public ResponseEntity create(@Auth AuthMember member, @RequestBody TopicCr @LoginRequired @PostMapping("/merge") - public ResponseEntity mergeAndCreate(@Auth AuthMember member, @RequestBody TopicMergeRequest request) { + public ResponseEntity mergeAndCreate(AuthMember member, @RequestBody TopicMergeRequest request) { long topicId = topicCommandService.createMerge(member, request); return ResponseEntity.created(URI.create("/topics/" + topicId)) @@ -55,7 +54,7 @@ public ResponseEntity mergeAndCreate(@Auth AuthMember member, @RequestBody @LoginRequired @PutMapping("/{topicId}") public ResponseEntity update( - @Auth AuthMember member, + AuthMember member, @PathVariable Long topicId, @RequestBody TopicUpdateRequest request ) { @@ -66,21 +65,21 @@ public ResponseEntity update( @LoginRequired @DeleteMapping("/{topicId}") - public ResponseEntity delete(@Auth AuthMember member, @PathVariable Long topicId) { + public ResponseEntity delete(AuthMember member, @PathVariable Long topicId) { topicCommandService.delete(member, topicId); return ResponseEntity.noContent().build(); } @GetMapping - public ResponseEntity> findAll(@Auth AuthMember member) { + public ResponseEntity> findAll(AuthMember member) { List topics = topicQueryService.findAll(member); return ResponseEntity.ok(topics); } @GetMapping("/{id}") - public ResponseEntity findById(@Auth AuthMember member, @PathVariable Long id) { + public ResponseEntity findById(AuthMember member, @PathVariable Long id) { TopicDetailResponse response = topicQueryService.findById(member, id); return ResponseEntity.ok(response); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/AddressTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/AddressTest.java new file mode 100644 index 000000000..9a2feb886 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/AddressTest.java @@ -0,0 +1,46 @@ +package com.mapbefine.mapbefine.location.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class AddressTest { + + private static final String 지번_주소 = "지번 주소"; + private static final String 도로명_주소 = "도로명 주소"; + private static final String 법정동_코드 = "법정동 코드"; + + private Address address; + + @BeforeEach + void setUp() { + address = new Address( + 지번_주소, + 도로명_주소, + 법정동_코드 + ); + } + + @Nested + @DisplayName("isSameAddress에") + class IsSameAddress { + + @Test + @DisplayName("지번 주소나 도로명 주소가 동일한 true를 반환한다.") + void success() { + assertThat(address.isSameAddress(지번_주소)).isTrue(); + assertThat(address.isSameAddress(도로명_주소)).isTrue(); + } + + @Test + @DisplayName("지번 주소나 도로명 주소가 동일한 true를 반환한다.") + void fail() { + assertThat(address.isSameAddress("다른 지번 주소")).isFalse(); + assertThat(address.isSameAddress("다른 도로명 주소")).isFalse(); + } + + } +} From 209a4e2a6e7f36dc21bf1eba78849fdf38f52c17 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Tue, 1 Aug 2023 13:37:20 +0900 Subject: [PATCH 30/88] =?UTF-8?q?test:=20Pin=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/pin/domain/PinImageTest.java | 45 ++++++ .../mapbefine/pin/domain/PinInfoTest.java | 144 ++++++++++++++++++ .../mapbefine/topic/domain/TopicInfoTest.java | 4 +- 3 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java new file mode 100644 index 000000000..25f039ada --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java @@ -0,0 +1,45 @@ +package com.mapbefine.mapbefine.pin.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.common.entity.Image; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinImage; +import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PinImageTest { + + private Topic topic; + private Pin pin; + + @BeforeEach + void setUp() { + topic = TopicFixture.createByName("아이크의 부잣집", MemberFixture.create(Role.USER)); + pin = PinFixture.create(LocationFixture.create(), topic); + + } + + + @Test + void createPinImageAssociatedWithPin() { + //given + String imageUrl = "https://example.com/image.jpg"; + + //when + PinImage pinImage = PinImage.createPinImageAssociatedWithPin(imageUrl, pin); + Image image = pinImage.getImage(); + + //then + assertThat(pinImage).isNotNull(); + assertThat(image.getImageUrl()).isEqualTo(imageUrl); + assertThat(pinImage.getPin()).isEqualTo(pin); + assertThat(pin.getPinImages()).contains(pinImage); + } +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java new file mode 100644 index 000000000..d572d1bea --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java @@ -0,0 +1,144 @@ +package com.mapbefine.mapbefine.pin.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.mapbefine.mapbefine.pin.Domain.PinInfo; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +class PinInfoTest { + + @Nested + class Validate { + + @Test + @DisplayName("정확한 값을 입력하면 객체가 생성된다") + void success() { + //given + String validName = "매튜의 산스장"; + String validDescription = "매튜가 엄마 몰래 찾는 산스장"; + + //when + PinInfo pinInfo = PinInfo.of(validName, validDescription); + + //then + assertThat(pinInfo).isNotNull(); + assertThat(pinInfo.getName()).isEqualTo(validName); + assertThat(pinInfo.getDescription()).isEqualTo(validDescription); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", + "ExampleOf50CharStringToDemonstrateLengthCheck123456"}) + @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") + void whenNameIsInvalid_thenFail(String input) { + //given + String validDescription = "매튜가 엄마 몰래 찾는 산스장"; + + //when + //then + assertThatThrownBy(() -> PinInfo.of(input, validDescription)) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @NullSource + @EmptySource + @DisplayName("유효한 설명이 아닌 경우 예외가 발생한다") + void whenDescriptionIsInvalid_thenFail(String input) { + //given + String validName = "매튜의 산스장"; + + //when + //then + assertThatThrownBy(() -> PinInfo.of(validName, input)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("설명의 길이가 1000자를 초과하는 경우 예외가 발생한다") + void whenDescriptionIsLongerThanThousand_thenFail() { + //given + String validName = "매튜의 산스장"; + String validDescription = "a".repeat(1001); + + //when + //then + assertThatThrownBy(() -> PinInfo.of(validName, validDescription)) + .isInstanceOf(IllegalArgumentException.class); + } + + } + + @Nested + class Update { + + private final String name = "쥬니의 안 갈 집"; + private final String description = "쥬니가 두 번은 안 갈 집"; + + private PinInfo pinInfo; + + @BeforeEach + void setUp() { + pinInfo = PinInfo.of("매튜의 산스장", "매튜가 엄마 몰래 찾는 산스장"); + } + + @Test + @DisplayName("정확한 값을 입력하면 객체가 수정된다") + void success() { + //when + pinInfo.update(name, description); + + //then + assertThat(pinInfo).isNotNull(); + assertThat(pinInfo.getName()).isEqualTo(name); + assertThat(pinInfo.getDescription()).isEqualTo(description); + } + + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", + "ExampleOf50CharStringToDemonstrateLengthCheck123456"}) + @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") + void whenNameIsInvalid_thenFail(String input) { + //when + //then + assertThatThrownBy(() -> pinInfo.update(input, description)) + .isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @NullSource + @EmptySource + @DisplayName("유효한 설명이 아닌 경우 예외가 발생한다") + void whenDescriptionIsInvalid_thenFail(String input) { + //when + //then + assertThatThrownBy(() -> pinInfo.update(name, input)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("설명의 길이가 1000자를 초과하는 경우 예외가 발생한다") + void whenDescriptionIsLongerThanThousand_thenFail() { + //given + String validDescription = "a".repeat(1001); + + //when + //then + assertThatThrownBy(() -> pinInfo.update(name, validDescription)) + .isInstanceOf(IllegalArgumentException.class); + } + + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java index bdef9633e..d0daef31c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java @@ -15,7 +15,7 @@ class TopicInfoTest { @Nested - class validate { + class Validate { @Test @DisplayName("정확한 값을 입력하면 객체가 생성된다") @@ -228,5 +228,5 @@ void whenImageNull_thenReturnDefault() { } } - + } From d6e4e7aa8b49331ef1fd089aa73a2316bed62365 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 1 Aug 2023 15:17:48 +0900 Subject: [PATCH 31/88] =?UTF-8?q?refactor:=20Coordinate=20BigDecimal=20->?= =?UTF-8?q?=20Double=20=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/LocationQueryService.java | 2 +- .../mapbefine/location/domain/Coordinate.java | 92 +++++++------------ .../mapbefine/location/domain/Location.java | 8 +- .../location/domain/LocationRepository.java | 7 +- .../location/dto/CoordinateRequest.java | 6 +- .../mapbefine/mapbefine/pin/Domain/Pin.java | 4 +- .../pin/dto/request/PinCreateRequest.java | 4 +- .../pin/dto/response/PinDetailResponse.java | 4 +- .../pin/dto/response/PinResponse.java | 4 +- .../mapbefine/location/LocationFixture.java | 9 +- .../location/domain/CoordinateTest.java | 58 ++++++------ .../domain/LocationRepositoryTest.java | 33 ++++--- .../presentation/LocationControllerTest.java | 2 +- .../mapbefine/pin/PinIntegrationTest.java | 20 ++-- .../application/PinCommandServiceTest.java | 24 ++--- .../pin/application/PinQueryServiceTest.java | 4 +- .../pin/domain/PinRepositoryTest.java | 4 +- .../mapbefine/pin/domain/PinTest.java | 4 +- .../pin/presentation/PinControllerTest.java | 16 ++-- .../presentation/TopicControllerTest.java | 9 +- 20 files changed, 139 insertions(+), 175 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java index 49fa84294..8351131fe 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java @@ -38,7 +38,7 @@ public List findBests(AuthMember member, CoordinateRequest reques } private List findLocationsInRectangle(CoordinateRequest request) { - BigDecimal distance = BigDecimal.valueOf(0.03); + double distance = 0.03; return locationRepository.findAllByRectangle( request.latitude(), request.longitude(), diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java index 16a8509f2..03d32035f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java @@ -1,12 +1,13 @@ package com.mapbefine.mapbefine.location.domain; +import static java.lang.Math.acos; +import static java.lang.Math.cos; +import static java.lang.Math.sin; +import static java.lang.Math.toRadians; import static lombok.AccessLevel.PROTECTED; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; -import java.math.BigDecimal; -import java.math.MathContext; -import java.util.function.DoubleUnaryOperator; import lombok.Getter; import lombok.NoArgsConstructor; @@ -15,93 +16,70 @@ @Getter public class Coordinate { - private static final BigDecimal LATITUDE_LOWER_BOUND = BigDecimal.valueOf(33); - private static final BigDecimal LATITUDE_UPPER_BOUND = BigDecimal.valueOf(43); - private static final BigDecimal LONGITUDE_LOWER_BOUND = BigDecimal.valueOf(124); - private static final BigDecimal LONGITUDE_UPPER_BOUND = BigDecimal.valueOf(132); + private static final double LATITUDE_LOWER_BOUND = 33; + private static final double LATITUDE_UPPER_BOUND = 43; + private static final double LONGITUDE_LOWER_BOUND = 124; + private static final double LONGITUDE_UPPER_BOUND = 132; - private static final BigDecimal EARTH_RADIUS = BigDecimal.valueOf(6371); - private static final BigDecimal UNIT_FOR_CONVERT_RADIAN = BigDecimal.valueOf(Math.PI / 180); - private static final BigDecimal DUPLICATE_STANDARD_DISTANCE = BigDecimal.valueOf(0.01); - private static final BigDecimal UNIT_FOR_CONVERT_TO_CENTIMETER = BigDecimal.valueOf(Math.pow(10, 5)); + private static final double EARTH_RADIUS = 6371; + private static final double UNIT_FOR_CONVERT_RADIAN = Math.PI / 180; + private static final double DUPLICATE_STANDARD_DISTANCE = 0.01; + private static final double UNIT_FOR_CONVERT_TO_CENTIMETER = Math.pow(10, 5); - @Column(precision = 18, scale = 15) - private BigDecimal latitude; - @Column(precision = 18, scale = 15) - private BigDecimal longitude; +// @Column(precision = 15, scale = 12) // 상의해야 할 부분 + private double latitude; +// @Column(precision = 15, scale = 12) + private double longitude; - private Coordinate(BigDecimal latitude, BigDecimal longitude) { + private Coordinate(double latitude, double longitude) { this.latitude = latitude; this.longitude = longitude; } - public static Coordinate of(BigDecimal latitude, BigDecimal longitude) { + public static Coordinate of(double latitude, double longitude) { validateRange(latitude, longitude); return new Coordinate(latitude, longitude); } - private static void validateRange(BigDecimal latitude, BigDecimal longitude) { + private static void validateRange(double latitude, double longitude) { if (isNotInRange(latitude, longitude)) { throw new IllegalArgumentException("한국 내의 좌표만 입력해주세요."); } } - private static boolean isNotInRange(BigDecimal latitude, BigDecimal longitude) { - return LATITUDE_LOWER_BOUND.compareTo(latitude) > 0 || - LATITUDE_UPPER_BOUND.compareTo(latitude) < 0 || - LONGITUDE_LOWER_BOUND.compareTo(longitude) > 0 || - LONGITUDE_UPPER_BOUND.compareTo(longitude) < 0; + private static boolean isNotInRange(double latitude, double longitude) { + return (latitude < LATITUDE_LOWER_BOUND || LATITUDE_UPPER_BOUND < latitude) + || (longitude < LONGITUDE_LOWER_BOUND || LONGITUDE_UPPER_BOUND < longitude); } /* * 오차 범위 2% * */ - public BigDecimal calculateDistance(Coordinate otherCoordinate) { - BigDecimal result = applyHaversine(otherCoordinate); + public double calculateDistance(Coordinate otherCoordinate) { + double result = applyHaversine(otherCoordinate); return convertToCentimeter(result); } - private BigDecimal applyHaversine(Coordinate otherCoordinate) { - BigDecimal sinDeltaLatitude = convertToSinDelta(latitude, otherCoordinate.latitude); - BigDecimal sinDeltaLongitude = convertToSinDelta(longitude, otherCoordinate.longitude); - - BigDecimal squareRoot = applyFormula(Math::cos, convertToRadian(latitude)) - .multiply(applyFormula(Math::cos, convertToRadian(otherCoordinate.latitude))) - .multiply(applyFormula(value -> Math.pow(value, 2), sinDeltaLongitude)) - .add(applyFormula(value -> Math.pow(value, 2), sinDeltaLatitude)) - .sqrt(MathContext.DECIMAL64); - - return applyFormula(Math::asin, squareRoot) - .multiply(BigDecimal.valueOf(2)) - .multiply(EARTH_RADIUS); - } - - private BigDecimal convertToSinDelta(BigDecimal x, BigDecimal y) { - BigDecimal delta = convertToRadian(x.subtract(y)); - - return applyFormula(value -> Math.sin(value / 2), delta); - } - - private BigDecimal applyFormula(DoubleUnaryOperator formula, BigDecimal value) { - return BigDecimal.valueOf(formula.applyAsDouble(value.doubleValue())); - } - - private BigDecimal convertToRadian(BigDecimal value) { - return value.multiply(UNIT_FOR_CONVERT_RADIAN); + private double applyHaversine(Coordinate otherCoordinate) { + return acos( + sin(toRadians(otherCoordinate.latitude)) * sin(toRadians(this.latitude)) + + (cos(toRadians(otherCoordinate.latitude)) * cos(toRadians(this.latitude)) + * cos(toRadians(otherCoordinate.longitude - this.longitude))) + ) * EARTH_RADIUS; } - private BigDecimal convertToCentimeter(BigDecimal distance) { - return distance.multiply(UNIT_FOR_CONVERT_TO_CENTIMETER); + private double convertToCentimeter(double distance) { + return distance * UNIT_FOR_CONVERT_TO_CENTIMETER; } public boolean isDuplicateCoordinate(Coordinate otherCoordinate) { - return calculateDistance(otherCoordinate).doubleValue() - <= convertToCentimeter(DUPLICATE_STANDARD_DISTANCE).doubleValue(); + return calculateDistance(otherCoordinate) + <= convertToCentimeter(DUPLICATE_STANDARD_DISTANCE); } - public static BigDecimal getDuplicateStandardDistance() { + public static double getDuplicateStandardDistance() { return DUPLICATE_STANDARD_DISTANCE; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java index a1d2a7183..a5e859130 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java @@ -43,8 +43,8 @@ public static Location of( String parcelBaseAddress, String roadBaseAddress, String legalDongCode, - BigDecimal latitude, - BigDecimal longitude + double latitude, + double longitude ) { return new Location( new Address( @@ -71,12 +71,12 @@ public boolean isSameAddress(String otherAddress) { return address.isSameAddress(otherAddress); } - public BigDecimal getLatitude() { + public double getLatitude() { return coordinate.getLatitude(); } - public BigDecimal getLongitude() { + public double getLongitude() { return coordinate.getLongitude(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java index 83c8b09c1..c566d8639 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/LocationRepository.java @@ -1,6 +1,5 @@ package com.mapbefine.mapbefine.location.domain; -import java.math.BigDecimal; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -17,9 +16,9 @@ public interface LocationRepository extends JpaRepository { + "AND l.coordinate.longitude BETWEEN :currentLongitude - :distance AND :currentLongitude + :distance" ) List findAllByRectangle( - @Param("currentLatitude") BigDecimal currentLatitude, - @Param("currentLongitude") BigDecimal currentLongitude, - @Param("distance") BigDecimal distance + @Param("currentLatitude") double currentLatitude, + @Param("currentLongitude") double currentLongitude, + @Param("distance") double distance ); @Query( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java index 8bb3f2a87..6ebaaf5cd 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/dto/CoordinateRequest.java @@ -1,9 +1,7 @@ package com.mapbefine.mapbefine.location.dto; -import java.math.BigDecimal; - public record CoordinateRequest( - BigDecimal latitude, - BigDecimal longitude + double latitude, + double longitude ) { } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java index fb990772e..5628c67c9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java @@ -94,11 +94,11 @@ public void addPinImage(PinImage pinImage) { pinImages.add(pinImage); } - public BigDecimal getLatitude() { + public double getLatitude() { return location.getLatitude(); } - public BigDecimal getLongitude() { + public double getLongitude() { return location.getLongitude(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java index 64edfe124..84d790710 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/request/PinCreateRequest.java @@ -9,8 +9,8 @@ public record PinCreateRequest( String description, String address, String legalDongCode, - BigDecimal latitude, - BigDecimal longitude, + double latitude, + double longitude, List images ) { } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java index 1f1ce37de..e20762ab4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java @@ -13,8 +13,8 @@ public record PinDetailResponse( String name, String address, String description, - BigDecimal latitude, - BigDecimal longitude, + double latitude, + double longitude, LocalDateTime updatedAt, List images ) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java index dc565f3f2..a4eb25903 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java @@ -9,8 +9,8 @@ public record PinResponse( String name, String address, String description, - BigDecimal latitude, - BigDecimal longitude + double latitude, + double longitude ) { public static PinResponse from(Pin pin) { PinInfo pinInfo = pin.getPinInfo(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java index 47a65589f..1bbe47c69 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/LocationFixture.java @@ -14,10 +14,7 @@ public static Location create() { "도로명주소", "111000" ), - Coordinate.of( - BigDecimal.valueOf(35), - BigDecimal.valueOf(127) - ) + Coordinate.of(35, 127) ); } @@ -28,9 +25,7 @@ public static Location createByCoordinate(double latitude, double longitude) { "도로명주소", "111000" ), - Coordinate.of( - BigDecimal.valueOf(latitude), - BigDecimal.valueOf(longitude)) + Coordinate.of(latitude, longitude) ); } } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java index 3af677b12..e8d41e38c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/CoordinateTest.java @@ -15,41 +15,36 @@ class CoordinateTest { @ParameterizedTest - @ValueSource(strings = {"32.9", "43.1"}) + @ValueSource(doubles = {32.9, 43.1}) @DisplayName("위도의 값이 33~43사이의 값이 아니면 실패한다.") - void createCoordinate_FailByInvalidLatitude(String input) { - BigDecimal latitude = new BigDecimal(input); - - assertThatThrownBy(() -> Coordinate.of(latitude, BigDecimal.valueOf(127))) + void createCoordinate_FailByInvalidLatitude(double latitude) { + assertThatThrownBy(() -> Coordinate.of(latitude, 127)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("한국 내의 좌표만 입력해주세요."); } @ParameterizedTest - @ValueSource(strings = {"33.1", "42.9"}) + @ValueSource(doubles = {33.1, 42.9}) @DisplayName("위도의 값이 33~43사이의 값이면 통과한다.") - void createLatitude_Success(String input) { - BigDecimal latitude = new BigDecimal(input); + void createLatitude_Success(double latitude) { - assertDoesNotThrow(() -> Coordinate.of(latitude, BigDecimal.valueOf(127))); + assertDoesNotThrow(() -> Coordinate.of(latitude, 127)); } @ParameterizedTest - @ValueSource(strings = {"124.1", "131.9"}) + @ValueSource(doubles = {124.1, 131.9}) @DisplayName("경도의 값이 124~132사이의 값이면 통과한다.") - void createLongitude_Success(String input) { - BigDecimal longitude = new BigDecimal(input); + void createLongitude_Success(double longitude) { - assertDoesNotThrow(() -> Coordinate.of(BigDecimal.valueOf(37), longitude)); + assertDoesNotThrow(() -> Coordinate.of(37, longitude)); } @ParameterizedTest - @ValueSource(strings = {"123.9", "132.1"}) + @ValueSource(doubles = {123.9, 132.1}) @DisplayName("경도의 값이 124~132사이의 값이 아니면 실패한다.") - void createCoordinate_FailByInvalidLongitude(String input) { - BigDecimal longitude = new BigDecimal(input); + void createCoordinate_FailByInvalidLongitude(double longitude) { - assertThatThrownBy(() -> Coordinate.of(BigDecimal.valueOf(37), longitude)) + assertThatThrownBy(() -> Coordinate.of(37, longitude)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("한국 내의 좌표만 입력해주세요."); } @@ -57,9 +52,9 @@ void createCoordinate_FailByInvalidLongitude(String input) { @ParameterizedTest @MethodSource(value = "calculateDistanceProvider") @DisplayName("좌표 사이의 거리를 계산한다.") - void calculateDistance(Coordinate coordinate, Coordinate other, BigDecimal underBound, BigDecimal upperBound) { + void calculateDistance(Coordinate coordinate, Coordinate other, double underBound, double upperBound) { // when - BigDecimal result = coordinate.calculateDistance(other); + double result = coordinate.calculateDistance(other); // then assertThat(result).isBetween(underBound, upperBound); @@ -68,22 +63,23 @@ void calculateDistance(Coordinate coordinate, Coordinate other, BigDecimal under static Stream calculateDistanceProvider() { return Stream.of( Arguments.of( - Coordinate.of(BigDecimal.valueOf(37.6273677), BigDecimal.valueOf(127.0447364)), - Coordinate.of(BigDecimal.valueOf(37.6273438), BigDecimal.valueOf(127.0447853)), - BigDecimal.valueOf(500 * 0.98), - BigDecimal.valueOf(500 * 1.02) + Coordinate.of(37.6273677, 127.0447364), + Coordinate.of(37.6273438, 127.0447853), + 500 * 0.98, + 500 * 1.02 ), Arguments.of( - Coordinate.of(BigDecimal.valueOf(37.5909374), BigDecimal.valueOf(127.1537482)), - Coordinate.of(BigDecimal.valueOf(37.610454), BigDecimal.valueOf(127.2050749)), - BigDecimal.valueOf(500000 * 0.98), - BigDecimal.valueOf(500000 * 1.02) + Coordinate.of(37.5909374, 127.1537482), + Coordinate.of(37.610454, 127.2050749), + 500000 * 0.98, + 500000 * 1.02 ), Arguments.of( - Coordinate.of(BigDecimal.valueOf(37.6273677), BigDecimal.valueOf(127.0447364)), - Coordinate.of(BigDecimal.valueOf(37.6273777), BigDecimal.valueOf(127.0447364)), - BigDecimal.valueOf(111 * 0.98), - BigDecimal.valueOf(111 * 1.02)) + Coordinate.of(37.6273677, 127.0447364), + Coordinate.of(37.6273777, 127.0447364), + 111 * 0.98, + 111 * 1.02 + ) ); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java index a4e511320..490c2ac31 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java @@ -2,7 +2,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.math.BigDecimal; import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -21,9 +20,9 @@ class LocationRepositoryTest { @ParameterizedTest @MethodSource(value = "coordinates_Success") @DisplayName("범위 내의 Pin을 검색한다.") - void findAllByRectangle_Success(BigDecimal latitude, BigDecimal longitude) { + void findAllByRectangle_Success(double latitude, double longitude) { // given - BigDecimal distance = BigDecimal.valueOf(0.0001); + double distance = 0.0001; Coordinate coordinate = Coordinate.of(latitude, longitude); Address address = new Address( "parcel", @@ -38,8 +37,8 @@ void findAllByRectangle_Success(BigDecimal latitude, BigDecimal longitude) { // when List locations = locationRepository.findAllByRectangle( - BigDecimal.valueOf(35), - BigDecimal.valueOf(127), + 35, + 127, distance ); @@ -49,19 +48,19 @@ void findAllByRectangle_Success(BigDecimal latitude, BigDecimal longitude) { static Stream coordinates_Success() { return Stream.of( - Arguments.of(BigDecimal.valueOf(34.9999), BigDecimal.valueOf(126.9999)), - Arguments.of(BigDecimal.valueOf(35.0001), BigDecimal.valueOf(126.9999)), - Arguments.of(BigDecimal.valueOf(34.9999), BigDecimal.valueOf(127.0001)), - Arguments.of(BigDecimal.valueOf(35.0001), BigDecimal.valueOf(127.0001)) + Arguments.of(34.9999, 126.999), + Arguments.of(35.0001, 126.999), + Arguments.of(34.9999, 127.000), + Arguments.of(35.0001, 127.000) ); } @ParameterizedTest @MethodSource(value = "coordinates_Fail") @DisplayName("범위 내의 Pin을 검색한다.") - void findAllByRectangle_Fail(BigDecimal latitude, BigDecimal longitude) { + void findAllByRectangle_Fail(double latitude, double longitude) { // given - BigDecimal distance = BigDecimal.valueOf(0.0001); + double distance = 0.0001; Coordinate coordinate = Coordinate.of(latitude, longitude); Address address = new Address( "지번주소", @@ -76,8 +75,8 @@ void findAllByRectangle_Fail(BigDecimal latitude, BigDecimal longitude) { // when List locations = locationRepository.findAllByRectangle( - BigDecimal.valueOf(35), - BigDecimal.valueOf(127), + 35, + 127, distance ); @@ -87,10 +86,10 @@ void findAllByRectangle_Fail(BigDecimal latitude, BigDecimal longitude) { static Stream coordinates_Fail() { return Stream.of( - Arguments.of(BigDecimal.valueOf(34.9999), BigDecimal.valueOf(126.9998)), - Arguments.of(BigDecimal.valueOf(35.0001), BigDecimal.valueOf(126.9998)), - Arguments.of(BigDecimal.valueOf(34.9998), BigDecimal.valueOf(127.0001)), - Arguments.of(BigDecimal.valueOf(35.0002), BigDecimal.valueOf(127.0001)) + Arguments.of(34.9999, 126.999), + Arguments.of(35.0001, 126.999), + Arguments.of(34.9998, 127.000), + Arguments.of(35.0002, 127.000) ); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java index aa20b70ca..96a75e5c5 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java @@ -38,7 +38,7 @@ void findBests() throws Exception { 3, LocalDateTime.now() )); - CoordinateRequest coordinateRequest = new CoordinateRequest(BigDecimal.valueOf(37), BigDecimal.valueOf(127)); + CoordinateRequest coordinateRequest = new CoordinateRequest(37, 127); given(locationQueryService.findBests(any(), any())).willReturn(responses); mockMvc.perform( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java index fb3cc67ca..a7e2da21f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java @@ -62,8 +62,8 @@ void addIfExistDuplicateLocation_Success() { "description", address.getRoadBaseAddress(), "legalDongCode", - new BigDecimal("37.5152933"), - new BigDecimal("127.1029866"), + 37.5152933, + 127.1029866, BASE_IMAGES ); @@ -95,8 +95,8 @@ void addIfNotExistDuplicateLocation_Success() { "description", "기존에 없는 주소", "legalDongCode", - new BigDecimal("37"), - new BigDecimal("126"), + 37, + 126, BASE_IMAGES ); @@ -118,8 +118,8 @@ void findAll_Success() { "description", "기존에 없는 주소", "legalDongCode", - new BigDecimal("37"), - new BigDecimal("126"), + 37, + 126, BASE_IMAGES ); @@ -129,8 +129,8 @@ void findAll_Success() { "description", "기존에 없는 주소", "legalDongCode", - new BigDecimal("37.12345"), - new BigDecimal("126.12345"), + 37.12345, + 126.12345, BASE_IMAGES ); @@ -162,8 +162,8 @@ void findDetail_Success() { "description", "기존에 없는 주소", "legalDongCode", - new BigDecimal("37"), - new BigDecimal("126"), + 37, + 126, BASE_IMAGES ); ExtractableResponse createResponse = createPin(request); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java index 0c07afec2..32553c70c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java @@ -81,8 +81,8 @@ void setUp() { @DisplayName("핀을 저장하려는 위치(Location)가 존재하면 해당 위치에 핀을 저장한다.") void saveIfExistLocation_Success() { // given - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; Coordinate coordinate = Coordinate.of(latitude, longitude); Location location = saveLocation(coordinate); @@ -139,8 +139,8 @@ private Location saveLocation(Coordinate coordinate) { @DisplayName("핀을 저장하려는 존재하지 않는 위치(Location)가 존재하지 않으면 위치를 저장하고 핀을 저장한다.") void saveIfNotExistLocation_Success() { // given - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; // when PinCreateRequest request = new PinCreateRequest( @@ -183,8 +183,8 @@ void saveIfNotExistLocation_Success() { @DisplayName("제약 사항(name, description)을 지킨 정보로 핀의 정보를 수정하면 핀이 수정된다.") void update_Success() { // given - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); @@ -230,8 +230,8 @@ void update_Success() { @DisplayName("제약 사항(name, description)을 지키지 않은 정보로 핀의 정보를 수정하면 핀이 수정되지 않는다.") void update_Fail() { // given - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); @@ -257,8 +257,8 @@ void update_Fail() { @DisplayName("핀을 삭제하면 soft-deleting 된다.") void removeById_Success() { // given - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); @@ -290,8 +290,8 @@ void removeById_Success() { @DisplayName("토픽을 삭제하면 이와 관련된 모든 핀들이 soft-deleting 된다.") void removeAllByTopicId_Success() { // given - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; Coordinate coordinate = Coordinate.of(latitude, longitude); saveLocation(coordinate); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index 37bca2132..853d4663e 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -60,8 +60,8 @@ class PinQueryServiceTest { @BeforeEach void setUp() { - BigDecimal latitude = BigDecimal.valueOf(37.123456); - BigDecimal longitude = BigDecimal.valueOf(127.123456); + double latitude = 37.123456; + double longitude = 127.123456; coordinate = Coordinate.of(latitude, longitude); location = saveLocation(coordinate); member = memberRepository.save(MemberFixture.create(Role.ADMIN)); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java index 809a49bf1..afdcf5260 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java @@ -25,8 +25,8 @@ @DataJpaTest class PinRepositoryTest { private static final Coordinate DEFAULT_COORDINATE = Coordinate.of( - BigDecimal.valueOf(37.5152933), - BigDecimal.valueOf(127.1029866) + 37.5152933, + 127.1029866 ); @Autowired diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java index 723ccefdc..17f6bf047 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java @@ -30,8 +30,8 @@ class PinTest { "legalDongCode" ), Coordinate.of( - BigDecimal.valueOf(38.123456), - BigDecimal.valueOf(127.123456) + 38.123456, + 127.123456 ) ); private static final Topic topic = Topic.of( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java index af0f8a2b8..a086d8612 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java @@ -40,8 +40,8 @@ void add() throws Exception { "매튜가 사랑하는 산스장", "지번 주소", "법정동 코드", - new BigDecimal("37"), - new BigDecimal("127"), + 37, + 127, BASE_IMAGES ); @@ -87,8 +87,8 @@ void findById() throws Exception { "매튜의 산스장", "지번 주소", "매튜가 사랑하는 산스장", - new BigDecimal(37), - new BigDecimal(127), + 37, + 127, LocalDateTime.now(), BASE_IMAGES ); @@ -111,15 +111,15 @@ void findAll() throws Exception { "매튜의 산스장", "지번 주소", "매튜가 사랑하는 산스장", - new BigDecimal(37), - new BigDecimal(127) + 37, + 127 ), new PinResponse( 2L, "매튜의 안갈집", "지번 주소", "매튜가 두번은 안 갈 집", - new BigDecimal(37), - new BigDecimal(127) + 37, + 127 ) ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java index 45bfca6ec..b9ba568eb 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java @@ -14,7 +14,6 @@ import com.mapbefine.mapbefine.topic.dto.request.TopicUpdateRequest; import com.mapbefine.mapbefine.topic.dto.response.TopicDetailResponse; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -132,15 +131,15 @@ void findById() throws Exception { "매튜의 산스장", "지번 주소", "매튜가 사랑하는 산스장", - new BigDecimal(37), - new BigDecimal(127) + 37, + 127 ), new PinResponse( 2L, "매튜의 안갈집", "지번 주소", "매튜가 두번은 안 갈 집", - new BigDecimal(37), - new BigDecimal(127) + 37, + 127 ) ) ); From 712a28938938af9bf5bfa5b769d78e726ed70a0d Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 1 Aug 2023 16:01:22 +0900 Subject: [PATCH 32/88] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EA=B0=80=20=EC=84=B1=EA=B3=B5?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BasicAuthorizationExtractor.java | 13 ++++--- .../mapbefine/location/domain/Coordinate.java | 5 +-- .../location/domain/LocationRepository.java | 3 +- .../domain/LocationRepositoryTest.java | 5 ++- .../presentation/LocationControllerTest.java | 13 ++++++- .../mapbefine/pin/PinIntegrationTest.java | 18 ++++++--- .../pin/presentation/PinControllerTest.java | 35 +++++++++++++++++- .../presentation/TopicControllerTest.java | 37 +++++++++++++++++++ 8 files changed, 109 insertions(+), 20 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java index 046741275..46e6b0920 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/infrastructure/BasicAuthorizationExtractor.java @@ -17,18 +17,19 @@ public class BasicAuthorizationExtractor implements AuthorizationExtractor findAllByRectangle( + "WHERE ( 6371000 * acos( cos( radians(:#{#current_coordinate.latitude}) ) " + " * cos( radians( l.coordinate.latitude ) ) " + " * cos( radians( l.coordinate.longitude ) - radians(:#{#current_coordinate.longitude}) ) " - + " + sin( radians(:latitude) ) " + + " + sin( radians(:#{#current_coordinate.latitude}) ) " + " * sin( radians( l.coordinate.latitude ) ) ) ) <= :distance", nativeQuery = true ) @@ -35,5 +35,4 @@ List findAllByCoordinateAndDistanceInMeters( @Param("distance") double distance ); - } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java index 490c2ac31..12416299b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java @@ -22,7 +22,9 @@ class LocationRepositoryTest { @DisplayName("범위 내의 Pin을 검색한다.") void findAllByRectangle_Success(double latitude, double longitude) { // given - double distance = 0.0001; +// double distance = 0.00011; + double distance = 0.0010; + // 지옥의 문제가 다시 시작되었다..... 자릿수 문제를 해결하기 위해서는 어쩔 수 없이 BigDecimal 을 사용하는 방법밖에 없다. Coordinate coordinate = Coordinate.of(latitude, longitude); Address address = new Address( "parcel", @@ -35,6 +37,7 @@ void findAllByRectangle_Success(double latitude, double longitude) { ); locationRepository.save(location); + // when List locations = locationRepository.findAllByRectangle( 35, diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java index 96a75e5c5..0cca3dc05 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java @@ -1,15 +1,19 @@ package com.mapbefine.mapbefine.location.presentation; +import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import com.mapbefine.mapbefine.common.RestDocsIntegration; import com.mapbefine.mapbefine.location.application.LocationQueryService; import com.mapbefine.mapbefine.location.dto.CoordinateRequest; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; +import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -18,6 +22,8 @@ class LocationControllerTest extends RestDocsIntegration { + private static final String BASIC_FORMAT = "Basic %s"; + @MockBean private LocationQueryService locationQueryService; @@ -25,6 +31,10 @@ class LocationControllerTest extends RestDocsIntegration { @Test @DisplayName("현재 위치를 기준 토픽의 핀 개수로 나열한다.") void findBests() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); List responses = List.of(new TopicResponse( 1L, "준팍의 또 토픽", @@ -43,6 +53,7 @@ void findBests() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/location/best") + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(coordinateRequest)) ).andDo(restDocs.document()); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java index a7e2da21f..21a5c6133 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.pin; +import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; import com.mapbefine.mapbefine.common.IntegrationTest; @@ -15,10 +16,11 @@ import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; -import io.restassured.*; -import io.restassured.response.*; -import java.math.BigDecimal; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; import java.util.List; +import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -28,12 +30,13 @@ class PinIntegrationTest extends IntegrationTest { - private static final String AUTHORIZATION = "Authorization"; + private static final String BASIC_FORMAT = "Basic %s"; private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); private Topic topic; private Location location; private Member member; + private String authHeader; @Autowired private MemberRepository memberRepository; @@ -47,6 +50,9 @@ class PinIntegrationTest extends IntegrationTest { @BeforeEach void saveTopicAndLocation() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); topic = topicRepository.save(TopicFixture.createByName("PinIntegration 토픽", member)); location = locationRepository.save(LocationFixture.createByCoordinate(37.5152933, 127.1029866)); } @@ -77,7 +83,7 @@ void addIfExistDuplicateLocation_Success() { private ExtractableResponse createPin(PinCreateRequest request) { return RestAssured.given().log().all() - .header(AUTHORIZATION, member.getEmail()) + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/pins") @@ -139,6 +145,7 @@ void findAll_Success() { // when ExtractableResponse response = RestAssured.given().log().all() + .header(AUTHORIZATION, authHeader) .accept(MediaType.APPLICATION_JSON_VALUE) .when().get("/pins") .then().log().all() @@ -172,6 +179,7 @@ void findDetail_Success() { // when ExtractableResponse response = RestAssured.given().log().all() + .header(AUTHORIZATION, authHeader) .accept(MediaType.APPLICATION_JSON_VALUE) .when().get("/pins/" + pinId) .then().log().all() diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java index a086d8612..be163b8ec 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java @@ -1,9 +1,13 @@ package com.mapbefine.mapbefine.pin.presentation; +import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.pin.application.PinCommandService; import com.mapbefine.mapbefine.pin.application.PinQueryService; import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; @@ -13,6 +17,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; +import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -21,6 +26,9 @@ class PinControllerTest extends RestDocsIntegration { + + private static final String BASIC_FORMAT = "Basic %s"; + private static final List BASE_IMAGES = List.of("https://map-befine-official.github.io/favicon.png"); @MockBean @@ -32,6 +40,10 @@ class PinControllerTest extends RestDocsIntegration { @Test @DisplayName("핀 추가") void add() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); given(pinCommandService.save(any(), any())).willReturn(1L); PinCreateRequest pinCreateRequest = new PinCreateRequest( @@ -47,6 +59,7 @@ void add() throws Exception { mockMvc.perform( MockMvcRequestBuilders.post("/pins") + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(pinCreateRequest)) ).andDo(restDocs.document()); @@ -55,6 +68,10 @@ void add() throws Exception { @Test @DisplayName("핀 수정") void update() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); PinUpdateRequest pinUpdateRequest = new PinUpdateRequest( "매튜의 안갈집", @@ -64,6 +81,7 @@ void update() throws Exception { mockMvc.perform( MockMvcRequestBuilders.put("/pins/1") + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(pinUpdateRequest)) ).andDo(restDocs.document()); @@ -72,15 +90,23 @@ void update() throws Exception { @Test @DisplayName("핀 삭제") void delete() throws Exception { - + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); mockMvc.perform( MockMvcRequestBuilders.delete("/pins/1") + .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } @Test @DisplayName("핀 상세 조회") void findById() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); PinDetailResponse pinDetailResponse = new PinDetailResponse( 1L, @@ -97,6 +123,7 @@ void findById() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/pins/1") +// .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } @@ -104,6 +131,10 @@ void findById() throws Exception { @Test @DisplayName("핀 목록 조회") void findAll() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); List pinResponses = List.of( new PinResponse( @@ -127,8 +158,8 @@ void findAll() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/pins") + .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } - } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java index b9ba568eb..21ec02990 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java @@ -1,9 +1,13 @@ package com.mapbefine.mapbefine.topic.presentation; +import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.application.TopicCommandService; import com.mapbefine.mapbefine.topic.application.TopicQueryService; @@ -16,6 +20,7 @@ import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.time.LocalDateTime; import java.util.List; +import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -24,6 +29,8 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Image 칼람 추가됨으로 인해 수정 필요 + private static final String BASIC_FORMAT = "Basic %s"; + @MockBean private TopicCommandService topicCommandService; @@ -33,6 +40,10 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Imag @Test @DisplayName("토픽 새로 생성") void create() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); given(topicCommandService.createNew(any(), any())).willReturn(1L); TopicCreateRequest topicCreateRequest = new TopicCreateRequest( @@ -46,6 +57,7 @@ void create() throws Exception { mockMvc.perform( MockMvcRequestBuilders.post("/topics/new") + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(topicCreateRequest)) ).andDo(restDocs.document()); @@ -54,6 +66,10 @@ void create() throws Exception { @Test @DisplayName("토픽 병합 생성") void mergeAndCreate() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); given(topicCommandService.createMerge(any(), any())).willReturn(1L); TopicMergeRequest topicMergeRequest = new TopicMergeRequest( "준팍의 안갈집", @@ -66,6 +82,7 @@ void mergeAndCreate() throws Exception { mockMvc.perform( MockMvcRequestBuilders.post("/topics/merge") + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(topicMergeRequest)) ).andDo(restDocs.document()); @@ -74,11 +91,16 @@ void mergeAndCreate() throws Exception { @Test @DisplayName("토픽 수정") void update() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); TopicUpdateRequest topicUpdateRequest = new TopicUpdateRequest("준팍의 안갈집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 다시 안갈집"); mockMvc.perform( MockMvcRequestBuilders.put("/topics/1") + .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(topicUpdateRequest)) ).andDo(restDocs.document()); @@ -87,14 +109,23 @@ void update() throws Exception { @Test @DisplayName("토픽 삭제") void delete() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); mockMvc.perform( MockMvcRequestBuilders.delete("/topics/1") + .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } @Test @DisplayName("토픽 목록 조회") void findAll() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); List responses = List.of(new TopicResponse( 1L, "준팍의 또 토픽", @@ -112,12 +143,17 @@ void findAll() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/topics") + .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } @Test @DisplayName("토픽 상세 조회") void findById() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + String authHeader = Base64.encodeBase64String( + String.format(BASIC_FORMAT, member.getEmail()).getBytes() + ); TopicDetailResponse topicDetailResponse = new TopicDetailResponse( 1L, "준팍의 두번째 토픽", @@ -147,6 +183,7 @@ void findById() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/topics/1") + .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } From 846490a58f1aa6a18480de7e74bf5f7ae0601d18 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 1 Aug 2023 16:33:57 +0900 Subject: [PATCH 33/88] =?UTF-8?q?refactor:=20LocationRepositoryTest=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 --- .../mapbefine/location/domain/Coordinate.java | 12 ++++++----- .../domain/LocationRepositoryTest.java | 20 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java index d8a0be897..42ca767ce 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Coordinate.java @@ -6,6 +6,7 @@ import static java.lang.Math.toRadians; import static lombok.AccessLevel.PROTECTED; +import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import lombok.Getter; import lombok.NoArgsConstructor; @@ -25,12 +26,13 @@ public class Coordinate { private static final double DUPLICATE_STANDARD_DISTANCE = 0.01; private static final double UNIT_FOR_CONVERT_TO_CENTIMETER = Math.pow(10, 5); -// @Column(precision = 10, scale = 7) // 상의해야 할 부분 - private double latitude; -// @Column(precision = 10, scale = 7) - private double longitude; + @Column(columnDefinition = "Decimal(18,15)") + private Double latitude; - private Coordinate(double latitude, double longitude) { + @Column(columnDefinition = "Decimal(18,15)") + private Double longitude; + + private Coordinate(Double latitude, Double longitude) { this.latitude = latitude; this.longitude = longitude; } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java index 12416299b..f43cb69a4 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/domain/LocationRepositoryTest.java @@ -22,9 +22,7 @@ class LocationRepositoryTest { @DisplayName("범위 내의 Pin을 검색한다.") void findAllByRectangle_Success(double latitude, double longitude) { // given -// double distance = 0.00011; - double distance = 0.0010; - // 지옥의 문제가 다시 시작되었다..... 자릿수 문제를 해결하기 위해서는 어쩔 수 없이 BigDecimal 을 사용하는 방법밖에 없다. + double distance = 0.0001; Coordinate coordinate = Coordinate.of(latitude, longitude); Address address = new Address( "parcel", @@ -51,10 +49,10 @@ void findAllByRectangle_Success(double latitude, double longitude) { static Stream coordinates_Success() { return Stream.of( - Arguments.of(34.9999, 126.999), - Arguments.of(35.0001, 126.999), - Arguments.of(34.9999, 127.000), - Arguments.of(35.0001, 127.000) + Arguments.of(34.9999, 126.9999), + Arguments.of(35.0001, 126.9999), + Arguments.of(34.9999, 127.0001), + Arguments.of(35.0001, 127.0001) ); } @@ -89,10 +87,10 @@ void findAllByRectangle_Fail(double latitude, double longitude) { static Stream coordinates_Fail() { return Stream.of( - Arguments.of(34.9999, 126.999), - Arguments.of(35.0001, 126.999), - Arguments.of(34.9998, 127.000), - Arguments.of(35.0002, 127.000) + Arguments.of(34.9998, 126.9998), + Arguments.of(35.0002, 126.9998), + Arguments.of(34.9998, 127.0002), + Arguments.of(35.0002, 127.0002) ); } From 6626b7e3757c7ade795f4c832ed386419356a4fc Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 1 Aug 2023 21:57:15 +0900 Subject: [PATCH 34/88] =?UTF-8?q?feat:=20=EB=A9=A4=EB=B2=84=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=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 --- .../application/MemberCommandService.java | 4 ++++ .../application/MemberQueryService.java | 11 +++++++++ .../dto/response/MemberDetailResponse.java | 22 ++++++++++++++++++ .../member/dto/response/MemberResponse.java | 18 +++++++++++++++ .../member/presentation/MemberController.java | 23 +++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index a8b0cecc8..8b9281249 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -1,6 +1,9 @@ package com.mapbefine.mapbefine.member.application; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -13,4 +16,5 @@ public class MemberCommandService { public MemberCommandService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index eb27532de..97d7303a5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -1,6 +1,9 @@ package com.mapbefine.mapbefine.member.application; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -13,4 +16,12 @@ public class MemberQueryService { public MemberQueryService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } + + public MemberDetailResponse findById(Long id) { + Member member = memberRepository.findById(id) + .orElseThrow(NoSuchElementException::new); + + return MemberDetailResponse.from(member); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java new file mode 100644 index 000000000..4aa17c409 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java @@ -0,0 +1,22 @@ +package com.mapbefine.mapbefine.member.dto.response; + +import com.mapbefine.mapbefine.member.domain.Member; +import java.time.LocalDateTime; + +public record MemberDetailResponse( + Long id, + String name, + String email, + String imageUrl, + LocalDateTime updateAt +) { + public static MemberDetailResponse from(Member member) { + return new MemberDetailResponse( + member.getId(), + member.getName(), + member.getEmail(), + member.getImageUrl(), + member.getUpdatedAt() + ); + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java new file mode 100644 index 000000000..3b63825f4 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java @@ -0,0 +1,18 @@ +package com.mapbefine.mapbefine.member.dto.response; + +import com.mapbefine.mapbefine.member.domain.Member; + +public record MemberResponse ( + Long id, + String name, + String email +) { + + public static MemberResponse from(Member member) { + return new MemberResponse( + member.getId(), + member.getName(), + member.getEmail() + ); + } +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 10e0ec0c7..4b76da879 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -1,5 +1,10 @@ package com.mapbefine.mapbefine.member.presentation; +import com.mapbefine.mapbefine.member.application.MemberCommandService; +import com.mapbefine.mapbefine.member.application.MemberQueryService; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -7,4 +12,22 @@ @RequestMapping("/members") public class MemberController { + private final MemberCommandService memberCommandService; + private final MemberQueryService memberQueryService; + + public MemberController( + MemberCommandService memberCommandService, + MemberQueryService memberQueryService + ) { + this.memberCommandService = memberCommandService; + this.memberQueryService = memberQueryService; + } + + @GetMapping("/{memberId}") + public ResponseEntity findMemberById(Long memberId) { + MemberDetailResponse response = memberQueryService.findById(memberId); + + return ResponseEntity.ok(response); + } + } From 02979b3f90438b10fba0178e1954664282ff5580 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 1 Aug 2023 22:00:24 +0900 Subject: [PATCH 35/88] =?UTF-8?q?feat:=20=EB=A9=A4=EB=B2=84=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/member/application/MemberQueryService.java | 9 +++++++++ .../mapbefine/member/presentation/MemberController.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 97d7303a5..d03b742fa 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -3,6 +3,8 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import java.util.List; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,4 +26,11 @@ public MemberDetailResponse findById(Long id) { return MemberDetailResponse.from(member); } + public List findAll() { + return memberRepository.findAll() + .stream() + .map(MemberResponse::from) + .toList(); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 4b76da879..373c33085 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -3,6 +3,8 @@ import com.mapbefine.mapbefine.member.application.MemberCommandService; import com.mapbefine.mapbefine.member.application.MemberQueryService; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,4 +32,11 @@ public ResponseEntity findMemberById(Long memberId) { return ResponseEntity.ok(response); } + @GetMapping + public ResponseEntity> findAllMember() { + List responses = memberQueryService.findAll(); + + return ResponseEntity.ok(responses); + } + } From be59142c735d6c0f0fcc1dd1feb819941017ca4d Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 09:50:55 +0900 Subject: [PATCH 36/88] =?UTF-8?q?feat=20:=20Member=20=EB=A5=BC=20Create=20?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberCommandService.java | 14 +++ .../mapbefine/member/domain/Member.java | 64 +++++++++++-- .../mapbefine/member/domain/MemberInfo.java | 95 +++++++++++++++++++ .../member/domain/MemberRepository.java | 3 +- .../mapbefine/member/domain/Role.java | 16 ++++ .../dto/request/MemberCreateRequest.java | 11 +++ .../dto/response/MemberDetailResponse.java | 1 + .../member/dto/response/MemberResponse.java | 1 + .../member/presentation/MemberController.java | 11 +++ .../mapbefine/member/MemberFixture.java | 6 +- 10 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index 8b9281249..269c9d24b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -1,7 +1,9 @@ package com.mapbefine.mapbefine.member.application; +import com.mapbefine.mapbefine.common.entity.Image; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; @@ -17,4 +19,16 @@ public MemberCommandService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } + public Long save(MemberCreateRequest request) { + Member member = Member.of( + request.name(), + request.email(), + request.imageUrl(), + request.role() + ); + + return memberRepository.save(member) + .getId(); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 57cfa60f6..23e6c5f7f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -3,6 +3,8 @@ import static lombok.AccessLevel.PROTECTED; import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; +import com.mapbefine.mapbefine.common.entity.Image; +import com.mapbefine.mapbefine.common.util.RegexUtil; import com.mapbefine.mapbefine.topic.domain.Topic; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -22,6 +24,9 @@ @Getter public class Member extends BaseTimeEntity { + private static final int MAX_NAME_LENGTH = 20; + private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -33,7 +38,7 @@ public class Member extends BaseTimeEntity { private String email; @Column(nullable = false) - private String imageUrl; + private Image imageUrl; @Enumerated(EnumType.STRING) @Column(nullable = false) @@ -45,10 +50,10 @@ public class Member extends BaseTimeEntity { @OneToMany(mappedBy = "member") private List topicsWithPermission = new ArrayList<>(); - public Member( + private Member( String name, String email, - String imageUrl, + Image imageUrl, Role role ) { this.name = name; @@ -57,9 +62,52 @@ public Member( this.role = role; } - public void update(String name, String imageUrl) { + public static Member of( + String name, + String email, + String imageUrl, + Role role + ) { + validateName(name); + validateEmail(email); + validateRole(role); + + return new Member( + name, + email, + Image.of(imageUrl), + role + ); + } + + public void update(String name, String email, String imageUrl) { + validateName(name); + validateEmail(email); + this.name = name; - this.imageUrl = imageUrl; + this.email = email; + this.imageUrl = Image.of(imageUrl); + } + + private static void validateName(String name) { + if (name == null) { + throw new IllegalArgumentException("name null"); + } + if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException("이름 길이 이상"); + } + } + + private static void validateEmail(String email) { + if (!RegexUtil.matches(VALID_EMAIL_URL_REGEX, email)) { + throw new IllegalArgumentException("올바르지 않은 이메일 형식입니다."); + } + } + + private static void validateRole(Role role) { + if (role == null) { + throw new IllegalArgumentException("role null"); + } } public void addTopic(Topic topic) { @@ -67,7 +115,7 @@ public void addTopic(Topic topic) { } public String getRoleKey() { - return this.role.getKey(); + return role.getKey(); } public boolean isAdmin() { @@ -78,6 +126,10 @@ public boolean isUser() { return role == Role.USER; } + public String getImageUrl() { + return imageUrl.getImageUrl(); + } + public List getTopicsWithPermission() { return topicsWithPermission.stream() .map(MemberTopicPermission::getTopic) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java new file mode 100644 index 000000000..8b616447d --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -0,0 +1,95 @@ +package com.mapbefine.mapbefine.member.domain; + +import static lombok.AccessLevel.PROTECTED; + +import com.mapbefine.mapbefine.common.entity.Image; +import com.mapbefine.mapbefine.common.util.RegexUtil; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Embeddable +@NoArgsConstructor(access = PROTECTED) +@Getter +public class MemberInfo { + + private static final int MAX_NAME_LENGTH = 20; + private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; + + @Column(nullable = false, length = 20) + private String name; + + @Column(nullable = false) + private String email; + + @Column(nullable = false) + private Image imageUrl; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private Role role; + + private MemberInfo( + String name, + String email, + Image imageUrl, + Role role + ) { + this.name = name; + this.email = email; + this.imageUrl = imageUrl; + this.role = role; + } + + public static MemberInfo of( + String name, + String email, + String imageUrl, + Role role + ) { + validateName(name); + validateEmail(email); + validateRole(role); + + return new MemberInfo( + name, + email, + Image.of(imageUrl), + role + ); + } + + public void update(String name, String email, String imageUrl) { + validateName(name); + validateEmail(email); + + this.name = name; + this.email = email; + this.imageUrl = Image.of(imageUrl); + } + + private static void validateName(String name) { + if (name == null) { + throw new IllegalArgumentException("name null"); + } + if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException("이름 길이 이상"); + } + } + + private static void validateEmail(String email) { + if (!RegexUtil.matches(VALID_EMAIL_URL_REGEX, email)) { + throw new IllegalArgumentException("올바르지 않은 이메일 형식입니다."); + } + } + + private static void validateRole(Role role) { + if (role == null) { + throw new IllegalArgumentException("role null"); + } + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index a09fbfc27..fe729a718 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -2,8 +2,9 @@ import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -public interface MemberRepository extends JpaRepository { +public interface MemberRepository extends JpaRepository, JpaSpecificationExecutor { Optional findByEmail(String email); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java index abf162920..9222f5248 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Role.java @@ -1,5 +1,8 @@ package com.mapbefine.mapbefine.member.domain; +import com.fasterxml.jackson.annotation.JsonCreator; +import java.util.Arrays; +import java.util.NoSuchElementException; import lombok.Getter; @Getter @@ -17,4 +20,17 @@ public enum Role { this.title = title; } + @JsonCreator + public static Role from(String input) { + return Arrays.stream(values()) + .filter(role -> isSameName(input, role)) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } + + public static boolean isSameName(String input, Role role) { + return role.name() + .equalsIgnoreCase(input); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java new file mode 100644 index 000000000..4e62aaee5 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java @@ -0,0 +1,11 @@ +package com.mapbefine.mapbefine.member.dto.request; + +import com.mapbefine.mapbefine.member.domain.Role; + +public record MemberCreateRequest( + String name, + String email, + String imageUrl, + Role role +) { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java index 4aa17c409..d85d9e523 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java @@ -1,6 +1,7 @@ package com.mapbefine.mapbefine.member.dto.response; import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberInfo; import java.time.LocalDateTime; public record MemberDetailResponse( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java index 3b63825f4..2237ba1cc 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java @@ -1,6 +1,7 @@ package com.mapbefine.mapbefine.member.dto.response; import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberInfo; public record MemberResponse ( Long id, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 373c33085..b34871b55 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -2,11 +2,14 @@ import com.mapbefine.mapbefine.member.application.MemberCommandService; import com.mapbefine.mapbefine.member.application.MemberQueryService; +import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import java.net.URI; import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -39,4 +42,12 @@ public ResponseEntity> findAllMember() { return ResponseEntity.ok(responses); } + @PostMapping + public ResponseEntity add(MemberCreateRequest request) { + Long savedId = memberCommandService.save(request); + + return ResponseEntity.created(URI.create("/members/" + savedId)).build(); + } + + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java index 8cab2465b..63013e403 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java @@ -6,10 +6,10 @@ public class MemberFixture { public static Member create(Role role) { - return new Member( + return Member.of( "member", - "member@naver.com", - "image.com", + "jakind@naver.com", + "https://map-befine-official.github.io/favicon.png", role ); } From 1d81886ac287bb55aba89bad666db86ffc327db2 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 10:09:40 +0900 Subject: [PATCH 37/88] =?UTF-8?q?feat=20:=20Member=20=EA=B0=80=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A0=20Topic=20=EB=93=A4=EC=9D=84=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/auth/domain/AuthMember.java | 1 + .../application/MemberQueryService.java | 20 ++++++++++++++++++- .../member/presentation/MemberController.java | 10 ++++++++++ .../topic/domain/TopicRepository.java | 2 ++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java index b10df29e3..9a87d3fa9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java @@ -60,4 +60,5 @@ private static List getCreatedTopics(Member member) { public Long getMemberId() { return memberId; } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index d03b742fa..e4d77b47a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -1,9 +1,13 @@ package com.mapbefine.mapbefine.member.application; +import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.List; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; @@ -14,9 +18,14 @@ public class MemberQueryService { private final MemberRepository memberRepository; + private final TopicRepository topicRepository; - public MemberQueryService(MemberRepository memberRepository) { + public MemberQueryService( + MemberRepository memberRepository, + TopicRepository topicRepository + ) { this.memberRepository = memberRepository; + this.topicRepository = topicRepository; } public MemberDetailResponse findById(Long id) { @@ -33,4 +42,13 @@ public List findAll() { .toList(); } + public List findTopicByMember(final AuthMember authMember) { + Long memberId = authMember.getMemberId(); + List topicsByCreator = topicRepository.findByCreatorId(memberId); + + return topicsByCreator.stream() + .map(TopicResponse::from) + .toList(); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index b34871b55..c2aba82fb 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -1,10 +1,12 @@ package com.mapbefine.mapbefine.member.presentation; +import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.member.application.MemberCommandService; import com.mapbefine.mapbefine.member.application.MemberQueryService; import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.net.URI; import java.util.List; import org.springframework.http.ResponseEntity; @@ -49,5 +51,13 @@ public ResponseEntity add(MemberCreateRequest request) { return ResponseEntity.created(URI.create("/members/" + savedId)).build(); } + // TODO: 2023/08/02 Member 가 만든 토픽 조회 + @GetMapping("/topics") + public ResponseEntity> findTopicByMember(AuthMember authMember) { + List responses = memberQueryService.findTopicByMember(authMember); + return ResponseEntity.ok(responses); + } + + // TODO: 2023/08/02 Member 가 만든 핀들 조회 } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java index 9a5cf5722..10f9d0cd1 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java @@ -16,4 +16,6 @@ public interface TopicRepository extends JpaRepository { @Query("update Topic t set t.isDeleted = true where t.id = :topicId") void deleteById(@Param("topicId") Long topicId); + List findByCreatorId(Long creatorId); + } From 2dccd5f5bc5a57afdcd4b968c1cb7722445341f5 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 10:48:37 +0900 Subject: [PATCH 38/88] =?UTF-8?q?feat=20:=20Member=20=EA=B0=80=20=EB=B3=B8?= =?UTF-8?q?=EC=9D=B8=EC=9D=B4=20=EB=A7=8C=EB=93=A0=20Pin=20=EC=9D=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 --- .../auth/application/AuthService.java | 4 +- .../application/MemberQueryService.java | 18 +++- .../mapbefine/member/domain/Member.java | 84 ++++--------------- .../mapbefine/member/domain/MemberInfo.java | 4 + .../member/domain/MemberRepository.java | 4 +- .../dto/response/MemberDetailResponse.java | 8 +- .../member/dto/response/MemberResponse.java | 6 +- .../member/presentation/MemberController.java | 13 ++- .../mapbefine/mapbefine/pin/Domain/Pin.java | 6 +- .../mapbefine/pin/Domain/PinRepository.java | 2 + .../presentation/LocationControllerTest.java | 2 +- .../mapbefine/pin/PinIntegrationTest.java | 2 +- .../pin/presentation/PinControllerTest.java | 12 +-- .../mapbefine/topic/TopicIntegrationTest.java | 14 ++-- .../presentation/TopicControllerTest.java | 12 +-- 15 files changed, 85 insertions(+), 106 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java index ed5d313a0..eb2296141 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java @@ -23,11 +23,11 @@ public AuthService(MemberRepository memberRepository) { } public boolean isMember(AuthInfo authInfo) { - return memberRepository.existsByEmail(authInfo.email()); + return memberRepository.existsByMemberInfoEmail(authInfo.email()); } public AuthMember findAuthMemberByEmail(AuthInfo authInfo) { - return memberRepository.findByEmail(authInfo.email()) + return memberRepository.findByMemberInfoEmail(authInfo.email()) .map(this::convertToAuthMember) .orElseGet(Guest::new); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index e4d77b47a..141ff3563 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -5,6 +5,9 @@ import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; @@ -19,13 +22,16 @@ public class MemberQueryService { private final MemberRepository memberRepository; private final TopicRepository topicRepository; + private final PinRepository pinRepository; public MemberQueryService( MemberRepository memberRepository, - TopicRepository topicRepository + TopicRepository topicRepository, + PinRepository pinRepository ) { this.memberRepository = memberRepository; this.topicRepository = topicRepository; + this.pinRepository = pinRepository; } public MemberDetailResponse findById(Long id) { @@ -42,7 +48,7 @@ public List findAll() { .toList(); } - public List findTopicByMember(final AuthMember authMember) { + public List findTopicsByMember(final AuthMember authMember) { Long memberId = authMember.getMemberId(); List topicsByCreator = topicRepository.findByCreatorId(memberId); @@ -51,4 +57,12 @@ public List findTopicByMember(final AuthMember authMember) { .toList(); } + public List findPinsByMember(final AuthMember authMember) { + Long memberId = authMember.getMemberId(); + List pinsByCreator = pinRepository.findByCreatorId(memberId); + + return pinsByCreator.stream() + .map(PinResponse::from) + .toList(); + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 23e6c5f7f..447387870 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -3,13 +3,10 @@ import static lombok.AccessLevel.PROTECTED; import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; -import com.mapbefine.mapbefine.common.entity.Image; -import com.mapbefine.mapbefine.common.util.RegexUtil; +import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.topic.domain.Topic; -import jakarta.persistence.Column; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -31,35 +28,22 @@ public class Member extends BaseTimeEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false, length = 20) - private String name; - - @Column(nullable = false) - private String email; - - @Column(nullable = false) - private Image imageUrl; - - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private Role role; + @Embedded + private MemberInfo memberInfo; @OneToMany(mappedBy = "creator") private List createdTopic = new ArrayList<>(); + @OneToMany(mappedBy = "creator") + private List createdPin = new ArrayList<>(); + @OneToMany(mappedBy = "member") private List topicsWithPermission = new ArrayList<>(); private Member( - String name, - String email, - Image imageUrl, - Role role + MemberInfo memberInfo ) { - this.name = name; - this.email = email; - this.imageUrl = imageUrl; - this.role = role; + this.memberInfo = memberInfo; } public static Member of( @@ -68,46 +52,12 @@ public static Member of( String imageUrl, Role role ) { - validateName(name); - validateEmail(email); - validateRole(role); - - return new Member( - name, - email, - Image.of(imageUrl), - role - ); + MemberInfo memberInfo = MemberInfo.of(name, email, imageUrl, role); + return new Member(memberInfo); } public void update(String name, String email, String imageUrl) { - validateName(name); - validateEmail(email); - - this.name = name; - this.email = email; - this.imageUrl = Image.of(imageUrl); - } - - private static void validateName(String name) { - if (name == null) { - throw new IllegalArgumentException("name null"); - } - if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { - throw new IllegalArgumentException("이름 길이 이상"); - } - } - - private static void validateEmail(String email) { - if (!RegexUtil.matches(VALID_EMAIL_URL_REGEX, email)) { - throw new IllegalArgumentException("올바르지 않은 이메일 형식입니다."); - } - } - - private static void validateRole(Role role) { - if (role == null) { - throw new IllegalArgumentException("role null"); - } + memberInfo.update(name, email, imageUrl); } public void addTopic(Topic topic) { @@ -115,19 +65,15 @@ public void addTopic(Topic topic) { } public String getRoleKey() { - return role.getKey(); + return memberInfo.getRole().getKey(); } public boolean isAdmin() { - return role == Role.ADMIN; + return memberInfo.getRole() == Role.ADMIN; } public boolean isUser() { - return role == Role.USER; - } - - public String getImageUrl() { - return imageUrl.getImageUrl(); + return memberInfo.getRole() == Role.USER; } public List getTopicsWithPermission() { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index 8b616447d..981e4e201 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -92,4 +92,8 @@ private static void validateRole(Role role) { } } + public String getImageUrl() { + return imageUrl.getImageUrl(); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index fe729a718..b4ee0d144 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -6,8 +6,8 @@ public interface MemberRepository extends JpaRepository, JpaSpecificationExecutor { - Optional findByEmail(String email); + Optional findByMemberInfoEmail(String email); - boolean existsByEmail(String email); + boolean existsByMemberInfoEmail(String email); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java index d85d9e523..11d308669 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java @@ -12,11 +12,13 @@ public record MemberDetailResponse( LocalDateTime updateAt ) { public static MemberDetailResponse from(Member member) { + MemberInfo memberInfo = member.getMemberInfo(); + return new MemberDetailResponse( member.getId(), - member.getName(), - member.getEmail(), - member.getImageUrl(), + memberInfo.getName(), + memberInfo.getEmail(), + memberInfo.getImageUrl(), member.getUpdatedAt() ); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java index 2237ba1cc..701bdd313 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java @@ -10,10 +10,12 @@ public record MemberResponse ( ) { public static MemberResponse from(Member member) { + MemberInfo memberInfo = member.getMemberInfo(); + return new MemberResponse( member.getId(), - member.getName(), - member.getEmail() + memberInfo.getName(), + memberInfo.getEmail() ); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index c2aba82fb..60e742147 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -6,6 +6,7 @@ import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.net.URI; import java.util.List; @@ -51,13 +52,17 @@ public ResponseEntity add(MemberCreateRequest request) { return ResponseEntity.created(URI.create("/members/" + savedId)).build(); } - // TODO: 2023/08/02 Member 가 만든 토픽 조회 @GetMapping("/topics") - public ResponseEntity> findTopicByMember(AuthMember authMember) { - List responses = memberQueryService.findTopicByMember(authMember); + public ResponseEntity> findTopicsByMember(AuthMember authMember) { + List responses = memberQueryService.findTopicsByMember(authMember); return ResponseEntity.ok(responses); } - // TODO: 2023/08/02 Member 가 만든 핀들 조회 + @GetMapping("/pins") + public ResponseEntity> findPinsByMember(AuthMember authMember) { + List responses = memberQueryService.findPinsByMember(authMember); + + return ResponseEntity.ok(responses); + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java index 5628c67c9..397202285 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java @@ -5,6 +5,7 @@ import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; import com.mapbefine.mapbefine.location.domain.Address; import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.topic.domain.Topic; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -16,7 +17,6 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import lombok.Getter; @@ -35,6 +35,10 @@ public class Pin extends BaseTimeEntity { @Embedded private PinInfo pinInfo; + @ManyToOne + @JoinColumn(name = "member_id") + private Member creator; + @OneToMany(mappedBy = "pin", cascade = CascadeType.PERSIST) private List pinImages = new ArrayList<>(); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java index 50379fd4d..92a7357f2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java @@ -20,4 +20,6 @@ public interface PinRepository extends JpaRepository { List findAllByTopicId(Long topicId); + List findByCreatorId(Long creatorId); + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java index 0cca3dc05..a98a15da7 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java @@ -33,7 +33,7 @@ class LocationControllerTest extends RestDocsIntegration { void findBests() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); List responses = List.of(new TopicResponse( 1L, diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java index 21a5c6133..d01873a74 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java @@ -51,7 +51,7 @@ class PinIntegrationTest extends IntegrationTest { void saveTopicAndLocation() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); topic = topicRepository.save(TopicFixture.createByName("PinIntegration 토픽", member)); location = locationRepository.save(LocationFixture.createByCoordinate(37.5152933, 127.1029866)); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java index be163b8ec..6c6609fbf 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java @@ -42,7 +42,7 @@ class PinControllerTest extends RestDocsIntegration { void add() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); given(pinCommandService.save(any(), any())).willReturn(1L); @@ -70,7 +70,7 @@ void add() throws Exception { void update() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); PinUpdateRequest pinUpdateRequest = new PinUpdateRequest( @@ -92,7 +92,7 @@ void update() throws Exception { void delete() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); mockMvc.perform( MockMvcRequestBuilders.delete("/pins/1") @@ -105,7 +105,7 @@ void delete() throws Exception { void findById() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); PinDetailResponse pinDetailResponse = new PinDetailResponse( @@ -123,7 +123,7 @@ void findById() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/pins/1") -// .header(AUTHORIZATION, authHeader) + .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } @@ -133,7 +133,7 @@ void findById() throws Exception { void findAll() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); List pinResponses = List.of( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java index d70ea9bac..bcff05696 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java @@ -55,7 +55,7 @@ void createNewTopicWithoutPins_Success() { ); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); // when @@ -87,7 +87,7 @@ void createNewTopicWithPins_Success() { .toList(); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( @@ -113,7 +113,7 @@ void createMergeTopic_Success() { // given Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( @@ -167,7 +167,7 @@ void createMergeTopic_Success() { void updateTopic_Success() { Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); ExtractableResponse newTopic = createNewTopic( @@ -208,7 +208,7 @@ void deleteTopic_Success() { Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); ExtractableResponse newTopic = createNewTopic( new TopicCreateRequest( @@ -243,7 +243,7 @@ void findTopics_Success() { Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); // when @@ -266,7 +266,7 @@ void findTopicDetail_Success() { Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); TopicCreateRequest request = new TopicCreateRequest( "topicName", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java index 21ec02990..54977bd03 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java @@ -42,7 +42,7 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Imag void create() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); given(topicCommandService.createNew(any(), any())).willReturn(1L); @@ -68,7 +68,7 @@ void create() throws Exception { void mergeAndCreate() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); given(topicCommandService.createMerge(any(), any())).willReturn(1L); TopicMergeRequest topicMergeRequest = new TopicMergeRequest( @@ -93,7 +93,7 @@ void mergeAndCreate() throws Exception { void update() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); TopicUpdateRequest topicUpdateRequest = new TopicUpdateRequest("준팍의 안갈집", "https://map-befine-official.github.io/favicon.png", "준팍이 두번 다시 안갈집"); @@ -111,7 +111,7 @@ void update() throws Exception { void delete() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); mockMvc.perform( MockMvcRequestBuilders.delete("/topics/1") @@ -124,7 +124,7 @@ void delete() throws Exception { void findAll() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); List responses = List.of(new TopicResponse( 1L, @@ -152,7 +152,7 @@ void findAll() throws Exception { void findById() throws Exception { Member member = MemberFixture.create(Role.ADMIN); String authHeader = Base64.encodeBase64String( - String.format(BASIC_FORMAT, member.getEmail()).getBytes() + String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); TopicDetailResponse topicDetailResponse = new TopicDetailResponse( 1L, From 975fffdae76b514db2303aa9fa59e7a48c606498 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 12:01:36 +0900 Subject: [PATCH 39/88] =?UTF-8?q?feat=20:=20=ED=86=A0=ED=94=BD=EC=9D=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=9C=20=EC=9E=90=EA=B0=80=20=ED=8A=B9?= =?UTF-8?q?=EC=A0=95=20=EB=A9=A4=EB=B2=84=EC=97=90=EA=B2=8C=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=EC=9D=84=20=EC=A3=BC=EB=8A=94=20=EA=B8=B0=EB=8A=A5=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 --- .../application/MemberCommandService.java | 40 +++++++++++++++++-- .../mapbefine/member/domain/Member.java | 4 ++ .../member/domain/MemberRepository.java | 3 +- .../member/domain/MemberTopicPermission.java | 10 +++++ .../MemberTopicPermissionRepository.java | 6 +++ .../MemberTopicPermissionCreateRequest.java | 7 ++++ .../member/presentation/MemberController.java | 21 ++++++++++ .../mapbefine/topic/domain/Topic.java | 8 ++++ 8 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberTopicPermissionCreateRequest.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index 269c9d24b..6d024da2c 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -1,10 +1,15 @@ package com.mapbefine.mapbefine.member.application; -import com.mapbefine.mapbefine.common.entity.Image; +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.AuthTopic; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; -import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -14,9 +19,17 @@ public class MemberCommandService { private final MemberRepository memberRepository; + private final TopicRepository topicRepository; + private final MemberTopicPermissionRepository memberTopicPermissionRepository; - public MemberCommandService(MemberRepository memberRepository) { + public MemberCommandService( + MemberRepository memberRepository, + TopicRepository topicRepository, + MemberTopicPermissionRepository memberTopicPermissionRepository + ) { this.memberRepository = memberRepository; + this.topicRepository = topicRepository; + this.memberTopicPermissionRepository = memberTopicPermissionRepository; } public Long save(MemberCreateRequest request) { @@ -31,4 +44,25 @@ public Long save(MemberCreateRequest request) { .getId(); } + public Long saveMemberTopicPermission( + AuthMember authMember, + MemberTopicPermissionCreateRequest request + ) { + Member member = memberRepository.findById(request.memberId()) + .orElseThrow(NoSuchElementException::new); + Topic topic = topicRepository.findById(request.topicId()) + .orElseThrow(NoSuchElementException::new); + + validateMemberCanTopicUpdate(authMember, topic); + + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + return memberTopicPermissionRepository.save(memberTopicPermission).getId(); + } + + private void validateMemberCanTopicUpdate(AuthMember authMember, Topic topic) { + if (!authMember.canTopicUpdate(AuthTopic.from(topic))) { + throw new IllegalArgumentException("해당 유저는 해당 토픽에서 다른 유저에게 권한을 줄 수 없습니다."); + } + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 447387870..99e85dfed 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -82,4 +82,8 @@ public List getTopicsWithPermission() { .toList(); } + public void addMemberTopicPermission(MemberTopicPermission memberTopicPermission) { + topicsWithPermission.add(memberTopicPermission); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index b4ee0d144..ce532c1e5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -2,9 +2,8 @@ import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -public interface MemberRepository extends JpaRepository, JpaSpecificationExecutor { +public interface MemberRepository extends JpaRepository { Optional findByMemberInfoEmail(String email); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java index 6d1cf8297..5bab14767 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java @@ -35,4 +35,14 @@ public MemberTopicPermission(Topic topic, Member member) { this.member = member; } + public static MemberTopicPermission createPermissionAssociatedWithTopicAndMember( + Topic topic, + Member member + ) { + MemberTopicPermission memberTopicPermission = new MemberTopicPermission(topic, member); + topic.addMemberTopicPermission(memberTopicPermission); + member.addMemberTopicPermission(memberTopicPermission); + return memberTopicPermission; + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java new file mode 100644 index 000000000..f1773fd20 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java @@ -0,0 +1,6 @@ +package com.mapbefine.mapbefine.member.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberTopicPermissionRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberTopicPermissionCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberTopicPermissionCreateRequest.java new file mode 100644 index 000000000..55b3ea7d1 --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberTopicPermissionCreateRequest.java @@ -0,0 +1,7 @@ +package com.mapbefine.mapbefine.member.dto.request; + +public record MemberTopicPermissionCreateRequest( + Long topicId, + Long memberId +) { +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 60e742147..1443aca81 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -1,9 +1,11 @@ package com.mapbefine.mapbefine.member.presentation; import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.interceptor.LoginRequired; import com.mapbefine.mapbefine.member.application.MemberCommandService; import com.mapbefine.mapbefine.member.application.MemberQueryService; import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; +import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; @@ -65,4 +67,23 @@ public ResponseEntity> findPinsByMember(AuthMember authMember) return ResponseEntity.ok(responses); } + + // TODO: 2023/08/02 특정 멤버에게 권한을 주는 기능 (Creator만 가능) + @LoginRequired + @PostMapping("/permissions") + public ResponseEntity addMemberTopicPermission( + AuthMember authMember, + MemberTopicPermissionCreateRequest request + ) { + Long savedId = memberCommandService.saveMemberTopicPermission(authMember, request); + + return ResponseEntity.created(URI.create("/members/permissions/" + savedId)).build(); + } + + // TODO: 2023/08/02 특정 멤버의 권한을 삭제하는 기능 (Creator만 가능) + + // TODO: 2023/08/02 권한이 있는 멤버들을 읽어오는 API (로그인 유저만) + + // TODO: 2023/08/02 특정 멤버의 권한을 확인하는 기능 (로그인 유저만 가능) + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java index 9eab1dc81..e8169c8c6 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -4,6 +4,7 @@ import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; import com.mapbefine.mapbefine.pin.Domain.Pin; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; @@ -40,6 +41,9 @@ public class Topic extends BaseTimeEntity { @JoinColumn(name = "member_id") private Member creator; + @OneToMany(mappedBy = "topic") + private List memberTopicPermissions = new ArrayList<>(); + @OneToMany(mappedBy = "topic", cascade = CascadeType.PERSIST) private List pins = new ArrayList<>(); @@ -101,4 +105,8 @@ public void addPin(Pin pin) { pins.add(pin); } + public void addMemberTopicPermission(MemberTopicPermission memberTopicPermission) { + memberTopicPermissions.add(memberTopicPermission); + } + } From 6cc09a4cccab4c71ee20c7a78a0d0a693c5a7105 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 12:08:46 +0900 Subject: [PATCH 40/88] =?UTF-8?q?feat=20:=20=ED=86=A0=ED=94=BD=EC=9D=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=9C=EC=9E=90=EA=B0=80=20=ED=8A=B9?= =?UTF-8?q?=EC=A0=95=20=EB=A9=A4=EB=B2=84=EC=9D=98=20=EA=B6=8C=ED=95=9C?= =?UTF-8?q?=EC=9D=84=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberCommandService.java | 10 ++++++++++ .../member/presentation/MemberController.java | 14 +++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index 6d024da2c..f8b8c1d3a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -60,9 +60,19 @@ public Long saveMemberTopicPermission( return memberTopicPermissionRepository.save(memberTopicPermission).getId(); } + public void deleteMemberTopicPermission(final AuthMember authMember, final Long permissionId) { + MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) + .orElseThrow(NoSuchElementException::new); + + validateMemberCanTopicUpdate(authMember, memberTopicPermission.getTopic()); + + memberTopicPermissionRepository.delete(memberTopicPermission); + } + private void validateMemberCanTopicUpdate(AuthMember authMember, Topic topic) { if (!authMember.canTopicUpdate(AuthTopic.from(topic))) { throw new IllegalArgumentException("해당 유저는 해당 토픽에서 다른 유저에게 권한을 줄 수 없습니다."); } } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 1443aca81..380167ede 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -13,8 +13,11 @@ import java.net.URI; import java.util.List; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -68,19 +71,24 @@ public ResponseEntity> findPinsByMember(AuthMember authMember) return ResponseEntity.ok(responses); } - // TODO: 2023/08/02 특정 멤버에게 권한을 주는 기능 (Creator만 가능) @LoginRequired @PostMapping("/permissions") public ResponseEntity addMemberTopicPermission( AuthMember authMember, - MemberTopicPermissionCreateRequest request + @RequestBody MemberTopicPermissionCreateRequest request ) { Long savedId = memberCommandService.saveMemberTopicPermission(authMember, request); return ResponseEntity.created(URI.create("/members/permissions/" + savedId)).build(); } - // TODO: 2023/08/02 특정 멤버의 권한을 삭제하는 기능 (Creator만 가능) + @LoginRequired + @DeleteMapping("/permissions/{permissionId}") + public ResponseEntity deleteMemberTopicPermission(AuthMember authMember, @PathVariable Long permissionId) { + memberCommandService.deleteMemberTopicPermission(authMember, permissionId); + + return ResponseEntity.noContent().build(); + } // TODO: 2023/08/02 권한이 있는 멤버들을 읽어오는 API (로그인 유저만) From dc90aa57f056d0b3466265675e8b36e8e6d53f9e Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 12:21:20 +0900 Subject: [PATCH 41/88] =?UTF-8?q?feat=20:=20=ED=95=B4=EB=8B=B9=20=ED=86=A0?= =?UTF-8?q?=ED=94=BD=EC=97=90=20=EA=B6=8C=ED=95=9C=EC=9D=84=20=EA=B0=80?= =?UTF-8?q?=EC=A7=84=20=EB=AA=A8=EB=93=A0=20=EC=9C=A0=EC=A0=80=EB=A5=BC=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 --- .../member/application/MemberQueryService.java | 17 ++++++++++++++++- .../domain/MemberTopicPermissionRepository.java | 4 ++++ .../member/presentation/MemberController.java | 8 +++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 141ff3563..2f3fb2ae8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -3,6 +3,8 @@ import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.pin.Domain.Pin; @@ -23,15 +25,19 @@ public class MemberQueryService { private final MemberRepository memberRepository; private final TopicRepository topicRepository; private final PinRepository pinRepository; + private final MemberTopicPermissionRepository memberTopicPermissionRepository; + public MemberQueryService( MemberRepository memberRepository, TopicRepository topicRepository, - PinRepository pinRepository + PinRepository pinRepository, + MemberTopicPermissionRepository memberTopicPermissionRepository ) { this.memberRepository = memberRepository; this.topicRepository = topicRepository; this.pinRepository = pinRepository; + this.memberTopicPermissionRepository = memberTopicPermissionRepository; } public MemberDetailResponse findById(Long id) { @@ -65,4 +71,13 @@ public List findPinsByMember(final AuthMember authMember) { .map(PinResponse::from) .toList(); } + + public List findAllWithPermission(Long topicId) { + return memberTopicPermissionRepository.findByTopicId(topicId) + .stream() + .map(MemberTopicPermission::getMember) + .map(MemberResponse::from) + .toList(); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java index f1773fd20..fde7b4a2c 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java @@ -1,6 +1,10 @@ package com.mapbefine.mapbefine.member.domain; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberTopicPermissionRepository extends JpaRepository { + + List findByTopicId(Long topicId); + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 380167ede..9065a428d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -90,7 +90,13 @@ public ResponseEntity deleteMemberTopicPermission(AuthMember authMember, @ return ResponseEntity.noContent().build(); } - // TODO: 2023/08/02 권한이 있는 멤버들을 읽어오는 API (로그인 유저만) + @LoginRequired + @GetMapping("/permissions/{topicId}") + public ResponseEntity> findAllMemberTopicPermission(@PathVariable Long topicId) { + List responses = memberQueryService.findAllWithPermission(topicId); + + return ResponseEntity.ok(responses); + } // TODO: 2023/08/02 특정 멤버의 권한을 확인하는 기능 (로그인 유저만 가능) From a78a348c46236363e43f69849cba51195f6a5bc6 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 12:28:04 +0900 Subject: [PATCH 42/88] =?UTF-8?q?feat=20:=20=EA=B6=8C=ED=95=9C=EC=9D=84=20?= =?UTF-8?q?=EA=B0=80=EC=A7=84=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20ID=20?= =?UTF-8?q?=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/application/MemberQueryService.java | 7 +++++++ .../member/presentation/MemberController.java | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 2f3fb2ae8..539ba861a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -15,6 +15,7 @@ import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.List; import java.util.NoSuchElementException; +import java.util.Optional; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -80,4 +81,10 @@ public List findAllWithPermission(Long topicId) { .toList(); } + public MemberDetailResponse findMemberTopicPermissionById(final Long permissionId) { + MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) + .orElseThrow(NoSuchElementException::new); + + return MemberDetailResponse.from(memberTopicPermission.getMember()); + } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 9065a428d..408d2ad7c 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -12,6 +12,7 @@ import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.net.URI; import java.util.List; +import org.apache.coyote.Response; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -92,12 +93,18 @@ public ResponseEntity deleteMemberTopicPermission(AuthMember authMember, @ @LoginRequired @GetMapping("/permissions/{topicId}") - public ResponseEntity> findAllMemberTopicPermission(@PathVariable Long topicId) { + public ResponseEntity> findMemberTopicPermissionAll(@PathVariable Long topicId) { List responses = memberQueryService.findAllWithPermission(topicId); return ResponseEntity.ok(responses); } - // TODO: 2023/08/02 특정 멤버의 권한을 확인하는 기능 (로그인 유저만 가능) + @LoginRequired + @GetMapping("/permissions/{permissionId}") + public ResponseEntity findMemberTopicPermissionById(@PathVariable Long permissionId) { + MemberDetailResponse response = memberQueryService.findMemberTopicPermissionById(permissionId); + + return ResponseEntity.ok(response); + } } From 426ad350fdffcc0281dd2773e5a7fd5d9e75cfac Mon Sep 17 00:00:00 2001 From: junpakPark Date: Wed, 2 Aug 2023 14:36:44 +0900 Subject: [PATCH 43/88] =?UTF-8?q?refactor:=20AuthTopic=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/auth/domain/AuthMember.java | 8 +-- .../mapbefine/auth/domain/AuthTopic.java | 39 ------------ .../mapbefine/auth/domain/member/Admin.java | 10 +-- .../mapbefine/auth/domain/member/Guest.java | 14 +++-- .../mapbefine/auth/domain/member/User.java | 22 ++++--- .../application/LocationQueryService.java | 4 +- .../pin/application/PinCommandService.java | 23 ++----- .../pin/application/PinQueryService.java | 5 +- .../application/TopicCommandService.java | 8 +-- .../topic/application/TopicQueryService.java | 5 +- .../mapbefine/auth/domain/AuthTopicTest.java | 63 ------------------- 11 files changed, 44 insertions(+), 157 deletions(-) delete mode 100644 backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java delete mode 100644 backend/src/test/java/com/mapbefine/mapbefine/auth/domain/AuthTopicTest.java diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java index b10df29e3..02237ea3f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java @@ -49,13 +49,13 @@ private static List getCreatedTopics(Member member) { .toList(); } - public abstract boolean canRead(AuthTopic authTopic); + public abstract boolean canRead(Topic topic); - public abstract boolean canDelete(AuthTopic authTopic); + public abstract boolean canDelete(Topic topic); - public abstract boolean canTopicUpdate(AuthTopic authTopic); + public abstract boolean canTopicUpdate(Topic topic); - public abstract boolean canPinCreateOrUpdate(AuthTopic authTopic); + public abstract boolean canPinCreateOrUpdate(Topic topic); public Long getMemberId() { return memberId; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java deleted file mode 100644 index 572cec631..000000000 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthTopic.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.mapbefine.mapbefine.auth.domain; - -import com.mapbefine.mapbefine.topic.domain.Topic; -import com.mapbefine.mapbefine.topic.domain.TopicStatus; - -public class AuthTopic { - - private final Long topicId; - private final TopicStatus topicStatus; - - private AuthTopic(Long topicId, TopicStatus topicStatus) { - this.topicId = topicId; - this.topicStatus = topicStatus; - } - - public static AuthTopic from(Topic topic) { - return new AuthTopic(topic.getId(), topic.getTopicStatus()); - } - - public boolean isPublic() { - return topicStatus.isPublic(); - } - - public boolean isPrivate() { - return topicStatus.isPrivate(); - } - - public boolean isAllMembers() { - return topicStatus.isAllMembers(); - } - - public boolean isGroupOnly() { - return topicStatus.isGroupOnly(); - } - - public Long getTopicId() { - return topicId; - } -} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java index 1ef7a8812..3d97522c7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Admin.java @@ -1,7 +1,7 @@ package com.mapbefine.mapbefine.auth.domain.member; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.topic.domain.Topic; import java.util.Collections; public class Admin extends AuthMember { @@ -15,22 +15,22 @@ public Admin(Long memberId) { } @Override - public boolean canRead(AuthTopic authTopic) { + public boolean canRead(Topic topic) { return true; } @Override - public boolean canDelete(AuthTopic authTopic) { + public boolean canDelete(Topic topic) { return true; } @Override - public boolean canTopicUpdate(AuthTopic authTopic) { + public boolean canTopicUpdate(Topic topic) { return true; } @Override - public boolean canPinCreateOrUpdate(AuthTopic authTopic) { + public boolean canPinCreateOrUpdate(Topic topic) { return true; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java index 26eb9279f..6c8c0edcd 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/Guest.java @@ -1,7 +1,8 @@ package com.mapbefine.mapbefine.auth.domain.member; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicStatus; import java.util.Collections; public class Guest extends AuthMember { @@ -15,22 +16,23 @@ public Guest() { } @Override - public boolean canRead(AuthTopic authTopic) { - return authTopic.isPublic(); + public boolean canRead(Topic topic) { + TopicStatus topicStatus = topic.getTopicStatus(); + return topicStatus.isPublic(); } @Override - public boolean canDelete(AuthTopic authTopic) { + public boolean canDelete(Topic topic) { return false; } @Override - public boolean canTopicUpdate(AuthTopic authTopic) { + public boolean canTopicUpdate(Topic topic) { return false; } @Override - public boolean canPinCreateOrUpdate(AuthTopic authTopic) { + public boolean canPinCreateOrUpdate(Topic topic) { return false; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java index 1c284aa68..81612e75f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/member/User.java @@ -1,7 +1,8 @@ package com.mapbefine.mapbefine.auth.domain.member; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicStatus; import java.util.List; public class User extends AuthMember { @@ -19,23 +20,26 @@ public User( } @Override - public boolean canRead(AuthTopic authTopic) { - return authTopic.isPublic() || isGroup(authTopic.getTopicId()); + public boolean canRead(Topic topic) { + TopicStatus topicStatus = topic.getTopicStatus(); + return topicStatus.isPublic() || isGroup(topic.getId()); } @Override - public boolean canDelete(AuthTopic authTopic) { - return authTopic.isPrivate() && isCreator(authTopic.getTopicId()); + public boolean canDelete(Topic topic) { + TopicStatus topicStatus = topic.getTopicStatus(); + return topicStatus.isPrivate() && isCreator(topic.getId()); } @Override - public boolean canTopicUpdate(AuthTopic authTopic) { - return isCreator(authTopic.getTopicId()); + public boolean canTopicUpdate(Topic topic) { + return isCreator(topic.getId()); } @Override - public boolean canPinCreateOrUpdate(AuthTopic authTopic) { - return authTopic.isAllMembers() || hasPermission(authTopic.getTopicId()); + public boolean canPinCreateOrUpdate(Topic topic) { + TopicStatus topicStatus = topic.getTopicStatus(); + return topicStatus.isAllMembers() || hasPermission(topic.getId()); } private boolean isCreator(Long topicId) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java index 8351131fe..e77e28248 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java @@ -4,14 +4,12 @@ import static java.util.stream.Collectors.groupingBy; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; import com.mapbefine.mapbefine.location.domain.Location; import com.mapbefine.mapbefine.location.domain.LocationRepository; import com.mapbefine.mapbefine.location.dto.CoordinateRequest; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; -import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -55,7 +53,7 @@ private Map countTopicsInLocations(List locations) { private List sortTopicsByCounts(Map topicCounts, AuthMember member) { return topicCounts.entrySet().stream() - .filter(topicEntry -> member.canRead(AuthTopic.from(topicEntry.getKey()))) // TODO : 볼 수 있는 토픽만 걸러내는 과정 + .filter(topicEntry -> member.canRead(topicEntry.getKey())) .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .map(Map.Entry::getKey) .map(TopicResponse::from) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java index 9930e59c1..a5b8e7293 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java @@ -1,7 +1,6 @@ package com.mapbefine.mapbefine.pin.application; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; import com.mapbefine.mapbefine.location.domain.Address; import com.mapbefine.mapbefine.location.domain.Coordinate; import com.mapbefine.mapbefine.location.domain.Location; @@ -13,7 +12,6 @@ import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; -import java.util.List; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -35,23 +33,14 @@ public PinCommandService( this.locationRepository = locationRepository; this.topicRepository = topicRepository; } - public Long save(AuthMember member, PinCreateRequest request) { Coordinate coordinate = Coordinate.of(request.latitude(), request.longitude()); Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); - member.canPinCreateOrUpdate(AuthTopic.from(topic)); - - List all = locationRepository.findAllByCoordinateAndDistanceInMeters( - coordinate, 10.0); - - Location pinLocation = locationRepository.findAllByRectangle( - coordinate.getLatitude(), - coordinate.getLongitude(), - Coordinate.getDuplicateStandardDistance() - ) - .stream() - .filter(location -> location.isDuplicateCoordinate(coordinate)) + member.canPinCreateOrUpdate(topic); + + Location pinLocation = locationRepository.findAllByCoordinateAndDistanceInMeters( + coordinate, 10.0).stream() .filter(location -> location.isSameAddress(request.address())) .findFirst() .orElseGet(() -> saveLocation(request, coordinate)); @@ -89,7 +78,7 @@ public void update( ) { Pin pin = pinRepository.findById(pinId) .orElseThrow(NoSuchElementException::new); - member.canPinCreateOrUpdate(AuthTopic.from(pin.getTopic())); + member.canPinCreateOrUpdate(pin.getTopic()); pin.updatePinInfo(request.name(), request.description()); @@ -99,7 +88,7 @@ public void update( public void removeById(AuthMember member, Long pinId) { Pin pin = pinRepository.findById(pinId) .orElseThrow(NoSuchElementException::new); - member.canDelete(AuthTopic.from(pin.getTopic())); + member.canDelete(pin.getTopic()); pinRepository.deleteById(pinId); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java index 7b07df20c..94e9e17f0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java @@ -1,7 +1,6 @@ package com.mapbefine.mapbefine.pin.application; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; @@ -23,14 +22,14 @@ public PinQueryService(PinRepository pinRepository) { public List findAll(AuthMember member) { return pinRepository.findAll() .stream() - .filter(pin -> member.canRead(AuthTopic.from(pin.getTopic()))) + .filter(pin -> member.canRead(pin.getTopic())) .map(PinResponse::from) .toList(); } public PinDetailResponse findById(AuthMember member, Long pinId) { Pin pin = pinRepository.findById(pinId) - .filter(optionalPin -> member.canRead(AuthTopic.from(optionalPin.getTopic()))) + .filter(optionalPin -> member.canRead(optionalPin.getTopic())) .orElseThrow(NoSuchElementException::new); return PinDetailResponse.from(pin); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java index 46ef78984..3705567d5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java @@ -1,7 +1,6 @@ package com.mapbefine.mapbefine.topic.application; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.pin.Domain.Pin; @@ -67,7 +66,7 @@ public void updateTopicInfo( ) { Topic topic = topicRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); - member.canTopicUpdate(AuthTopic.from(topic)); + member.canTopicUpdate(topic); topic.updateTopicInfo( request.name(), @@ -79,7 +78,7 @@ public void updateTopicInfo( public void delete(AuthMember member, Long id) { Topic topic = topicRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 Topic입니다.")); - member.canDelete(AuthTopic.from(topic)); + member.canDelete(topic); pinRepository.deleteAllByTopicId(id); topicRepository.deleteById(id); @@ -88,8 +87,7 @@ public void delete(AuthMember member, Long id) { private List findTopicsByIds(AuthMember member, List topicIds) { return topicRepository.findAllById(topicIds) .stream() - .filter(topic -> member.canRead( - AuthTopic.from(topic))) // TODO : 일단, 이렇게 Merge 하기 이전에 canRead 한 놈들만 골라낼 수 있도록 했어요. + .filter(member::canRead) .toList(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java index e01a00525..72f8941a7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicQueryService.java @@ -1,7 +1,6 @@ package com.mapbefine.mapbefine.topic.application; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.auth.domain.AuthTopic; import com.mapbefine.mapbefine.location.domain.LocationRepository; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; @@ -24,7 +23,7 @@ public TopicQueryService(final TopicRepository topicRepository, LocationReposito public List findAll(AuthMember member) { return topicRepository.findAll().stream() - .filter(topic -> member.canRead(AuthTopic.from(topic))) + .filter(topic -> member.canRead(topic)) .map(TopicResponse::from) .toList(); } @@ -37,7 +36,7 @@ public List findAllByIds(List ids) { public TopicDetailResponse findById(AuthMember member, Long id) { Topic topic = topicRepository.findById(id) - .filter(presentTopic -> member.canRead(AuthTopic.from(presentTopic))) + .filter(member::canRead) .orElseThrow(() -> new IllegalArgumentException("해당하는 Topic이 존재하지 않습니다.")); return TopicDetailResponse.from(topic); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/auth/domain/AuthTopicTest.java b/backend/src/test/java/com/mapbefine/mapbefine/auth/domain/AuthTopicTest.java deleted file mode 100644 index 0adbcf896..000000000 --- a/backend/src/test/java/com/mapbefine/mapbefine/auth/domain/AuthTopicTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.mapbefine.mapbefine.auth.domain; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.mapbefine.mapbefine.member.MemberFixture; -import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.topic.TopicFixture; -import com.mapbefine.mapbefine.topic.domain.Topic; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -class AuthTopicTest { - - private Topic topic; - private AuthTopic authTopic; - - @BeforeEach - void setUp() { - topic = TopicFixture.createByName("도이의 독서실", MemberFixture.create(Role.USER)); - authTopic = AuthTopic.from(topic); - } - - @Test - @DisplayName("topic의 공개 범위가 Public일때, isPrivate은 false를 반환한다.") - void isPrivate() { - //when - boolean aPrivate = authTopic.isPrivate(); - - //then - assertThat(aPrivate).isFalse(); - } - - @Test - @DisplayName("topic의 공개 범위가 Public일때, isPublic은 true를 반환한다.") - void isPublic() { - //when - boolean aPublic = authTopic.isPublic(); - - //then - assertThat(aPublic).isTrue(); - } - - @Test - @DisplayName("topic의 권한이 allMembers일때, isAllMembers는 true를 반환한다.") - void isAllMembers() { - //when - boolean allMembers = authTopic.isAllMembers(); - - //then - assertThat(allMembers).isTrue(); - } - - @Test - @DisplayName("topic의 권한이 GroupOnly일때, isGroupOnly는 false를 반환한다.") - void isGroupOnly() { - //when - boolean groupOnly = authTopic.isGroupOnly(); - - //then - assertThat(groupOnly).isFalse(); - } -} From 1a825b53a7f5817d8504f692d5cf18b9f2e3a647 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 14:58:39 +0900 Subject: [PATCH 44/88] =?UTF-8?q?feat=20:=20Topic,=20Pin,=20Member=20?= =?UTF-8?q?=EC=97=90=20=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84=20=ED=8E=B8?= =?UTF-8?q?=EC=9D=98=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/member/domain/Member.java | 13 +++++++----- .../member/presentation/MemberController.java | 7 +++++-- .../mapbefine/mapbefine/pin/Domain/Pin.java | 21 +++++++++++++++++++ .../mapbefine/topic/domain/Topic.java | 21 +++++++++++++++++++ 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 99e85dfed..1217c5f40 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -64,6 +64,14 @@ public void addTopic(Topic topic) { createdTopic.add(topic); } + public void addPin(Pin pin) { + createdPin.add(pin); + } + + public void addMemberTopicPermission(MemberTopicPermission memberTopicPermission) { + topicsWithPermission.add(memberTopicPermission); + } + public String getRoleKey() { return memberInfo.getRole().getKey(); } @@ -71,7 +79,6 @@ public String getRoleKey() { public boolean isAdmin() { return memberInfo.getRole() == Role.ADMIN; } - public boolean isUser() { return memberInfo.getRole() == Role.USER; } @@ -82,8 +89,4 @@ public List getTopicsWithPermission() { .toList(); } - public void addMemberTopicPermission(MemberTopicPermission memberTopicPermission) { - topicsWithPermission.add(memberTopicPermission); - } - } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 408d2ad7c..ba5cc9f7d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -12,7 +12,6 @@ import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.net.URI; import java.util.List; -import org.apache.coyote.Response; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -37,13 +36,15 @@ public MemberController( this.memberQueryService = memberQueryService; } + @LoginRequired @GetMapping("/{memberId}") - public ResponseEntity findMemberById(Long memberId) { + public ResponseEntity findMemberById(@PathVariable Long memberId) { MemberDetailResponse response = memberQueryService.findById(memberId); return ResponseEntity.ok(response); } + @LoginRequired @GetMapping public ResponseEntity> findAllMember() { List responses = memberQueryService.findAll(); @@ -58,6 +59,7 @@ public ResponseEntity add(MemberCreateRequest request) { return ResponseEntity.created(URI.create("/members/" + savedId)).build(); } + @LoginRequired @GetMapping("/topics") public ResponseEntity> findTopicsByMember(AuthMember authMember) { List responses = memberQueryService.findTopicsByMember(authMember); @@ -65,6 +67,7 @@ public ResponseEntity> findTopicsByMember(AuthMember authMem return ResponseEntity.ok(responses); } + @LoginRequired @GetMapping("/pins") public ResponseEntity> findPinsByMember(AuthMember authMember) { List responses = memberQueryService.findPinsByMember(authMember); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java index 397202285..5a3971796 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java @@ -81,6 +81,27 @@ public static Pin createPinAssociatedWithLocationAndTopic( return pin; } + public static Pin createPinAssociatedWithLocationAndTopicAndMember( + String name, + String description, + Location location, + Topic topic, + Member creator + ) { // 추가된 정적 팩토리 메서드 + PinInfo pinInfo = PinInfo.of(name, description); + + Pin pin = new Pin( + pinInfo, + location, + topic + ); + + location.addPin(pin); + topic.addPin(pin); + creator.addPin(pin); + return pin; + } + public void updatePinInfo(String name, String description) { pinInfo.update(name, description); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java index e8169c8c6..d89a5b3b6 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -78,7 +78,28 @@ public static Topic of( TopicStatus.of(publicity, permission), creator ); + } + + public static Topic createTopicAssociatedWithMember( + String name, + String description, + String imageUrl, + Publicity publicity, + Permission permission, + Member creator + ) { // 추가된 정적 팩토리 메서드 + Topic topic = new Topic( + TopicInfo.of( + name, + description, + imageUrl + ), + TopicStatus.of(publicity, permission), + creator + ); + creator.addTopic(topic); + return topic; } public void updateTopicInfo( From f8370c3779038254b05fffa3cd0d8d56db670394 Mon Sep 17 00:00:00 2001 From: junpakPark Date: Wed, 2 Aug 2023 15:47:38 +0900 Subject: [PATCH 45/88] =?UTF-8?q?refactor:=20RestDocs=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20Interceptor=20=EC=A1=B0=EA=B1=B4=EB=AC=B8=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 --- .../mapbefine/mapbefine/common/interceptor/AuthInterceptor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java index cd12c1a6a..d6dcbd25e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/common/interceptor/AuthInterceptor.java @@ -27,7 +27,7 @@ public boolean preHandle( HttpServletResponse response, Object handler ) throws Exception { - if (isLoginRequired((HandlerMethod) handler)) { + if ((handler instanceof HandlerMethod) && isLoginRequired((HandlerMethod) handler)) { return isMember(request); } return true; From 1520467b5232b71b76ca798a55fc2f1d12cea320 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 17:14:48 +0900 Subject: [PATCH 46/88] =?UTF-8?q?test=20:=20Permission=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EC=99=80=20=EA=B4=80=EB=A0=A8=EB=90=9C=20Domain=20Tes?= =?UTF-8?q?t=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 102 ++++++++++ .../auth/application/AuthService.java | 4 +- .../mapbefine/auth/domain/AuthMember.java | 4 +- .../mapbefine/member/domain/Member.java | 19 +- .../mapbefine/member/domain/MemberInfo.java | 4 + .../member/domain/MemberTopicPermission.java | 2 +- .../mapbefine/mapbefine/pin/Domain/Pin.java | 33 +--- .../pin/application/PinCommandService.java | 22 ++- .../application/TopicCommandService.java | 26 +-- .../mapbefine/topic/domain/Topic.java | 21 +-- .../application/LocationQueryServiceTest.java | 2 +- .../member/domain/MemberInfoTest.java | 177 ++++++++++++++++++ .../mapbefine/member/domain/MemberTest.java | 35 ++++ .../domain/MemberTopicPermissionTest.java | 54 ++++++ .../mapbefine/mapbefine/pin/PinFixture.java | 8 +- .../application/PinCommandServiceTest.java | 3 +- .../pin/application/PinQueryServiceTest.java | 7 +- .../mapbefine/pin/domain/PinImageTest.java | 6 +- .../pin/domain/PinRepositoryTest.java | 5 +- .../mapbefine/pin/domain/PinTest.java | 72 ++++++- .../mapbefine/topic/TopicFixture.java | 2 +- .../application/TopicCommandServiceTest.java | 4 +- .../application/TopicQueryServiceTest.java | 2 +- .../mapbefine/topic/domain/TopicTest.java | 40 +++- 24 files changed, 545 insertions(+), 109 deletions(-) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java diff --git a/README.md b/README.md index 977115fc8..15923c19b 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,105 @@ #### 질문을 두려워하지 마라 - 이해하지 못했는데 알겠다고 대답하지 말아요. - 모르는 건 죄가 아니지만 모르는 데 아는 척 하는 건 죄입니다. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +- [ ] 해당 Topic 의 Creator 가 특정 멤버에게 Permission 을 주는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [x] MemberInfo 생성 테스트 + - [x] Member 생성 테스트 + - [x] MemberTopicPermission 에 createPermissionAssociatedWithTopicAndMember 잘 되는지 테스트 (연관관계 잘 추가되었는지) + - [ ] Pin 의 정팩메를 사용할 때 Member 가 잘 추가 되는지 + - [ ] Topic 의 정팩메를 사용할 때 Member 가 잘 추가 되는지 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Admin 이 권한을 주는 경우 + - [ ] Creator 가 권한을 주는 경우 + - [ ] 그냥 일반 유저가 권한을 주려는 경우 (이 경우만 실패) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] Creator 가 권한을 주는 경우로 Controller Test 를 진행한다. + - [ ] RestDocs 작성 + - [ ] Creator 가 권한을 주는 경우로 Controller Mocking Test 를 진행한다. + +- [ ] 해당 Topic 의 Creator 가 특정 멤버의 Permission 을 삭제하는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + +- [ ] 해당 Topic 에 Permission 을 가진 이들을 조회하는 기능 (로그인 유저에 한해서 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + +- [ ] Member 를 Create 하는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + +- [ ] Member 를 findAll 하는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + +- [ ] Member ID 를 통해 조회하는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + +- [ ] Member 가 본인이 만든 핀을 조회하는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성c + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + +- [ ] Member 가 본인이 만든 토픽을 조회하는 기능 + - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) + - [ ] Domain 테스트 작성 + - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) + - [ ] Controller 테스트 작성 (happy case 만) + - [ ] RestDocs 작성 + + + diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java index eb2296141..804342ab9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/application/AuthService.java @@ -45,14 +45,14 @@ private AuthMember convertToAuthMember(Member member) { } private List getTopicsWithPermission(Member member) { - return member.getTopicsWithPermission() + return member.getTopicsWithPermissions() .stream() .map(Topic::getId) .toList(); } private List getCreatedTopics(Member member) { - return member.getCreatedTopic() + return member.getCreatedTopics() .stream() .map(Topic::getId) .toList(); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java index 9a87d3fa9..e5675938e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/auth/domain/AuthMember.java @@ -36,14 +36,14 @@ public static AuthMember from(Member member) { } private static List getTopicsWithPermission(Member member) { - return member.getTopicsWithPermission() + return member.getTopicsWithPermissions() .stream() .map(Topic::getId) .toList(); } private static List getCreatedTopics(Member member) { - return member.getCreatedTopic() + return member.getCreatedTopics() .stream() .map(Topic::getId) .toList(); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 1217c5f40..7e5c5d0e0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -21,9 +21,6 @@ @Getter public class Member extends BaseTimeEntity { - private static final int MAX_NAME_LENGTH = 20; - private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -32,13 +29,13 @@ public class Member extends BaseTimeEntity { private MemberInfo memberInfo; @OneToMany(mappedBy = "creator") - private List createdTopic = new ArrayList<>(); + private List createdTopics = new ArrayList<>(); @OneToMany(mappedBy = "creator") - private List createdPin = new ArrayList<>(); + private List createdPins = new ArrayList<>(); @OneToMany(mappedBy = "member") - private List topicsWithPermission = new ArrayList<>(); + private List topicsWithPermissions = new ArrayList<>(); private Member( MemberInfo memberInfo @@ -61,15 +58,15 @@ public void update(String name, String email, String imageUrl) { } public void addTopic(Topic topic) { - createdTopic.add(topic); + createdTopics.add(topic); } public void addPin(Pin pin) { - createdPin.add(pin); + createdPins.add(pin); } public void addMemberTopicPermission(MemberTopicPermission memberTopicPermission) { - topicsWithPermission.add(memberTopicPermission); + topicsWithPermissions.add(memberTopicPermission); } public String getRoleKey() { @@ -83,8 +80,8 @@ public boolean isUser() { return memberInfo.getRole() == Role.USER; } - public List getTopicsWithPermission() { - return topicsWithPermission.stream() + public List getTopicsWithPermissions() { + return topicsWithPermissions.stream() .map(MemberTopicPermission::getTopic) .toList(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index 981e4e201..0b6361a6a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -81,6 +81,10 @@ private static void validateName(String name) { } private static void validateEmail(String email) { + if (email == null) { + throw new IllegalArgumentException("email null"); + } + if (!RegexUtil.matches(VALID_EMAIL_URL_REGEX, email)) { throw new IllegalArgumentException("올바르지 않은 이메일 형식입니다."); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java index 5bab14767..865594823 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java @@ -30,7 +30,7 @@ public class MemberTopicPermission extends BaseTimeEntity { @JoinColumn(name = "member_id", nullable = false) private Member member; - public MemberTopicPermission(Topic topic, Member member) { + private MemberTopicPermission(Topic topic, Member member) { this.topic = topic; this.member = member; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java index 5a3971796..309188653 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java @@ -57,28 +57,13 @@ public class Pin extends BaseTimeEntity { private Pin( PinInfo pinInfo, Location location, - Topic topic + Topic topic, + Member creator ) { this.pinInfo = pinInfo; this.location = location; this.topic = topic; - } - - public static Pin createPinAssociatedWithLocationAndTopic( - String name, - String description, - Location location, - Topic topic - ) { - PinInfo pinInfo = PinInfo.of(name, description); - Pin pin = new Pin( - pinInfo, - location, - topic - ); - location.addPin(pin); - topic.addPin(pin); - return pin; + this.creator = creator; } public static Pin createPinAssociatedWithLocationAndTopicAndMember( @@ -87,13 +72,14 @@ public static Pin createPinAssociatedWithLocationAndTopicAndMember( Location location, Topic topic, Member creator - ) { // 추가된 정적 팩토리 메서드 + ) { PinInfo pinInfo = PinInfo.of(name, description); Pin pin = new Pin( pinInfo, location, - topic + topic, + creator ); location.addPin(pin); @@ -106,12 +92,13 @@ public void updatePinInfo(String name, String description) { pinInfo.update(name, description); } - public Pin copy(Topic topic) { - return Pin.createPinAssociatedWithLocationAndTopic( + public Pin copy(Topic topic, Member creator) { + return Pin.createPinAssociatedWithLocationAndTopicAndMember( pinInfo.getName(), pinInfo.getDescription(), location, - topic + topic, + creator ); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java index 9930e59c1..20905c1a1 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java @@ -6,6 +6,8 @@ import com.mapbefine.mapbefine.location.domain.Coordinate; import com.mapbefine.mapbefine.location.domain.Location; import com.mapbefine.mapbefine.location.domain.LocationRepository; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinImage; import com.mapbefine.mapbefine.pin.Domain.PinRepository; @@ -13,7 +15,6 @@ import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; -import java.util.List; import java.util.NoSuchElementException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,25 +26,27 @@ public class PinCommandService { private final PinRepository pinRepository; private final LocationRepository locationRepository; private final TopicRepository topicRepository; + private final MemberRepository memberRepository; public PinCommandService( PinRepository pinRepository, LocationRepository locationRepository, - TopicRepository topicRepository + TopicRepository topicRepository, + MemberRepository memberRepository ) { this.pinRepository = pinRepository; this.locationRepository = locationRepository; this.topicRepository = topicRepository; + this.memberRepository = memberRepository; } - public Long save(AuthMember member, PinCreateRequest request) { + public Long save(AuthMember authMember, PinCreateRequest request) { Coordinate coordinate = Coordinate.of(request.latitude(), request.longitude()); Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); - member.canPinCreateOrUpdate(AuthTopic.from(topic)); - - List all = locationRepository.findAllByCoordinateAndDistanceInMeters( - coordinate, 10.0); + Member member = memberRepository.findById(authMember.getMemberId()) + .orElseThrow(NoSuchElementException::new); + authMember.canPinCreateOrUpdate(AuthTopic.from(topic)); Location pinLocation = locationRepository.findAllByRectangle( coordinate.getLatitude(), @@ -56,11 +59,12 @@ public Long save(AuthMember member, PinCreateRequest request) { .findFirst() .orElseGet(() -> saveLocation(request, coordinate)); - Pin pin = Pin.createPinAssociatedWithLocationAndTopic( + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( request.name(), request.description(), pinLocation, - topic + topic, + member ); for (String pinImage : request.images()) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java index 46ef78984..4e73dee44 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java @@ -35,27 +35,31 @@ public TopicCommandService( this.memberRepository = memberRepository; } - public long createNew(AuthMember member, TopicCreateRequest request) { - Topic topic = createNewTopic(member, request); + public long createNew(AuthMember authMember, TopicCreateRequest request) { + Topic topic = createNewTopic(authMember, request); + Member member = memberRepository.findById(authMember.getMemberId()) + .orElseThrow(NoSuchElementException::new); List pinIds = request.pins(); List original = pinRepository.findAllById(pinIds); validateExist(pinIds.size(), original.size()); - pinRepository.saveAll(copyPins(original, topic)); + pinRepository.saveAll(copyPins(original, topic, member)); return topic.getId(); } - public long createMerge(AuthMember member, TopicMergeRequest request) { + public long createMerge(AuthMember authMember, TopicMergeRequest request) { List topicIds = request.topics(); - List topics = findTopicsByIds(member, topicIds); + List topics = findTopicsByIds(authMember, topicIds); + Member member = memberRepository.findById(authMember.getMemberId()) + .orElseThrow(NoSuchElementException::new); validateExist(topicIds.size(), topics.size()); - Topic topic = createMergeTopic(member, request); + Topic topic = createMergeTopic(authMember, request); List original = getPinFromTopics(topics); - pinRepository.saveAll(copyPins(original, topic)); + pinRepository.saveAll(copyPins(original, topic, member)); return topic.getId(); } @@ -102,7 +106,7 @@ private List getPinFromTopics(List topics) { private Topic createMergeTopic(AuthMember member, TopicMergeRequest request) { Member creator = findCreatorByAuthMember(member); - Topic topic = Topic.of( + Topic topic = Topic.createTopicAssociatedWithMember( request.name(), request.description(), request.image(), @@ -116,7 +120,7 @@ private Topic createMergeTopic(AuthMember member, TopicMergeRequest request) { private Topic createNewTopic(AuthMember member, TopicCreateRequest request) { Member creator = findCreatorByAuthMember(member); - Topic topic = Topic.of( + Topic topic = Topic.createTopicAssociatedWithMember( request.name(), request.description(), request.image(), @@ -138,9 +142,9 @@ private void validateExist(int idCount, int existCount) { } } - private List copyPins(List pins, Topic topic) { + private List copyPins(List pins, Topic topic, Member member) { return pins.stream() - .map(original -> original.copy(topic)) + .map(original -> original.copy(topic, member)) .toList(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java index d89a5b3b6..16766ebb6 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -61,25 +61,6 @@ private Topic( this.creator = creator; } - public static Topic of( - String name, - String description, - String imageUrl, - Publicity publicity, - Permission permission, - Member creator - ) { - return new Topic( - TopicInfo.of( - name, - description, - imageUrl - ), - TopicStatus.of(publicity, permission), - creator - ); - } - public static Topic createTopicAssociatedWithMember( String name, String description, @@ -87,7 +68,7 @@ public static Topic createTopicAssociatedWithMember( Publicity publicity, Permission permission, Member creator - ) { // 추가된 정적 팩토리 메서드 + ) { Topic topic = new Topic( TopicInfo.of( name, diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java index 12afb573b..853aa9169 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java @@ -61,7 +61,7 @@ void setup() { private Topic createAndSaveByNameAndPinCounts(String topicName, int pinCounts) { Topic topic = TopicFixture.createByName(topicName, member); for (int i = 0; i < pinCounts; i++) { - PinFixture.create(ALL_PINS_LOCATION, topic); + PinFixture.create(ALL_PINS_LOCATION, topic, member); } return topicRepository.save(topic); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java new file mode 100644 index 000000000..59533cc01 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java @@ -0,0 +1,177 @@ +package com.mapbefine.mapbefine.member.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +public class MemberInfoTest { + + @Nested + class Validate { + + private final String VALID_NAME = "member"; + private final String VALID_EMAIL = "member@naver.com"; + private final String VALID_IMAGE_URL = "https://map-befine-official.github.io/favicon.png"; + private final Role VALID_ROLE = Role.ADMIN; + + @Test + @DisplayName("정확한 값을 입력하면 객체가 생성된다") + void success() { + //given when + MemberInfo memberInfo = MemberInfo.of( + VALID_NAME, + VALID_EMAIL, + VALID_IMAGE_URL, + VALID_ROLE + ); + + //then + assertThat(memberInfo).isNotNull(); + assertThat(memberInfo.getName()).isEqualTo(VALID_NAME); + assertThat(memberInfo.getEmail()).isEqualTo(VALID_EMAIL); + assertThat(memberInfo.getImageUrl()).isEqualTo(VALID_IMAGE_URL); + assertThat(memberInfo.getRole()).isEqualTo(VALID_ROLE); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", "aaaaaaaaaaaaaaaaaaaaa"}) + @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") + void whenNameIsInvalid_thenFail(String invalidName) { + //given when then + assertThatThrownBy(() -> MemberInfo.of( + invalidName, + VALID_EMAIL, + VALID_IMAGE_URL, + VALID_ROLE + )).isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @NullSource + @EmptySource + @ValueSource(strings = "jakind") + @DisplayName("유효한 이메일이 아닌 경우 예외가 발생한다") + void whenEmailIsInvalid_thenFail(String invalidEmail) { + //given when then + assertThatThrownBy(() -> MemberInfo.of( + VALID_NAME, + invalidEmail, + VALID_IMAGE_URL, + VALID_ROLE + )).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("올바르지 않은 형식의 Image Url 이 들어오는 경우 예외가 발생한다.") + void whenImageUrlIsInvalid_thenFail() { + String invalidImageUrl = "image.png"; + + //given when then + assertThatThrownBy(() -> MemberInfo.of( + VALID_NAME, + VALID_EMAIL, + invalidImageUrl, + VALID_ROLE + )).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("유효하지 않은 Role 이 들어오는 경우 예외가 발생한다.") + void whenRoleIsInvalid_thenFail() { + String invalidImageUrl = "image.png"; + + //given when then + assertThatThrownBy(() -> MemberInfo.of( + VALID_NAME, + VALID_EMAIL, + invalidImageUrl, + VALID_ROLE + )).isInstanceOf(IllegalArgumentException.class); + } + + + } + + @Nested + class Update { + + private final String name = "member1"; + private final String email = "memberr@naver.com"; + private final String imageUrl = "https://map-befine-official.github.io/Matthew.png"; + + private final String VALID_NAME = "member"; + private final String VALID_EMAIL = "member@naver.com"; + private final String VALID_IMAGE_URL = "https://map-befine-official.github.io/favicon.png"; + private final Role VALID_ROLE = Role.ADMIN; + + private MemberInfo memberInfo; + + @BeforeEach + void setUp() { + memberInfo = MemberInfo.of( + VALID_NAME, + VALID_EMAIL, + VALID_IMAGE_URL, + VALID_ROLE + ); + } + + @Test + @DisplayName("정확한 값을 입력하면 객체가 수정된다") + void success() { + //when + memberInfo.update(name, email, imageUrl); + + //then + assertThat(memberInfo).isNotNull(); + assertThat(memberInfo.getName()).isEqualTo(name); + assertThat(memberInfo.getEmail()).isEqualTo(email); + assertThat(memberInfo.getImageUrl()).isEqualTo(imageUrl); + } + + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", "aaaaaaaaaaaaaaaaaaaaa"}) + @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") + void whenNameIsInvalid_thenFail(String invalidName) { + // given when then + assertThatThrownBy( + () -> memberInfo.update(invalidName, email, imageUrl) + ).isInstanceOf(IllegalArgumentException.class); + } + + @ParameterizedTest + @NullSource + @EmptySource + @DisplayName("유효한 email 아닌 경우 예외가 발생한다") + void whenEmailIsInvalid_thenFail(String invalidEmail) { + // given when then + assertThatThrownBy( + () -> memberInfo.update(name, invalidEmail, imageUrl) + ).isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("유효한 Image Url 이 아닌 경우 예외가 발생한다.") + void whenImageUrlIsInvalid_thenFail() { + // given + String invalidImageUrl = "image.png"; + // when then + assertThatThrownBy( + () -> memberInfo.update(name, email, invalidImageUrl) + ).isInstanceOf(IllegalArgumentException.class); + } + + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java new file mode 100644 index 000000000..baa016399 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java @@ -0,0 +1,35 @@ +package com.mapbefine.mapbefine.member.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MemberTest { + + @Test + @DisplayName("유효한 정보를 입력했을 때 객체가 정상 생성 된다.") + void createMember_success() { + // given + String name = "member"; + String email = "member@naver.com"; + String imageUrl = "https://map-befine-official.github.io/favicon.png"; + Role role = Role.ADMIN; + + // then + Member member = Member.of( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.ADMIN + ); + + // then + assertThat(member).isNotNull(); + assertThat(member.getMemberInfo().getName()).isEqualTo(name); + assertThat(member.getMemberInfo().getEmail()).isEqualTo(email); + assertThat(member.getMemberInfo().getImageUrl()).isEqualTo(imageUrl); + assertThat(member.getMemberInfo().getRole()).isEqualTo(role); + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java new file mode 100644 index 000000000..f31945826 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java @@ -0,0 +1,54 @@ +package com.mapbefine.mapbefine.member.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MemberTopicPermissionTest { + + @Test + @DisplayName("정상적인 값을 입력하면 객체가 생성된다.") + void createMemberTopicPermission() { + // given + Member member = MemberFixture.create(Role.ADMIN); + Topic topic = TopicFixture.createByName("topic", member); + + // when + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + + // then + assertThat(memberTopicPermission.getMember()).usingRecursiveComparison() + .isEqualTo(member); + assertThat(memberTopicPermission.getTopic()).usingRecursiveComparison() + .isEqualTo(topic); + } + + @Test + @DisplayName("MemberTopicPermission 을 생성하면, Topic 과 Member 에 등록이 된다.") + void createPermissionAssociatedWithTopicAndMember() { + // given + Member member = MemberFixture.create(Role.ADMIN); + Topic topic = TopicFixture.createByName("topic", member); + + // when + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + List topicsWithPermission = member.getTopicsWithPermissions(); + List memberTopicPermissions = topic.getMemberTopicPermissions(); + + // then + assertThat(topicsWithPermission).hasSize(1); + assertThat(memberTopicPermissions).hasSize(1); + assertThat(topicsWithPermission.get(0)).usingRecursiveComparison() + .isEqualTo(topic); + assertThat(memberTopicPermissions.get(0)).usingRecursiveComparison() + .isEqualTo(memberTopicPermission); + } + +} diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java index 47bf2721e..f87333bef 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java @@ -1,19 +1,21 @@ package com.mapbefine.mapbefine.pin; import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicInfo; public class PinFixture { - public static Pin create(Location location, Topic topic) { + public static Pin create(Location location, Topic topic, Member member) { TopicInfo topicInfo = topic.getTopicInfo(); - return Pin.createPinAssociatedWithLocationAndTopic( + return Pin.createPinAssociatedWithLocationAndTopicAndMember( topicInfo.getName() + "의 핀", "위도: " + location.getCoordinate().getLatitude() + ", 경도: " + location.getCoordinate().getLongitude(), location, - topic + topic, + member ); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java index 32553c70c..6370fcd2c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java @@ -21,7 +21,6 @@ import com.mapbefine.mapbefine.topic.domain.Publicity; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; -import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -66,7 +65,7 @@ void setUp() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); authMember = AuthMember.from(member); topic = topicRepository.save( - Topic.of( + Topic.createTopicAssociatedWithMember( "topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index 853d4663e..3858d4498 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -22,7 +22,6 @@ import com.mapbefine.mapbefine.topic.domain.Publicity; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; @@ -67,7 +66,7 @@ void setUp() { member = memberRepository.save(MemberFixture.create(Role.ADMIN)); authMember = AuthMember.from(member); topic = topicRepository.save( - Topic.of( + Topic.createTopicAssociatedWithMember( "topicName", "topicDescription", "https://map-befine-official.github.io/favicon.png", @@ -84,7 +83,7 @@ void findAll_Success() { // given List expected = new ArrayList<>(); for (int i = 0; i < 10; i++) { - Pin pin = Pin.createPinAssociatedWithLocationAndTopic("name", "description", location, topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); Long savedId = pinRepository.save(pin).getId(); expected.add(new PinResponse( savedId, @@ -108,7 +107,7 @@ void findAll_Success() { @DisplayName("핀의 Id 를 넘기면 핀을 가져온다.") void findById_Success() { // given - Pin pin = Pin.createPinAssociatedWithLocationAndTopic("name", "description", location, topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); PinImage.createPinImageAssociatedWithPin(BASE_IMAGES.get(0), pin); Long savedId = pinRepository.save(pin).getId(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java index 25f039ada..00c84308c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java @@ -5,6 +5,7 @@ import com.mapbefine.mapbefine.common.entity.Image; import com.mapbefine.mapbefine.location.LocationFixture; import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinImage; @@ -18,12 +19,13 @@ class PinImageTest { private Topic topic; private Pin pin; + private Member member; @BeforeEach void setUp() { topic = TopicFixture.createByName("아이크의 부잣집", MemberFixture.create(Role.USER)); - pin = PinFixture.create(LocationFixture.create(), topic); - + member = MemberFixture.create(Role.ADMIN); + pin = PinFixture.create(LocationFixture.create(), topic, member); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java index afdcf5260..8995772f9 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java @@ -15,7 +15,6 @@ import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; -import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -59,7 +58,7 @@ void deleteById_Success() { topicRepository.save(topic); locationRepository.save(location); - Pin pin = Pin.createPinAssociatedWithLocationAndTopic("name", "description", location, topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); pinRepository.save(pin); // when @@ -88,7 +87,7 @@ void deleteAllByTopicId_Success() { ); for (int i = 0; i < 10; i++) { - Pin.createPinAssociatedWithLocationAndTopic("name", "description", location, topic); + Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); } locationRepository.save(location); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java index 17f6bf047..f7fa6257e 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java @@ -1,22 +1,25 @@ package com.mapbefine.mapbefine.pin.domain; -import static com.mapbefine.mapbefine.pin.Domain.Pin.createPinAssociatedWithLocationAndTopic; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.mapbefine.mapbefine.location.LocationFixture; import com.mapbefine.mapbefine.location.domain.Address; import com.mapbefine.mapbefine.location.domain.Coordinate; import com.mapbefine.mapbefine.location.domain.Location; import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinInfo; +import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Permission; import com.mapbefine.mapbefine.topic.domain.Publicity; import com.mapbefine.mapbefine.topic.domain.Topic; -import java.math.BigDecimal; +import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -34,7 +37,7 @@ class PinTest { 127.123456 ) ); - private static final Topic topic = Topic.of( + private static final Topic topic = Topic.createTopicAssociatedWithMember( "topicName", "topicDescription", null, @@ -42,13 +45,25 @@ class PinTest { Permission.ALL_MEMBERS, MemberFixture.create(Role.ADMIN) ); + private static final Member member = Member.of( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.ADMIN + ); @ParameterizedTest @MethodSource(value = "validNameAndDescription") @DisplayName("올바른 정보를 주면 성공적으로 Pin 을 생성한다.") void createPinAssociatedWithLocationAndTopic_Success(String name, String description) { // given - Pin pin = createPinAssociatedWithLocationAndTopic(name, description, location, topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( + name, + description, + location, + topic, + member + ); PinInfo pinInfo = pin.getPinInfo(); @@ -66,8 +81,13 @@ void createPinAssociatedWithLocationAndTopic_Success(String name, String descrip @DisplayName("잘못된 정보를 주면 Pin 을 생성을 실패한다.") void createPinAssociatedWithLocationAndTopic_Fail(String name, String description) { // given when then - assertThatThrownBy(() -> Pin.createPinAssociatedWithLocationAndTopic(name, description, location, topic)) - .isInstanceOf(IllegalArgumentException.class); + assertThatThrownBy(() -> Pin.createPinAssociatedWithLocationAndTopicAndMember( + name, + description, + location, + topic, + member + )).isInstanceOf(IllegalArgumentException.class); } @ParameterizedTest @@ -75,7 +95,7 @@ void createPinAssociatedWithLocationAndTopic_Fail(String name, String descriptio @DisplayName("정상적인 정보를 통해 Update 를 진행하면 Pin 의 정보가 정상적으로 수정된다.") void update_Success(String name, String description) { // given - Pin pin = createPinAssociatedWithLocationAndTopic("name", "description", location, topic); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); // when pin.updatePinInfo(name, description); @@ -102,11 +122,12 @@ static Stream validNameAndDescription() { @DisplayName("정상적인 정보를 통해 Update 를 진행하면 Pin 의 수정을 실패한다.") void update_Fail(String name, String description) { // given - Pin pin = Pin.createPinAssociatedWithLocationAndTopic( + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( "name", "description", location, - topic + topic, + member ); // when then @@ -114,6 +135,39 @@ void update_Fail(String name, String description) { .isInstanceOf(IllegalArgumentException.class); } + @Test + @DisplayName("Pin 을 생성하면, Location, Topic, Member 에 등록이 된다.") + void createPinAssociatedWithLocationAndTopicAndMember() { + // given + Member mockMember = MemberFixture.create(Role.ADMIN); + Topic mockTopic = TopicFixture.createByName("topicName", mockMember); + Location mockLocation = LocationFixture.create(); + + // when + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( + "name", + "description", + mockLocation, + mockTopic, + mockMember + ); + + List pinsInLocation = mockLocation.getPins(); + List pinsInTopic = mockTopic.getPins(); + List pinsInMember = mockMember.getCreatedPins(); + + // then + assertThat(pinsInLocation).hasSize(1); + assertThat(pinsInTopic).hasSize(1); + assertThat(pinsInMember).hasSize(1); + assertThat(pinsInLocation.get(0)).usingRecursiveComparison() + .isEqualTo(pin); + assertThat(pinsInTopic.get(0)).usingRecursiveComparison() + .isEqualTo(pin); + assertThat(pinsInMember.get(0)).usingRecursiveComparison() + .isEqualTo(pin); + } + static Stream invalidNameOrDescription() { return Stream.of( Arguments.of(null, "1"), diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java index eeb70519e..38f621ad1 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicFixture.java @@ -9,7 +9,7 @@ public class TopicFixture { public static Topic createByName(String name, Member member) { - return Topic.of( + return Topic.createTopicAssociatedWithMember( name, "설명", null, diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java index 3b99c64aa..250e7940f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java @@ -51,8 +51,8 @@ void setup() { Location location = LocationFixture.create(); locationRepository.save(location); - PinFixture.create(location, TOPIC_WITH_TWO_PINS); - PinFixture.create(location, TOPIC_WITH_TWO_PINS); + PinFixture.create(location, TOPIC_WITH_TWO_PINS, member); + PinFixture.create(location, TOPIC_WITH_TWO_PINS, member); topicRepository.save(TOPIC_WITH_TWO_PINS); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java index 7e745b539..54191a87c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java @@ -56,7 +56,7 @@ void setup() { private Topic createAndSaveByNameAndPinCounts(String topicName, int pinCounts) { Topic topic = TopicFixture.createByName(topicName, member); for (int i = 0; i < pinCounts; i++) { - PinFixture.create(ALL_PINS_LOCATION, topic); + PinFixture.create(ALL_PINS_LOCATION, topic, member); } return topicRepository.save(topic); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java index ffb9193f7..f0203dd81 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java @@ -4,20 +4,24 @@ import com.mapbefine.mapbefine.location.LocationFixture; import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.PinFixture; +import java.util.List; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; class TopicTest { private Topic topic; private Pin pin; + private Member member; @BeforeEach void setUp() { - topic = Topic.of( + topic = Topic.createTopicAssociatedWithMember( "매튜의 산스장", "매튜가 엄마 몰래 찾는 산스장", "https://example.com/image.jpg", @@ -26,7 +30,14 @@ void setUp() { MemberFixture.create(Role.USER) ); - pin = PinFixture.create(LocationFixture.create(), topic); + member = Member.of( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.ADMIN + ); + + pin = PinFixture.create(LocationFixture.create(), topic, member); } @Test @@ -89,4 +100,29 @@ void addPin() { //then assertThat(topic.getPins()).contains(pin); } + + @Test + @DisplayName("Topic 을 생성하면, Member 에 등록이 된다.") + void createTopicAssociatedWithMember() { + // given + Member member = MemberFixture.create(Role.ADMIN); + + // when + Topic topic = Topic.createTopicAssociatedWithMember( + "name", + "description", + null, + Publicity.PUBLIC, + Permission.ALL_MEMBERS, + member + ); + + List topicsInMember = member.getCreatedTopics(); + + // then + assertThat(topicsInMember).hasSize(1); + assertThat(topicsInMember.get(0)).usingRecursiveComparison() + .isEqualTo(topic); + } + } From 2f48f416e572901125d18a49b3dd79a955fb5f11 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 17:56:41 +0900 Subject: [PATCH 47/88] =?UTF-8?q?test=20:=20=EB=8B=A4=EB=A5=B8=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=EC=97=90=EA=B2=8C=20=EA=B6=8C=ED=95=9C=EC=9D=84=20?= =?UTF-8?q?=EC=A3=BC=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 102 ------------- .../application/MemberCommandService.java | 45 +++++- .../MemberTopicPermissionRepository.java | 3 + .../application/MemberCommandServiceTest.java | 139 ++++++++++++++++++ 4 files changed, 179 insertions(+), 110 deletions(-) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java diff --git a/README.md b/README.md index 15923c19b..977115fc8 100644 --- a/README.md +++ b/README.md @@ -67,105 +67,3 @@ #### 질문을 두려워하지 마라 - 이해하지 못했는데 알겠다고 대답하지 말아요. - 모르는 건 죄가 아니지만 모르는 데 아는 척 하는 건 죄입니다. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- [ ] 해당 Topic 의 Creator 가 특정 멤버에게 Permission 을 주는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [x] MemberInfo 생성 테스트 - - [x] Member 생성 테스트 - - [x] MemberTopicPermission 에 createPermissionAssociatedWithTopicAndMember 잘 되는지 테스트 (연관관계 잘 추가되었는지) - - [ ] Pin 의 정팩메를 사용할 때 Member 가 잘 추가 되는지 - - [ ] Topic 의 정팩메를 사용할 때 Member 가 잘 추가 되는지 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Admin 이 권한을 주는 경우 - - [ ] Creator 가 권한을 주는 경우 - - [ ] 그냥 일반 유저가 권한을 주려는 경우 (이 경우만 실패) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] Creator 가 권한을 주는 경우로 Controller Test 를 진행한다. - - [ ] RestDocs 작성 - - [ ] Creator 가 권한을 주는 경우로 Controller Mocking Test 를 진행한다. - -- [ ] 해당 Topic 의 Creator 가 특정 멤버의 Permission 을 삭제하는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - -- [ ] 해당 Topic 에 Permission 을 가진 이들을 조회하는 기능 (로그인 유저에 한해서 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - -- [ ] Member 를 Create 하는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - -- [ ] Member 를 findAll 하는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - -- [ ] Member ID 를 통해 조회하는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - -- [ ] Member 가 본인이 만든 핀을 조회하는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성c - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - -- [ ] Member 가 본인이 만든 토픽을 조회하는 기능 - - [x] Controller, Service 코드 작성 (즉 기능 구현 완료) - - [ ] Domain 테스트 작성 - - [ ] Service 테스트 작성 (이 때에는 happy case 말고 예외 케이스 모두 검증하는 방식으로) - - [ ] Controller 테스트 작성 (happy case 만) - - [ ] RestDocs 작성 - - - diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index f8b8c1d3a..9ba29741f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -53,20 +53,22 @@ public Long saveMemberTopicPermission( Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); - validateMemberCanTopicUpdate(authMember, topic); + validateSaveMemberTopicPermission(authMember, request, member, topic); MemberTopicPermission memberTopicPermission = MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); return memberTopicPermissionRepository.save(memberTopicPermission).getId(); } - public void deleteMemberTopicPermission(final AuthMember authMember, final Long permissionId) { - MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) - .orElseThrow(NoSuchElementException::new); - - validateMemberCanTopicUpdate(authMember, memberTopicPermission.getTopic()); - - memberTopicPermissionRepository.delete(memberTopicPermission); + private void validateSaveMemberTopicPermission( + AuthMember authMember, + MemberTopicPermissionCreateRequest request, + Member member, + Topic topic + ) { + validateMemberCanTopicUpdate(authMember, topic); + validateSelfPermission(authMember, request); + validateDuplicatePermission(member, topic); } private void validateMemberCanTopicUpdate(AuthMember authMember, Topic topic) { @@ -75,4 +77,31 @@ private void validateMemberCanTopicUpdate(AuthMember authMember, Topic topic) { } } + private void validateSelfPermission( + AuthMember authMember, + MemberTopicPermissionCreateRequest request + ) { + if (authMember.getMemberId().equals(request.memberId())) { + throw new IllegalArgumentException("본인에게 권한을 줄 수 없습니다."); + } + } + + private void validateDuplicatePermission(final Member member, final Topic topic) { + if (memberTopicPermissionRepository.existsByTopicAndMember(topic, member)) { + throw new IllegalArgumentException("권한은 중복으로 줄 수 없습니다."); + } + } + + public void deleteMemberTopicPermission( + AuthMember authMember, + Long permissionId + ) { + MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) + .orElseThrow(NoSuchElementException::new); + + validateMemberCanTopicUpdate(authMember, memberTopicPermission.getTopic()); + + memberTopicPermissionRepository.delete(memberTopicPermission); + } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java index fde7b4a2c..c30b9c814 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.member.domain; +import com.mapbefine.mapbefine.topic.domain.Topic; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; @@ -7,4 +8,6 @@ public interface MemberTopicPermissionRepository extends JpaRepository findByTopicId(Long topicId); + boolean existsByTopicAndMember(Topic topic, Member member); + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java new file mode 100644 index 000000000..4c4ea5897 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java @@ -0,0 +1,139 @@ +package com.mapbefine.mapbefine.member.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@ServiceTest +class MemberCommandServiceTest { + + @Autowired + private MemberCommandService memberCommandService; + + @Autowired + private MemberQueryService memberQueryService; + + @Autowired + private TopicRepository topicRepository; + + @Autowired + private MemberRepository memberRepository; + + @Test + @DisplayName("Admin 이 권한을 주는 경우 정상적으로 권한이 주어진다.") + void saveMemberTopicPermissionByAdmin() { + // given + Member admin = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", admin)); + AuthMember authAdmin = AuthMember.from(admin); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + Long savedId = memberCommandService.saveMemberTopicPermission(authAdmin, request); + MemberDetailResponse memberDetailResponse = memberQueryService.findMemberTopicPermissionById(savedId); + + // then + assertThat(memberDetailResponse.id()).isEqualTo(member.getId()); + assertThat(memberDetailResponse.name()).isEqualTo(member.getMemberInfo().getName()); + assertThat(memberDetailResponse.email()).isEqualTo(member.getMemberInfo().getEmail()); + assertThat(memberDetailResponse.imageUrl()).isEqualTo(member.getMemberInfo().getImageUrl()); + } + + @Test + @DisplayName("Topic 의 Creator 이 권한을 주는 경우 정상적으로 권한이 주어진다.") + void saveMemberTopicPermissionByCreator() { + // given + Member creator = memberRepository.save(MemberFixture.create(Role.USER)); + Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember authCreator = AuthMember.from(creator); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + Long savedId = memberCommandService.saveMemberTopicPermission(authCreator, request); + MemberDetailResponse memberDetailResponse = memberQueryService.findMemberTopicPermissionById(savedId); + + // then + assertThat(memberDetailResponse.id()).isEqualTo(member.getId()); + assertThat(memberDetailResponse.name()).isEqualTo(member.getMemberInfo().getName()); + assertThat(memberDetailResponse.email()).isEqualTo(member.getMemberInfo().getEmail()); + assertThat(memberDetailResponse.imageUrl()).isEqualTo(member.getMemberInfo().getImageUrl()); + } + + @Test + @DisplayName("Creator 가 아닌 유저가 권한을 주려는 경우 예외가 발생한다.") + void saveMemberTopicPermissionByUser() { + // given + Member creator = memberRepository.save(MemberFixture.create(Role.USER)); + Member notCreator = memberRepository.save(MemberFixture.create(Role.USER)); + Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember authNotCreator = AuthMember.from(notCreator); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when then + assertThatThrownBy(() -> memberCommandService.saveMemberTopicPermission(authNotCreator, request)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("본인에게 권한을 주려하는 경우 예외가 발생한다.") + void saveMemberTopicPermissionByCreator_whenSelf_thanFail() { + // given + Member creator = memberRepository.save(MemberFixture.create(Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember authCreator = AuthMember.from(creator); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + creator.getId() + ); + + // when then + assertThatThrownBy(() -> memberCommandService.saveMemberTopicPermission(authCreator, request)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("이미 권한을 부여 받은 사람에게 권한을 주는 경우 예외가 발생한다.") + void saveMemberTopicPermissionByCreator__whenDuplicate_thanFail() { + // given + Member creator = memberRepository.save(MemberFixture.create(Role.USER)); + Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember authCreator = AuthMember.from(creator); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + memberCommandService.saveMemberTopicPermission(authCreator, request); + + // when then + assertThatThrownBy(() -> memberCommandService.saveMemberTopicPermission(authCreator, request)) + .isInstanceOf(IllegalArgumentException.class); + } + +} From b9a18fcebb1c6791dce4a516b536be151b9fe887 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 21:37:29 +0900 Subject: [PATCH 48/88] =?UTF-8?q?test=20:=20=EA=B6=8C=ED=95=9C=20=EB=B6=80?= =?UTF-8?q?=EC=97=AC=20=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../presentation/MemberIntegrationTest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java new file mode 100644 index 000000000..42a98fcd0 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -0,0 +1,69 @@ +package com.mapbefine.mapbefine.member.presentation; + +import static io.restassured.RestAssured.given; +import static org.apache.http.HttpHeaders.AUTHORIZATION; +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.common.IntegrationTest; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.apache.commons.codec.binary.Base64; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +class MemberIntegrationTest extends IntegrationTest { + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private TopicRepository topicRepository; + + @Test + @DisplayName("Topic 을 만든자가 특정 유저에게 권한을 준다.") + void addMemberTopicPermission() { + // given + Member creator = memberRepository.save( + Member.of( + "memberr", + "memberr@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ) + ); + Member member = memberRepository.save(MemberFixture.create(Role.USER)); + String authHeader = Base64.encodeBase64String( + ("Basic " + creator.getMemberInfo().getEmail()).getBytes() + ); + Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when().post("/members/permissions") + .then().log().all() + .extract(); + + // then + assertThat(response.header("Location")).isNotBlank(); + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } + +} From d6188c449f895f2f2d71608ea0fea25e8f5a5e5b Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 21:46:00 +0900 Subject: [PATCH 49/88] =?UTF-8?q?docs=20:=20=EA=B6=8C=ED=95=9C=20=EB=B6=80?= =?UTF-8?q?=EC=97=AC=20API=20=EB=AA=85=EC=84=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/index.adoc | 1 + backend/src/docs/asciidoc/member.adoc | 5 ++ .../presentation/MemberControllerTest.java | 50 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 backend/src/docs/asciidoc/member.adoc create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java diff --git a/backend/src/docs/asciidoc/index.adoc b/backend/src/docs/asciidoc/index.adoc index 2aff6bd52..1294932d7 100644 --- a/backend/src/docs/asciidoc/index.adoc +++ b/backend/src/docs/asciidoc/index.adoc @@ -10,3 +10,4 @@ toc::[] include::topic.adoc[] include::pin.adoc[] +include::member.adoc[] diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc new file mode 100644 index 000000000..09cebc47b --- /dev/null +++ b/backend/src/docs/asciidoc/member.adoc @@ -0,0 +1,5 @@ +== 유저 + +=== 유저 권한 부여 + +operation::member-controller-test/add-member-topic-permission[snippets='http-request,http-response'] diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java new file mode 100644 index 000000000..e40283a80 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -0,0 +1,50 @@ +package com.mapbefine.mapbefine.member.presentation; + +import static org.apache.http.HttpHeaders.AUTHORIZATION; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.application.MemberCommandService; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.pin.application.PinCommandService; +import com.mapbefine.mapbefine.pin.application.PinQueryService; +import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import org.apache.tomcat.util.codec.binary.Base64; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +class MemberControllerTest extends RestDocsIntegration { + + @MockBean + private MemberCommandService memberCommandService; + + @Test + @DisplayName("핀 추가") + void addMemberTopicPermission() throws Exception { + Member member = MemberFixture.create(Role.ADMIN); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + 1L, + 2L + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + member.getMemberInfo().getEmail()).getBytes() + ); + given(memberCommandService.save(any())).willReturn(1L); + + mockMvc.perform( + MockMvcRequestBuilders.post("/members/permissions") + .header(AUTHORIZATION, authHeader) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ).andDo(restDocs.document()); + } + + +} From 8ffb1f315329273ccd5c689c5155205f37100ee6 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 22:22:28 +0900 Subject: [PATCH 50/88] =?UTF-8?q?test=20:=20=EA=B6=8C=ED=95=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20Service=20Test=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberCommandService.java | 2 +- .../mapbefine/member/domain/MemberInfo.java | 4 +- .../application/LocationQueryServiceTest.java | 2 +- .../presentation/LocationControllerTest.java | 2 +- .../mapbefine/member/MemberFixture.java | 6 +- .../application/MemberCommandServiceTest.java | 102 +++++++++++++++--- .../domain/MemberTopicPermissionTest.java | 4 +- .../presentation/MemberControllerTest.java | 2 +- .../presentation/MemberIntegrationTest.java | 2 +- .../mapbefine/pin/PinIntegrationTest.java | 2 +- .../application/PinCommandServiceTest.java | 2 +- .../pin/application/PinQueryServiceTest.java | 2 +- .../mapbefine/pin/domain/PinImageTest.java | 4 +- .../pin/domain/PinRepositoryTest.java | 4 +- .../mapbefine/pin/domain/PinTest.java | 8 +- .../pin/presentation/PinControllerTest.java | 10 +- .../mapbefine/topic/TopicIntegrationTest.java | 14 +-- .../application/TopicCommandServiceTest.java | 2 +- .../application/TopicQueryServiceTest.java | 2 +- .../mapbefine/topic/domain/TopicTest.java | 4 +- .../presentation/TopicControllerTest.java | 12 +-- 21 files changed, 135 insertions(+), 57 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index fd1394c07..2a3f4aa7b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -85,7 +85,7 @@ private void validateSelfPermission( } } - private void validateDuplicatePermission(final Member member, final Topic topic) { + private void validateDuplicatePermission(Member member, Topic topic) { if (memberTopicPermissionRepository.existsByTopicAndMember(topic, member)) { throw new IllegalArgumentException("권한은 중복으로 줄 수 없습니다."); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index 0b6361a6a..cc14fa656 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -19,10 +19,10 @@ public class MemberInfo { private static final int MAX_NAME_LENGTH = 20; private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; - @Column(nullable = false, length = 20) + @Column(nullable = false, length = 20, unique = true) private String name; - @Column(nullable = false) + @Column(nullable = false, unique = true) private String email; @Column(nullable = false) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java index 853aa9169..76091eb22 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/application/LocationQueryServiceTest.java @@ -48,7 +48,7 @@ class LocationQueryServiceTest { @BeforeEach void setup() { - member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); authMember = AuthMember.from(member); ALL_PINS_LOCATION = LocationFixture.createByCoordinate(35.0, 127.0); locationRepository.save(ALL_PINS_LOCATION); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java index a98a15da7..57848d2e4 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/location/presentation/LocationControllerTest.java @@ -31,7 +31,7 @@ class LocationControllerTest extends RestDocsIntegration { @Test @DisplayName("현재 위치를 기준 토픽의 핀 개수로 나열한다.") void findBests() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java index 63013e403..04ae77364 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/MemberFixture.java @@ -5,10 +5,10 @@ public class MemberFixture { - public static Member create(Role role) { + public static Member create(String name, String email, Role role) { return Member.of( - "member", - "jakind@naver.com", + name, + email, "https://map-befine-official.github.io/favicon.png", role ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java index 4c4ea5897..d72fd0aad 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java @@ -14,6 +14,7 @@ import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import java.util.NoSuchElementException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -37,8 +38,8 @@ class MemberCommandServiceTest { @DisplayName("Admin 이 권한을 주는 경우 정상적으로 권한이 주어진다.") void saveMemberTopicPermissionByAdmin() { // given - Member admin = memberRepository.save(MemberFixture.create(Role.ADMIN)); - Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Member admin = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", admin)); AuthMember authAdmin = AuthMember.from(admin); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( @@ -61,8 +62,8 @@ void saveMemberTopicPermissionByAdmin() { @DisplayName("Topic 의 Creator 이 권한을 주는 경우 정상적으로 권한이 주어진다.") void saveMemberTopicPermissionByCreator() { // given - Member creator = memberRepository.save(MemberFixture.create(Role.USER)); - Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); AuthMember authCreator = AuthMember.from(creator); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( @@ -85,9 +86,9 @@ void saveMemberTopicPermissionByCreator() { @DisplayName("Creator 가 아닌 유저가 권한을 주려는 경우 예외가 발생한다.") void saveMemberTopicPermissionByUser() { // given - Member creator = memberRepository.save(MemberFixture.create(Role.USER)); - Member notCreator = memberRepository.save(MemberFixture.create(Role.USER)); - Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member notCreator = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create("memberss", "memberss@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); AuthMember authNotCreator = AuthMember.from(notCreator); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( @@ -102,9 +103,9 @@ void saveMemberTopicPermissionByUser() { @Test @DisplayName("본인에게 권한을 주려하는 경우 예외가 발생한다.") - void saveMemberTopicPermissionByCreator_whenSelf_thanFail() { + void saveMemberTopicPermissionByCreator_whenSelf_thenFail() { // given - Member creator = memberRepository.save(MemberFixture.create(Role.USER)); + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); AuthMember authCreator = AuthMember.from(creator); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( @@ -119,10 +120,10 @@ void saveMemberTopicPermissionByCreator_whenSelf_thanFail() { @Test @DisplayName("이미 권한을 부여 받은 사람에게 권한을 주는 경우 예외가 발생한다.") - void saveMemberTopicPermissionByCreator__whenDuplicate_thanFail() { + void saveMemberTopicPermissionByCreator_whenDuplicate_thenFail() { // given - Member creator = memberRepository.save(MemberFixture.create(Role.USER)); - Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); AuthMember authCreator = AuthMember.from(creator); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( @@ -136,4 +137,81 @@ void saveMemberTopicPermissionByCreator__whenDuplicate_thanFail() { .isInstanceOf(IllegalArgumentException.class); } + @Test + @DisplayName("Admin 이 권한을 삭제하는 경우 정상적으로 삭제가 이루어진다.") + void deleteMemberTopicPermissionByAdmin() { + // given + Member admin = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", admin)); + AuthMember authAdmin = AuthMember.from(admin); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + Long savedId = memberCommandService.saveMemberTopicPermission(authAdmin, request); + memberCommandService.deleteMemberTopicPermission(authAdmin, savedId); + + // then + assertThat(memberRepository.existsById(savedId)).isFalse(); + } + + @Test + @DisplayName("creator 이 권한을 삭제하는 경우 정상적으로 삭제가 이루어진다.") + void deleteMemberTopicPermissionByCreator() { + // given + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember authCreator = AuthMember.from(creator); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + Long savedId = memberCommandService.saveMemberTopicPermission(authCreator, request); + memberCommandService.deleteMemberTopicPermission(authCreator, savedId); + + // then + assertThat(memberRepository.existsById(savedId)).isFalse(); + } + + @Test + @DisplayName("creator 가 아닌 유저가 권한을 삭제하는 경우 예외가 발생한다.") + void deleteMemberTopicPermissionByUser() { + // given + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member nonCreator = memberRepository.save(MemberFixture.create("memberss", "memberss@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember authCreator = AuthMember.from(creator); + AuthMember authNonCreator = AuthMember.from(nonCreator); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + Long savedId = memberCommandService.saveMemberTopicPermission(authCreator, request); + + // then + assertThatThrownBy(() -> memberCommandService.deleteMemberTopicPermission(authNonCreator, savedId)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("존재하지 않는 유저의 권한을 삭제하려 하려는 경우 예외가 발생한다.") + void deleteMemberTopicPermissionByCreator_whenNoneExistsPermission_thenFail() { + // given + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + AuthMember authCreator = AuthMember.from(creator); + + // when then + assertThatThrownBy(() -> memberCommandService.deleteMemberTopicPermission(authCreator, Long.MAX_VALUE)) + .isInstanceOf(NoSuchElementException.class); + } + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java index f31945826..9e24f0c81 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java @@ -15,7 +15,7 @@ class MemberTopicPermissionTest { @DisplayName("정상적인 값을 입력하면 객체가 생성된다.") void createMemberTopicPermission() { // given - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); Topic topic = TopicFixture.createByName("topic", member); // when @@ -33,7 +33,7 @@ void createMemberTopicPermission() { @DisplayName("MemberTopicPermission 을 생성하면, Topic 과 Member 에 등록이 된다.") void createPermissionAssociatedWithTopicAndMember() { // given - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); Topic topic = TopicFixture.createByName("topic", member); // when diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index e40283a80..a5f09f347 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -28,7 +28,7 @@ class MemberControllerTest extends RestDocsIntegration { @Test @DisplayName("핀 추가") void addMemberTopicPermission() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( 1L, 2L diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index 42a98fcd0..69ca13c84 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -42,7 +42,7 @@ void addMemberTopicPermission() { Role.USER ) ); - Member member = memberRepository.save(MemberFixture.create(Role.USER)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); String authHeader = Base64.encodeBase64String( ("Basic " + creator.getMemberInfo().getEmail()).getBytes() ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java index d01873a74..ef8c87c8b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinIntegrationTest.java @@ -49,7 +49,7 @@ class PinIntegrationTest extends IntegrationTest { @BeforeEach void saveTopicAndLocation() { - member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java index 6370fcd2c..fe54e25ec 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java @@ -62,7 +62,7 @@ class PinCommandServiceTest { @BeforeEach void setUp() { locationRepository.deleteAll(); - member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); authMember = AuthMember.from(member); topic = topicRepository.save( Topic.createTopicAssociatedWithMember( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index 3858d4498..002631223 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -63,7 +63,7 @@ void setUp() { double longitude = 127.123456; coordinate = Coordinate.of(latitude, longitude); location = saveLocation(coordinate); - member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); authMember = AuthMember.from(member); topic = topicRepository.save( Topic.createTopicAssociatedWithMember( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java index 00c84308c..f13f8f57e 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java @@ -23,8 +23,8 @@ class PinImageTest { @BeforeEach void setUp() { - topic = TopicFixture.createByName("아이크의 부잣집", MemberFixture.create(Role.USER)); - member = MemberFixture.create(Role.ADMIN); + topic = TopicFixture.createByName("아이크의 부잣집", MemberFixture.create("member", "member@naver.com", Role.USER)); + member = MemberFixture.create("memberr", "memberr@naver.com", Role.ADMIN); pin = PinFixture.create(LocationFixture.create(), topic, member); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java index 8995772f9..17e0850b5 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java @@ -44,7 +44,7 @@ class PinRepositoryTest { @DisplayName("핀을 삭제하면 soft-deleting 된다.") void deleteById_Success() { // given - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); Topic topic = TopicFixture.createByName("name", member); Address address = new Address( "parcel", @@ -74,7 +74,7 @@ void deleteById_Success() { @DisplayName("토픽 ID로 핀을 삭제하면 soft-deleting 된다.") void deleteAllByTopicId_Success() { // given - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); Topic topic = TopicFixture.createByName("name", member); Address address = new Address( "parcel", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java index f7fa6257e..bd9ce6922 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java @@ -43,11 +43,11 @@ class PinTest { null, Publicity.PUBLIC, Permission.ALL_MEMBERS, - MemberFixture.create(Role.ADMIN) + MemberFixture.create("member", "member@naver.com", Role.ADMIN) ); private static final Member member = Member.of( - "member", - "member@naver.com", + "memberr", + "memberr@naver.com", "https://map-befine-official.github.io/favicon.png", Role.ADMIN ); @@ -139,7 +139,7 @@ void update_Fail(String name, String description) { @DisplayName("Pin 을 생성하면, Location, Topic, Member 에 등록이 된다.") void createPinAssociatedWithLocationAndTopicAndMember() { // given - Member mockMember = MemberFixture.create(Role.ADMIN); + Member mockMember = MemberFixture.create("member", "member@naver.com", Role.ADMIN); Topic mockTopic = TopicFixture.createByName("topicName", mockMember); Location mockLocation = LocationFixture.create(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java index 6c6609fbf..eefdfc35d 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/presentation/PinControllerTest.java @@ -40,7 +40,7 @@ class PinControllerTest extends RestDocsIntegration { @Test @DisplayName("핀 추가") void add() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -68,7 +68,7 @@ void add() throws Exception { @Test @DisplayName("핀 수정") void update() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -90,7 +90,7 @@ void update() throws Exception { @Test @DisplayName("핀 삭제") void delete() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -103,7 +103,7 @@ void delete() throws Exception { @Test @DisplayName("핀 상세 조회") void findById() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -131,7 +131,7 @@ void findById() throws Exception { @Test @DisplayName("핀 목록 조회") void findAll() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java index bcff05696..a8aeddbe2 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java @@ -44,7 +44,7 @@ class TopicIntegrationTest extends IntegrationTest { @Test @DisplayName("Pin 목록 없이 Topic을 생성하면 201을 반환한다") void createNewTopicWithoutPins_Success() { - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); TopicCreateRequest 준팍의_또간집 = new TopicCreateRequest( "준팍의 또간집", "https://map-befine-official.github.io/favicon.png", @@ -80,7 +80,7 @@ private ExtractableResponse createNewTopic(TopicCreateRequest request, @Test @DisplayName("Pin 목록과 함께 Topic을 생성하면 201을 반환한다") void createNewTopicWithPins_Success() { - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); List pins = pinRepository.findAll(); List pinIds = pins.stream() .map(Pin::getId) @@ -111,7 +111,7 @@ void createNewTopicWithPins_Success() { @DisplayName("여러개의 토픽을 병합하면 201을 반환한다") void createMergeTopic_Success() { // given - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -165,7 +165,7 @@ void createMergeTopic_Success() { @Test @DisplayName("Topic을 수정하면 200을 반환한다") void updateTopic_Success() { - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -205,7 +205,7 @@ void updateTopic_Success() { @Test @DisplayName("Topic을 삭제하면 204를 반환한다") void deleteTopic_Success() { - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() @@ -240,7 +240,7 @@ void deleteTopic_Success() { @DisplayName("Topic 목록을 조회하면 200을 반환한다") void findTopics_Success() { //given - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() @@ -263,7 +263,7 @@ void findTopics_Success() { @DisplayName("Topic 상세 정보를 조회하면 200을 반환한다") void findTopicDetail_Success() { //given - Member member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java index 250e7940f..d96ce26d3 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java @@ -44,7 +44,7 @@ class TopicCommandServiceTest { @BeforeEach void setup() { - member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); authMember = AuthMember.from(member); TOPIC_WITH_TWO_PINS = TopicFixture.createByName("준팍의 또간집", member); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java index 54191a87c..410293663 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicQueryServiceTest.java @@ -45,7 +45,7 @@ class TopicQueryServiceTest { @BeforeEach void setup() { - member = memberRepository.save(MemberFixture.create(Role.ADMIN)); + member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.ADMIN)); authMember = AuthMember.from(member); ALL_PINS_LOCATION = LocationFixture.createByCoordinate(35.0, 127.0); locationRepository.save(ALL_PINS_LOCATION); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java index f0203dd81..6a328c4b4 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java @@ -27,7 +27,7 @@ void setUp() { "https://example.com/image.jpg", Publicity.PUBLIC, Permission.GROUP_ONLY, - MemberFixture.create(Role.USER) + MemberFixture.create("member", "member@naver.com", Role.USER) ); member = Member.of( @@ -105,7 +105,7 @@ void addPin() { @DisplayName("Topic 을 생성하면, Member 에 등록이 된다.") void createTopicAssociatedWithMember() { // given - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); // when Topic topic = Topic.createTopicAssociatedWithMember( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java index 54977bd03..62e52c16b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/presentation/TopicControllerTest.java @@ -40,7 +40,7 @@ class TopicControllerTest extends RestDocsIntegration { // TODO: 2023/07/25 Imag @Test @DisplayName("토픽 새로 생성") void create() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -66,7 +66,7 @@ void create() throws Exception { @Test @DisplayName("토픽 병합 생성") void mergeAndCreate() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -91,7 +91,7 @@ void mergeAndCreate() throws Exception { @Test @DisplayName("토픽 수정") void update() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -109,7 +109,7 @@ void update() throws Exception { @Test @DisplayName("토픽 삭제") void delete() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -122,7 +122,7 @@ void delete() throws Exception { @Test @DisplayName("토픽 목록 조회") void findAll() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); @@ -150,7 +150,7 @@ void findAll() throws Exception { @Test @DisplayName("토픽 상세 조회") void findById() throws Exception { - Member member = MemberFixture.create(Role.ADMIN); + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); String authHeader = Base64.encodeBase64String( String.format(BASIC_FORMAT, member.getMemberInfo().getEmail()).getBytes() ); From 9a8a0194868e96e44d6ab7af3b63027d6573f64a Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 22:30:19 +0900 Subject: [PATCH 51/88] =?UTF-8?q?test=20:=20=EA=B6=8C=ED=95=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../presentation/MemberIntegrationTest.java | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index 69ca13c84..4cd68c608 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -3,6 +3,7 @@ import static io.restassured.RestAssured.given; import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.http.HttpStatus.NO_CONTENT; import com.mapbefine.mapbefine.common.IntegrationTest; import com.mapbefine.mapbefine.member.MemberFixture; @@ -53,17 +54,60 @@ void addMemberTopicPermission() { ); // when - ExtractableResponse response = given().log().all() + ExtractableResponse response = saveMemberTopicPermission(authHeader, request); + + // then + assertThat(response.header("Location")).isNotBlank(); + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } + + private ExtractableResponse saveMemberTopicPermission( + String authHeader, + MemberTopicPermissionCreateRequest request + ) { + return given().log().all() .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/members/permissions") .then().log().all() .extract(); + } + + @Test + @DisplayName("Topic 을 만든자가 특정 유저에게 권한을 삭제한다.") + void deleteMemberTopicPermission() { + // given + Member creator = memberRepository.save( + Member.of( + "memberr", + "memberr@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ) + ); + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + String authHeader = Base64.encodeBase64String( + ("Basic " + creator.getMemberInfo().getEmail()).getBytes() + ); + Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + ExtractableResponse newMemberTopicPermission = saveMemberTopicPermission(authHeader, request); + long memberTopicPermissionId = Long.parseLong(newMemberTopicPermission.header("Location").split("/")[3]); + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .when().delete("/members/permissions/" + memberTopicPermissionId) + .then().log().all() + .extract(); // then - assertThat(response.header("Location")).isNotBlank(); - assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + assertThat(response.statusCode()) + .isEqualTo(HttpStatus.NO_CONTENT.value()); } } From fa6d7fe3125b82b4202fda52fb74263b9605c734 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 22:41:30 +0900 Subject: [PATCH 52/88] =?UTF-8?q?docs=20:=20=EA=B6=8C=ED=95=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20API=20=EB=AA=85=EC=84=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/member.adoc | 3 +++ .../member/presentation/MemberControllerTest.java | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index 09cebc47b..920d5857e 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -3,3 +3,6 @@ === 유저 권한 부여 operation::member-controller-test/add-member-topic-permission[snippets='http-request,http-response'] + +=== 유저 권한 삭제 +operation::member-controller-test/delete-member-topic-permission[snippets='http-request,http-response'] diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index a5f09f347..f8f4f7f9d 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -26,7 +26,7 @@ class MemberControllerTest extends RestDocsIntegration { private MemberCommandService memberCommandService; @Test - @DisplayName("핀 추가") + @DisplayName("권한 추가") void addMemberTopicPermission() throws Exception { Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( @@ -46,5 +46,18 @@ void addMemberTopicPermission() throws Exception { ).andDo(restDocs.document()); } + @Test + @DisplayName("권한 삭제") + void deleteMemberTopicPermission() throws Exception { + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); + String authHeader = Base64.encodeBase64String( + ("Basic " + member.getMemberInfo().getEmail()).getBytes() + ); + + mockMvc.perform( + MockMvcRequestBuilders.delete("/members/permissions/1") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } } From 0dad751116e9ffff162f7736163db0fecbfdd4c4 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 22:46:16 +0900 Subject: [PATCH 53/88] =?UTF-8?q?test=20:=20memberResponse=20=EC=A0=95?= =?UTF-8?q?=EC=A0=81=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/domain/MemberResponseTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java new file mode 100644 index 000000000..2aba90279 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java @@ -0,0 +1,32 @@ +package com.mapbefine.mapbefine.member.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MemberResponseTest { + + @Test + @DisplayName("Member 를 이용하여 MemberResponse 가 정상적으로 생성된다.") + void createMemberResponse_success() { + // given + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.ADMIN + ); + + // when + MemberResponse memberResponse = MemberResponse.from(member); + + // then + assertThat(memberResponse.name()) + .isEqualTo(member.getMemberInfo().getName()); + assertThat(memberResponse.email()) + .isEqualTo(member.getMemberInfo().getEmail()); + } + +} From bb842239ab19973a0f481dc17da1afe8286a443d Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 22:59:26 +0900 Subject: [PATCH 54/88] =?UTF-8?q?test=20:=20=EA=B6=8C=ED=95=9C=EC=9D=B4=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20=EB=A9=A4=EB=B2=84=20=EC=A0=84=EC=B2=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20Service=20Test=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberQueryServiceTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java new file mode 100644 index 000000000..2a2f300b0 --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -0,0 +1,72 @@ +package com.mapbefine.mapbefine.member.application; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; +import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.topic.TopicFixture; +import com.mapbefine.mapbefine.topic.domain.Topic; +import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +@ServiceTest +public class MemberQueryServiceTest { + + @Autowired + private MemberQueryService memberQueryService; + + @Autowired + private TopicRepository topicRepository; + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private MemberTopicPermissionRepository memberTopicPermissionRepository; + + @Test + @DisplayName("Topic 에 권한이 있는자들을 모두 조회한다.") // creator 는 권한이 있는자들을 조회할 때 조회되어야 할 것인가?? + void findAllWithPermission() { + // given + Member member1InTopic1 = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Member member2InTopic1 = memberRepository.save( + MemberFixture.create("members", "members@naver.com", Role.USER) + ); + Member member3InTopic2 = memberRepository.save( + MemberFixture.create("memberss", "memberss@naver.com", Role.USER) + ); + Topic topic1 = topicRepository.save(TopicFixture.createByName("topic1", member1InTopic1)); + Topic topic2 = topicRepository.save(TopicFixture.createByName("topic2", member1InTopic1)); + memberTopicPermissionRepository.save( + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic1, member1InTopic1) + ); + memberTopicPermissionRepository.save( + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic1, member2InTopic1) + ); + memberTopicPermissionRepository.save( + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic2, member3InTopic2) + ); + + // when + List memberResponses = memberQueryService.findAllWithPermission(topic1.getId()); + MemberResponse memberResponse1 = MemberResponse.from(member1InTopic1); + MemberResponse memberResponse2 = MemberResponse.from(member2InTopic1); + + // then + assertThat(memberResponses).hasSize(2) + .usingRecursiveComparison() + .isEqualTo(List.of(memberResponse1, memberResponse2)); + } + +} From 71e970af2622b50b7f6ce356a456b1de8fedff99 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 23:27:02 +0900 Subject: [PATCH 55/88] =?UTF-8?q?test=20:=20=ED=95=B4=EB=8B=B9=20=ED=86=A0?= =?UTF-8?q?=ED=94=BD=EC=97=90=20=EA=B6=8C=ED=95=9C=EC=9D=84=20=EA=B0=80?= =?UTF-8?q?=EC=A7=84=20=EC=9E=90=EB=93=A4=EC=9D=84=20=EB=AA=A8=EB=91=90=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 2 +- .../mapbefine/common/IntegrationTest.java | 1 + .../presentation/MemberControllerTest.java | 14 ++++++ .../presentation/MemberIntegrationTest.java | 48 ++++++++++++++++++- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index ba5cc9f7d..0aecaa67a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -95,7 +95,7 @@ public ResponseEntity deleteMemberTopicPermission(AuthMember authMember, @ } @LoginRequired - @GetMapping("/permissions/{topicId}") + @GetMapping("/permissions/topics/{topicId}") public ResponseEntity> findMemberTopicPermissionAll(@PathVariable Long topicId) { List responses = memberQueryService.findAllWithPermission(topicId); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java index 1aa17b132..d7e910609 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/IntegrationTest.java @@ -2,6 +2,7 @@ import com.mapbefine.mapbefine.DatabaseCleanup; import io.restassured.*; +import io.restassured.parsing.Parser; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index f8f4f7f9d..29099f84c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -60,4 +60,18 @@ void deleteMemberTopicPermission() throws Exception { ).andDo(restDocs.document()); } + @Test + @DisplayName("권한이 있는 자들 모두 조회") + void findMemberTopicPermissionAll() throws Exception { + Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); + String authHeader = Base64.encodeBase64String( + ("Basic " + member.getMemberInfo().getEmail()).getBytes() + ); + + mockMvc.perform( + MockMvcRequestBuilders.delete("/members/permissions/1") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index 4cd68c608..942105b6a 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -3,7 +3,6 @@ import static io.restassured.RestAssured.given; import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.http.HttpStatus.NO_CONTENT; import com.mapbefine.mapbefine.common.IntegrationTest; import com.mapbefine.mapbefine.member.MemberFixture; @@ -11,11 +10,14 @@ import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import java.util.List; import org.apache.commons.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -110,4 +112,48 @@ void deleteMemberTopicPermission() { .isEqualTo(HttpStatus.NO_CONTENT.value()); } + @Test + @DisplayName("Topic 에 권한을 가진 자들을 모두 조회한다.") + void findMemberTopicPermissionAll() { + // given + Member creator = memberRepository.save( + Member.of( + "memberr", + "memberr@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ) + ); + Member member1 = memberRepository.save(MemberFixture.create("memberrr", "memberrr@naver.com", Role.USER)); + Member member2 = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + String authHeader = Base64.encodeBase64String( + ("Basic " + creator.getMemberInfo().getEmail()).getBytes() + ); + Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); + MemberTopicPermissionCreateRequest request1 = new MemberTopicPermissionCreateRequest( + topic.getId(), + member1.getId() + ); + MemberTopicPermissionCreateRequest request2 = new MemberTopicPermissionCreateRequest( + topic.getId(), + member2.getId() + ); + + // when + saveMemberTopicPermission(authHeader, request1); + saveMemberTopicPermission(authHeader, request2); + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .when().get("/members/permissions/topics/" + topic.getId()) + .then().log().all() + .extract(); + + // then + List memberResponses = response.as(new TypeRef<>() {}); + assertThat(response.statusCode()) + .isEqualTo(HttpStatus.OK.value()); + assertThat(memberResponses).usingRecursiveComparison() + .isEqualTo(List.of(MemberResponse.from(member1), MemberResponse.from(member2))); + } + } From d5128c622af0ac9730bee5a40d753afb344cc76c Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 2 Aug 2023 23:45:55 +0900 Subject: [PATCH 56/88] =?UTF-8?q?docs=20:=20=ED=95=B4=EB=8B=B9=20=ED=86=A0?= =?UTF-8?q?=ED=94=BD=EC=97=90=20=EA=B6=8C=ED=95=9C=EC=9D=84=20=EA=B0=80?= =?UTF-8?q?=EC=A7=84=20=EC=9C=A0=EC=A0=80=EC=9D=98=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20API=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/member.adoc | 4 ++ .../presentation/MemberControllerTest.java | 41 +++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index 920d5857e..1c3c9f5fb 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -6,3 +6,7 @@ operation::member-controller-test/add-member-topic-permission[snippets='http-req === 유저 권한 삭제 operation::member-controller-test/delete-member-topic-permission[snippets='http-request,http-response'] + +=== 토픽에 권한을 가진 유저 목록 조회 +operation::member-controller-test/find-member-topic-permission-all[snippets='http-request,http-response'] + diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 29099f84c..9888c1083 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -5,14 +5,15 @@ import static org.mockito.BDDMockito.given; import com.mapbefine.mapbefine.common.RestDocsIntegration; +import com.mapbefine.mapbefine.common.interceptor.AuthInterceptor; import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.application.MemberCommandService; +import com.mapbefine.mapbefine.member.application.MemberQueryService; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; -import com.mapbefine.mapbefine.pin.application.PinCommandService; -import com.mapbefine.mapbefine.pin.application.PinQueryService; -import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; +import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import java.util.List; import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -25,6 +26,12 @@ class MemberControllerTest extends RestDocsIntegration { @MockBean private MemberCommandService memberCommandService; + @MockBean + private MemberQueryService memberQueryService; + + @MockBean + private AuthInterceptor authInterceptor; + @Test @DisplayName("권한 추가") void addMemberTopicPermission() throws Exception { @@ -36,7 +43,9 @@ void addMemberTopicPermission() throws Exception { String authHeader = Base64.encodeBase64String( ("Basic " + member.getMemberInfo().getEmail()).getBytes() ); + given(memberCommandService.save(any())).willReturn(1L); + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.post("/members/permissions") @@ -54,6 +63,9 @@ void deleteMemberTopicPermission() throws Exception { ("Basic " + member.getMemberInfo().getEmail()).getBytes() ); + given(memberCommandService.save(any())).willReturn(1L); + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); + mockMvc.perform( MockMvcRequestBuilders.delete("/members/permissions/1") .header(AUTHORIZATION, authHeader) @@ -62,14 +74,29 @@ void deleteMemberTopicPermission() throws Exception { @Test @DisplayName("권한이 있는 자들 모두 조회") - void findMemberTopicPermissionAll() throws Exception { - Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); + void findMemberTopicPermissionAll() throws Exception { // LoginRequired 로 인해서 RestDocs 가 막힘... Hadnler 없어서.. 그래서 200 OK 만 반환하고, Response 도 적절하게 안내뱉음 + List memberResponses = List.of( + new MemberResponse( + 1L, + "member", + "member@naver.com" + ), + new MemberResponse( + 2L, + "memberr", + "memberr@naver.com" + ) + ); + String authHeader = Base64.encodeBase64String( - ("Basic " + member.getMemberInfo().getEmail()).getBytes() + ("Basic " + memberResponses.get(0).email()).getBytes() ); + given(memberQueryService.findAllWithPermission(any())).willReturn(memberResponses); + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); + mockMvc.perform( - MockMvcRequestBuilders.delete("/members/permissions/1") + MockMvcRequestBuilders.get("/members/permissions/topics/1") .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } From c5423ad98a166bfa3e98cdea90ce1fae6d93535c Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 09:31:51 +0900 Subject: [PATCH 57/88] =?UTF-8?q?test=20:=20MemberDetailResponse=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../domain/MemberDetailResponseTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java new file mode 100644 index 000000000..9aea6b74d --- /dev/null +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java @@ -0,0 +1,34 @@ +package com.mapbefine.mapbefine.member.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.mapbefine.mapbefine.member.MemberFixture; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MemberDetailResponseTest { + + @Test + @DisplayName("Member 를 이용하여 MemberDetailResponse 가 정상적으로 생성된다.") + void createMemberResponse_success() { + // given + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.ADMIN + ); + + // when + MemberDetailResponse memberDetailResponse = MemberDetailResponse.from(member); + + // then + assertThat(memberDetailResponse.name()) + .isEqualTo(member.getMemberInfo().getName()); + assertThat(memberDetailResponse.email()) + .isEqualTo(member.getMemberInfo().getEmail()); + assertThat(memberDetailResponse.imageUrl()) + .isEqualTo(member.getMemberInfo().getImageUrl()); + } + +} From 37a79a8b94e356169163ec485caefa5acc4ec3db Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 09:41:40 +0900 Subject: [PATCH 58/88] =?UTF-8?q?test=20:=20=EA=B6=8C=ED=95=9C=EC=9D=84=20?= =?UTF-8?q?=EA=B0=80=EC=A7=84=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20Service=20Te?= =?UTF-8?q?st=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberQueryServiceTest.java | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index 2a2f300b0..16ea5b926 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -1,6 +1,8 @@ package com.mapbefine.mapbefine.member.application; +import static java.lang.Long.MAX_VALUE; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.mapbefine.mapbefine.common.annotation.ServiceTest; import com.mapbefine.mapbefine.member.MemberFixture; @@ -9,11 +11,13 @@ import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.util.List; +import java.util.NoSuchElementException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -46,7 +50,7 @@ void findAllWithPermission() { Member member3InTopic2 = memberRepository.save( MemberFixture.create("memberss", "memberss@naver.com", Role.USER) ); - Topic topic1 = topicRepository.save(TopicFixture.createByName("topic1", member1InTopic1)); + Topic topic1 = topicRepository.save(TopicFixture.createByName("topic1", member3InTopic2)); Topic topic2 = topicRepository.save(TopicFixture.createByName("topic2", member1InTopic1)); memberTopicPermissionRepository.save( MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic1, member1InTopic1) @@ -69,4 +73,36 @@ void findAllWithPermission() { .isEqualTo(List.of(memberResponse1, memberResponse2)); } + @Test + @DisplayName("ID 를 통해서 토픽에 권한이 있는자를 조회한다.") + void findMemberTopicPermissionById() { + // given + Member creator = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Member permissionUser = memberRepository.save( + MemberFixture.create("members", "members@naver.com", Role.USER) + ); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + Long savedId = memberTopicPermissionRepository.save( + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, permissionUser) + ).getId(); + + // when + MemberDetailResponse memberDetailResponse = memberQueryService.findMemberTopicPermissionById(savedId); + MemberDetailResponse permissionUserResponse = MemberDetailResponse.from(permissionUser); + + // then + assertThat(memberDetailResponse).usingRecursiveComparison() + .isEqualTo(permissionUserResponse); + } + + @Test + @DisplayName("ID 를 통해서 토픽에 권한이 있는자를 조회하려 할 때, 결과가 존재하지 않을 때 예외가 발생한다.") + void findMemberTopicPermissionById_whenNoneExistsPermission_thenFail() { + // given when then + assertThatThrownBy(() -> memberQueryService.findMemberTopicPermissionById(MAX_VALUE)) + .isInstanceOf(NoSuchElementException.class); + } + } From 36ac58e7f3afb48b8e5f024ed185356a2a861434 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 09:45:32 +0900 Subject: [PATCH 59/88] =?UTF-8?q?test=20:=20=EA=B6=8C=ED=95=9C=EC=9D=84=20?= =?UTF-8?q?=EA=B0=80=EC=A7=84=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=9D=B8?= =?UTF-8?q?=EC=88=98=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/MemberIntegrationTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index 942105b6a..3900140fa 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -10,6 +10,7 @@ import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; @@ -156,4 +157,44 @@ void findMemberTopicPermissionAll() { .isEqualTo(List.of(MemberResponse.from(member1), MemberResponse.from(member2))); } + @Test + @DisplayName("Topic 에 권한을 가진 자를 조회한다.") + void findMemberTopicPermissionById() { + // given + Member creator = memberRepository.save( + Member.of( + "memberr", + "memberr@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ) + ); + Member member = memberRepository.save(MemberFixture.create("memberrr", "memberrr@naver.com", Role.USER)); + String authHeader = Base64.encodeBase64String( + ("Basic " + creator.getMemberInfo().getEmail()).getBytes() + ); + Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when + ExtractableResponse newMemberTopicPermission = saveMemberTopicPermission(authHeader, request); + long memberTopicPermissionId = Long.parseLong(newMemberTopicPermission.header("Location").split("/")[3]); + + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .when().get("/members/permissions/" + memberTopicPermissionId) + .then().log().all() + .extract(); + + // then + MemberDetailResponse memberResponses = response.as(MemberDetailResponse.class); + assertThat(response.statusCode()) + .isEqualTo(HttpStatus.OK.value()); + assertThat(memberResponses).usingRecursiveComparison() + .isEqualTo(MemberDetailResponse.from(member)); + } + } From 342f35eee331e177247010486f59e2f3e4092bfe Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 09:50:20 +0900 Subject: [PATCH 60/88] =?UTF-8?q?docs=20:=20=EA=B6=8C=ED=95=9C=EC=9D=84=20?= =?UTF-8?q?=EA=B0=80=EC=A7=84=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20API=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/member.adoc | 4 +++ .../presentation/MemberControllerTest.java | 28 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index 1c3c9f5fb..cb3843b02 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -10,3 +10,7 @@ operation::member-controller-test/delete-member-topic-permission[snippets='http- === 토픽에 권한을 가진 유저 목록 조회 operation::member-controller-test/find-member-topic-permission-all[snippets='http-request,http-response'] +=== 토픽에 권한을 가진 유저 단일 조회 +operation::member-controller-test/find-member-topic-permission-by-id[snippets='http-request,http-response'] + + diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 9888c1083..e72a507bf 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -12,7 +12,9 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; +import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import java.time.LocalDateTime; import java.util.List; import org.apache.tomcat.util.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; @@ -74,7 +76,7 @@ void deleteMemberTopicPermission() throws Exception { @Test @DisplayName("권한이 있는 자들 모두 조회") - void findMemberTopicPermissionAll() throws Exception { // LoginRequired 로 인해서 RestDocs 가 막힘... Hadnler 없어서.. 그래서 200 OK 만 반환하고, Response 도 적절하게 안내뱉음 + void findMemberTopicPermissionAll() throws Exception { List memberResponses = List.of( new MemberResponse( 1L, @@ -101,4 +103,28 @@ void findMemberTopicPermissionAll() throws Exception { // LoginRequired 로 인 ).andDo(restDocs.document()); } + @Test + @DisplayName("권한이 있는 자들 모두 조회") + void findMemberTopicPermissionById() throws Exception { + MemberDetailResponse memberDetailResponse = new MemberDetailResponse( + 1L, + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + LocalDateTime.now() + ); + + String authHeader = Base64.encodeBase64String( + ("Basic " + memberDetailResponse.email()).getBytes() + ); + + given(memberQueryService.findMemberTopicPermissionById(any())).willReturn(memberDetailResponse); + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); + + mockMvc.perform( + MockMvcRequestBuilders.get("/members/permissions/1") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } + } From 864b851ef13d600c78b4bff710218fd3f856522f Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 10:48:57 +0900 Subject: [PATCH 61/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20Ser?= =?UTF-8?q?vice=20Test=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberCommandService.java | 15 ++++ .../member/domain/MemberRepository.java | 2 + .../application/MemberCommandServiceTest.java | 73 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index 2a3f4aa7b..f77ebc500 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -32,6 +32,9 @@ public MemberCommandService( } public Long save(MemberCreateRequest request) { + validateUniqueName(request.name()); + validateUniqueEmail(request.email()); + Member member = Member.of( request.name(), request.email(), @@ -43,6 +46,18 @@ public Long save(MemberCreateRequest request) { .getId(); } + private void validateUniqueName(String name) { + if (memberRepository.existsByMemberInfoName(name)) { + throw new IllegalArgumentException("이미 존재하는 이름입니다."); + } + } + + private void validateUniqueEmail(String email) { + if (memberRepository.existsByMemberInfoEmail(email)) { + throw new IllegalArgumentException("이미 존재하는 이메일입니다."); + } + } + public Long saveMemberTopicPermission( AuthMember authMember, MemberTopicPermissionCreateRequest request diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index ce532c1e5..4935e1628 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -7,6 +7,8 @@ public interface MemberRepository extends JpaRepository { Optional findByMemberInfoEmail(String email); + boolean existsByMemberInfoName(String name); + boolean existsByMemberInfoEmail(String email); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java index d72fd0aad..c811892c3 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java @@ -9,12 +9,14 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.util.NoSuchElementException; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -214,4 +216,75 @@ void deleteMemberTopicPermissionByCreator_whenNoneExistsPermission_thenFail() { .isInstanceOf(NoSuchElementException.class); } + @Test + @DisplayName("유저를 저장한다.") + void save() { + // given + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ); + MemberCreateRequest memberCreateRequest = new MemberCreateRequest( + member.getMemberInfo().getName(), + member.getMemberInfo().getEmail(), + member.getMemberInfo().getImageUrl(), + member.getMemberInfo().getRole() + ); + + // when + Long savedId = memberCommandService.save(memberCreateRequest); + Member savedResult = memberRepository.findById(savedId) + .orElseThrow(NoSuchElementException::new); + + // then + assertThat(savedResult).usingRecursiveComparison() + .ignoringFields("id") + .isEqualTo(member); + } + + @Test + @DisplayName("이미 존재하는 이름으로 유저를 저장할 때 예외가 발생한다.") + void save_whenDuplicateName_thenFail() { + // given + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ); + memberRepository.save(member); + MemberCreateRequest memberCreateRequest = new MemberCreateRequest( + member.getMemberInfo().getName(), + "memberr@naver.com", + member.getMemberInfo().getImageUrl(), + member.getMemberInfo().getRole() + ); + + // when + assertThatThrownBy(() -> memberCommandService.save(memberCreateRequest)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("이미 존재하는 이메일로 유저를 저장할 때 예외가 발생한다.") + void save_whenDuplicateEmail_thenFail() { + // given + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ); + memberRepository.save(member); + MemberCreateRequest memberCreateRequest = new MemberCreateRequest( + "memberr", + member.getMemberInfo().getEmail(), + member.getMemberInfo().getImageUrl(), + member.getMemberInfo().getRole() + ); + + // when + assertThatThrownBy(() -> memberCommandService.save(memberCreateRequest)) + .isInstanceOf(IllegalArgumentException.class); + } + } From 3fa28bc121ccc62e431a0e670f8d48ed90bcc0a9 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 10:55:19 +0900 Subject: [PATCH 62/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 2 +- .../presentation/MemberIntegrationTest.java | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 0aecaa67a..4d2916285 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -53,7 +53,7 @@ public ResponseEntity> findAllMember() { } @PostMapping - public ResponseEntity add(MemberCreateRequest request) { + public ResponseEntity add(@RequestBody MemberCreateRequest request) { Long savedId = memberCommandService.save(request); return ResponseEntity.created(URI.create("/members/" + savedId)).build(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index 3900140fa..d45b9f318 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -9,6 +9,7 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; @@ -197,4 +198,34 @@ void findMemberTopicPermissionById() { .isEqualTo(MemberDetailResponse.from(member)); } + @Test + @DisplayName("유저를 생성한다.") + void add() { + // given + MemberCreateRequest request = new MemberCreateRequest( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ); + + // when + ExtractableResponse response = saveMember(request); + + // then + assertThat(response.header("Location")).isNotBlank(); + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } + + private ExtractableResponse saveMember( + MemberCreateRequest request + ) { + return given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when().post("/members") + .then().log().all() + .extract(); + } + } From 6b3696f865ddc4fe6a0b7f3b80914c5b8b2c63ef Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 11:00:10 +0900 Subject: [PATCH 63/88] =?UTF-8?q?docs=20:=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20API?= =?UTF-8?q?=20=EB=AA=85=EC=84=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/member.adoc | 9 ++++++++ .../presentation/MemberControllerTest.java | 23 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index cb3843b02..0a9f3ac2f 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -5,12 +5,21 @@ operation::member-controller-test/add-member-topic-permission[snippets='http-request,http-response'] === 유저 권한 삭제 + operation::member-controller-test/delete-member-topic-permission[snippets='http-request,http-response'] === 토픽에 권한을 가진 유저 목록 조회 + operation::member-controller-test/find-member-topic-permission-all[snippets='http-request,http-response'] === 토픽에 권한을 가진 유저 단일 조회 + operation::member-controller-test/find-member-topic-permission-by-id[snippets='http-request,http-response'] +=== 유저 생성 + +operation::member-controller-test/add[snippets='http-request,http-response'] + + + diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index e72a507bf..98517ff4c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -11,6 +11,7 @@ import com.mapbefine.mapbefine.member.application.MemberQueryService; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; +import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; @@ -46,7 +47,7 @@ void addMemberTopicPermission() throws Exception { ("Basic " + member.getMemberInfo().getEmail()).getBytes() ); - given(memberCommandService.save(any())).willReturn(1L); + given(memberCommandService.saveMemberTopicPermission(any(), any())).willReturn(1L); given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( @@ -127,4 +128,24 @@ void findMemberTopicPermissionById() throws Exception { ).andDo(restDocs.document()); } + @Test + @DisplayName("유저 생성") + void add() throws Exception { + MemberCreateRequest request = new MemberCreateRequest( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ); + + given(memberCommandService.save(any())).willReturn(1L); + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); + + mockMvc.perform( + MockMvcRequestBuilders.post("/members") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ).andDo(restDocs.document()); + } + } From 9192536c82c240f162fd462dec7cde2dedb51668 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 11:23:38 +0900 Subject: [PATCH 64/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20Service=20Test=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberQueryServiceTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index 16ea5b926..b24ac1895 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -105,4 +105,24 @@ void findMemberTopicPermissionById_whenNoneExistsPermission_thenFail() { .isInstanceOf(NoSuchElementException.class); } + + @Test + @DisplayName("유저 목록을 조회한다.") + void findAllMember() { + // given + Member member = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Member memberr = memberRepository.save( + MemberFixture.create("memberr", "memberr@naver.com", Role.USER) + ); + + // when + List responses = memberQueryService.findAll(); + + // then + assertThat(responses).usingRecursiveComparison() + .isEqualTo(List.of(MemberResponse.from(member), MemberResponse.from(memberr))); + } + } From 522708f1e6d1ce466867a621bc6953b066c6f78a Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 11:32:28 +0900 Subject: [PATCH 65/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/MemberIntegrationTest.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index d45b9f318..fa2f61551 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -228,4 +228,57 @@ private ExtractableResponse saveMember( .extract(); } + @Test + @DisplayName("유저 목록을 조회한다.") + void findAllMember() { + // given + Member member = Member.of( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ); + Member memberr = Member.of( + "memberr", + "memberr@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ); + MemberCreateRequest request1 = new MemberCreateRequest( + member.getMemberInfo().getName(), + member.getMemberInfo().getEmail(), + member.getMemberInfo().getImageUrl(), + member.getMemberInfo().getRole() + ); + MemberCreateRequest request2 = new MemberCreateRequest( + memberr.getMemberInfo().getName(), + memberr.getMemberInfo().getEmail(), + memberr.getMemberInfo().getImageUrl(), + memberr.getMemberInfo().getRole() + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + member.getMemberInfo().getEmail()).getBytes() + ); + + // when + saveMember(request1); + saveMember(request2); + + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/members") + .then().log().all() + .extract(); + + List memberResponses = response.as(new TypeRef<>() {}); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + assertThat(memberResponses).hasSize(2) + .usingRecursiveComparison() + .ignoringFields("id") + .isEqualTo(List.of(MemberResponse.from(member), MemberResponse.from(memberr))); + } + } From 0815ff76430f175695d36fceb9d7e548b01515b1 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 11:37:18 +0900 Subject: [PATCH 66/88] =?UTF-8?q?docs=20:=20=EC=9C=A0=EC=A0=80=EB=A5=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20API=20=EB=AA=85=EC=84=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/member.adoc | 4 +-- .../presentation/MemberControllerTest.java | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index 0a9f3ac2f..fc5fc0caa 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -20,6 +20,6 @@ operation::member-controller-test/find-member-topic-permission-by-id[snippets='h operation::member-controller-test/add[snippets='http-request,http-response'] +=== 유저 목록 조회 - - +operation::member-controller-test/find-all-member[snippets='http-request,http-response'] diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 98517ff4c..ba699e887 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -148,4 +148,32 @@ void add() throws Exception { ).andDo(restDocs.document()); } + @Test + @DisplayName("유저 목록 조회") + void findAllMember() throws Exception { + List memberResponses = List.of( + new MemberResponse( + 1L, + "member", + "member@naver.com" + ), + new MemberResponse( + 2L, + "memberr", + "memberr@naver.com" + ) + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + memberResponses.get(0).email()).getBytes() + ); + + given(memberQueryService.findAll()).willReturn(memberResponses); + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); + + mockMvc.perform( + MockMvcRequestBuilders.get("/members") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } + } From 7fcc517f648092f0ecdf62dde4b9f1de7ad3ffb8 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 14:31:00 +0900 Subject: [PATCH 67/88] =?UTF-8?q?refactor=20:=20AuthInterceptor=20mocking?= =?UTF-8?q?=20=EC=9D=84=20RestDocs=20=EC=97=90=EC=84=9C=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/common/RestDocsIntegration.java | 9 ++++++++- .../member/presentation/MemberControllerTest.java | 10 ---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java b/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java index 3a3a7111f..a6ecf542e 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java @@ -1,8 +1,11 @@ package com.mapbefine.mapbefine.common; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import com.fasterxml.jackson.databind.ObjectMapper; +import com.mapbefine.mapbefine.common.interceptor.AuthInterceptor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -10,6 +13,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.RestDocumentationExtension; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation; @@ -31,12 +35,15 @@ public abstract class RestDocsIntegration { protected MockMvc mockMvc; + @MockBean + private AuthInterceptor authInterceptor; @BeforeEach void beforeEach( final WebApplicationContext context, final RestDocumentationContextProvider provider - ) { + ) throws Exception { + given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); this.restDocs = MockMvcRestDocumentation.document("{class-name}/{method-name}"); this.mockMvc = MockMvcBuilders.webAppContextSetup(context) .apply( diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index ba699e887..0fe4d7849 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -5,7 +5,6 @@ import static org.mockito.BDDMockito.given; import com.mapbefine.mapbefine.common.RestDocsIntegration; -import com.mapbefine.mapbefine.common.interceptor.AuthInterceptor; import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.application.MemberCommandService; import com.mapbefine.mapbefine.member.application.MemberQueryService; @@ -32,9 +31,6 @@ class MemberControllerTest extends RestDocsIntegration { @MockBean private MemberQueryService memberQueryService; - @MockBean - private AuthInterceptor authInterceptor; - @Test @DisplayName("권한 추가") void addMemberTopicPermission() throws Exception { @@ -48,7 +44,6 @@ void addMemberTopicPermission() throws Exception { ); given(memberCommandService.saveMemberTopicPermission(any(), any())).willReturn(1L); - given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.post("/members/permissions") @@ -67,7 +62,6 @@ void deleteMemberTopicPermission() throws Exception { ); given(memberCommandService.save(any())).willReturn(1L); - given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.delete("/members/permissions/1") @@ -96,7 +90,6 @@ void findMemberTopicPermissionAll() throws Exception { ); given(memberQueryService.findAllWithPermission(any())).willReturn(memberResponses); - given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.get("/members/permissions/topics/1") @@ -120,7 +113,6 @@ void findMemberTopicPermissionById() throws Exception { ); given(memberQueryService.findMemberTopicPermissionById(any())).willReturn(memberDetailResponse); - given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.get("/members/permissions/1") @@ -139,7 +131,6 @@ void add() throws Exception { ); given(memberCommandService.save(any())).willReturn(1L); - given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.post("/members") @@ -168,7 +159,6 @@ void findAllMember() throws Exception { ); given(memberQueryService.findAll()).willReturn(memberResponses); - given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); mockMvc.perform( MockMvcRequestBuilders.get("/members") From 2ea4a21f19e7f0bc4b30ce6b26e2ed7ca54417e9 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 15:40:50 +0900 Subject: [PATCH 68/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20Service=20Test=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 --- .../application/MemberQueryServiceTest.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index b24ac1895..3b38ab22c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -1,6 +1,5 @@ package com.mapbefine.mapbefine.member.application; -import static java.lang.Long.MAX_VALUE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -101,7 +100,7 @@ void findMemberTopicPermissionById() { @DisplayName("ID 를 통해서 토픽에 권한이 있는자를 조회하려 할 때, 결과가 존재하지 않을 때 예외가 발생한다.") void findMemberTopicPermissionById_whenNoneExistsPermission_thenFail() { // given when then - assertThatThrownBy(() -> memberQueryService.findMemberTopicPermissionById(MAX_VALUE)) + assertThatThrownBy(() -> memberQueryService.findMemberTopicPermissionById(Long.MAX_VALUE)) .isInstanceOf(NoSuchElementException.class); } @@ -125,4 +124,28 @@ void findAllMember() { .isEqualTo(List.of(MemberResponse.from(member), MemberResponse.from(memberr))); } + @Test + @DisplayName("유저를 단일 조회한다.") + void findMemberById() { + // given + Member member = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + + // when + MemberDetailResponse response = memberQueryService.findById(member.getId()); + + // then + assertThat(response).usingRecursiveComparison() + .isEqualTo(MemberDetailResponse.from(member)); + } + + @Test + @DisplayName("조회하려는 유저가 없는 경우 예외를 반환한다.") + void findMemberById_whenNoneExists_thenFail() { + // given when then + assertThatThrownBy(() -> memberQueryService.findById(Long.MAX_VALUE)) + .isInstanceOf(NoSuchElementException.class); + } + } From e521b2cedf04965997d28f33dc3f79ab79c176f2 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 15:48:35 +0900 Subject: [PATCH 69/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20=EC=9D=B8=EC=88=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/MemberIntegrationTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index fa2f61551..4088d3669 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -281,4 +281,45 @@ void findAllMember() { .isEqualTo(List.of(MemberResponse.from(member), MemberResponse.from(memberr))); } + @Test + @DisplayName("유저를 단일 조회한다.") + void findMemberById() { + // given + Member member = Member.of( + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + Role.USER + ); + MemberCreateRequest request = new MemberCreateRequest( + member.getMemberInfo().getName(), + member.getMemberInfo().getEmail(), + member.getMemberInfo().getImageUrl(), + member.getMemberInfo().getRole() + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + member.getMemberInfo().getEmail()).getBytes() + ); + + // when + ExtractableResponse saveMemberResponse = saveMember(request); + Long newMemberId = Long.parseLong(saveMemberResponse.header("Location").split("/")[2]); + + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/members/" + newMemberId) + .then().log().all() + .extract(); + + MemberDetailResponse memberDetailResponse = response.as(MemberDetailResponse.class); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + assertThat(memberDetailResponse) + .usingRecursiveComparison() + .ignoringFields("id", "updateAt") + .isEqualTo(MemberDetailResponse.from(member)); + } + } From e2bb58e2fe707078673d988db27cc467e4e99493 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 19:13:39 +0900 Subject: [PATCH 70/88] =?UTF-8?q?docs=20:=20=EC=9C=A0=EC=A0=80=20=EB=8B=A8?= =?UTF-8?q?=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20API=20=EB=AA=85=EC=84=B8=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 --- backend/src/docs/asciidoc/member.adoc | 4 ++++ .../presentation/MemberControllerTest.java | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index fc5fc0caa..5ca81ca4b 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -23,3 +23,7 @@ operation::member-controller-test/add[snippets='http-request,http-response'] === 유저 목록 조회 operation::member-controller-test/find-all-member[snippets='http-request,http-response'] + +=== 유저 단일 조회 + +operation::member-controller-test/find-member-by-id[snippets='http-request,http-response'] diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 0fe4d7849..563b8512c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -166,4 +166,26 @@ void findAllMember() throws Exception { ).andDo(restDocs.document()); } + @Test + @DisplayName("유저 단일 조회") + void findMemberById() throws Exception { + MemberDetailResponse memberDetailResponse = new MemberDetailResponse( + 1L, + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + LocalDateTime.now() + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + memberDetailResponse.email()).getBytes() + ); + + given(memberQueryService.findById(any())).willReturn(memberDetailResponse); + + mockMvc.perform( + MockMvcRequestBuilders.get("/members/1") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } + } From 9d04afb739b8cde3ddd94ae3b5f9a446a3297a59 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 19:59:12 +0900 Subject: [PATCH 71/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=EA=B0=80=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A0=20=ED=86=A0=ED=94=BD,=20=ED=95=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20Service=20Test=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberQueryService.java | 24 ++++-- .../member/domain/MemberRepository.java | 1 + .../mapbefine/pin/Domain/PinRepository.java | 3 +- .../topic/domain/TopicRepository.java | 3 +- .../application/MemberQueryServiceTest.java | 85 +++++++++++++++++++ 5 files changed, 107 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 539ba861a..15001fdc3 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -55,24 +55,34 @@ public List findAll() { .toList(); } - public List findTopicsByMember(final AuthMember authMember) { - Long memberId = authMember.getMemberId(); - List topicsByCreator = topicRepository.findByCreatorId(memberId); + public List findTopicsByMember(AuthMember authMember) { + validateNull(authMember.getMemberId()); + Member member = memberRepository.findById(authMember.getMemberId()) + .orElseThrow(NoSuchElementException::new); + List topicsByCreator = topicRepository.findByCreator(member); return topicsByCreator.stream() .map(TopicResponse::from) .toList(); } - public List findPinsByMember(final AuthMember authMember) { - Long memberId = authMember.getMemberId(); - List pinsByCreator = pinRepository.findByCreatorId(memberId); + public List findPinsByMember(AuthMember authMember) { + validateNull(authMember.getMemberId()); + Member creator = memberRepository.findById(authMember.getMemberId()) + .orElseThrow(NoSuchElementException::new); + List pinsByCreator = pinRepository.findByCreator(creator); return pinsByCreator.stream() .map(PinResponse::from) .toList(); } + private void validateNull(Long id) { + if (id == null) { + throw new IllegalArgumentException("id 는 null 일 수 없습니다."); + } + } + public List findAllWithPermission(Long topicId) { return memberTopicPermissionRepository.findByTopicId(topicId) .stream() @@ -81,7 +91,7 @@ public List findAllWithPermission(Long topicId) { .toList(); } - public MemberDetailResponse findMemberTopicPermissionById(final Long permissionId) { + public MemberDetailResponse findMemberTopicPermissionById(Long permissionId) { MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) .orElseThrow(NoSuchElementException::new); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index 4935e1628..bd5ee2dc2 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -2,6 +2,7 @@ import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.lang.Nullable; public interface MemberRepository extends JpaRepository { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java index 92a7357f2..58b0ca093 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.pin.Domain; +import com.mapbefine.mapbefine.member.domain.Member; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -20,6 +21,6 @@ public interface PinRepository extends JpaRepository { List findAllByTopicId(Long topicId); - List findByCreatorId(Long creatorId); + List findByCreator(Member creator); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java index 10f9d0cd1..e64543382 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java @@ -1,5 +1,6 @@ package com.mapbefine.mapbefine.topic.domain; +import com.mapbefine.mapbefine.member.domain.Member; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -16,6 +17,6 @@ public interface TopicRepository extends JpaRepository { @Query("update Topic t set t.isDeleted = true where t.id = :topicId") void deleteById(@Param("topicId") Long topicId); - List findByCreatorId(Long creatorId); + List findByCreator(Member creator); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index 3b38ab22c..bd1b26655 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -3,7 +3,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.common.annotation.ServiceTest; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; @@ -12,9 +16,14 @@ import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.List; import java.util.NoSuchElementException; import org.junit.jupiter.api.DisplayName; @@ -36,6 +45,12 @@ public class MemberQueryServiceTest { @Autowired private MemberTopicPermissionRepository memberTopicPermissionRepository; + @Autowired + private LocationRepository locationRepository; + + @Autowired + private PinRepository pinRepository; + @Test @DisplayName("Topic 에 권한이 있는자들을 모두 조회한다.") // creator 는 권한이 있는자들을 조회할 때 조회되어야 할 것인가?? void findAllWithPermission() { @@ -148,4 +163,74 @@ void findMemberById_whenNoneExists_thenFail() { .isInstanceOf(NoSuchElementException.class); } + @Test + @DisplayName("유저가 만든 핀을 조회한다.") + void findPinsByMember() { + // given + Member creator = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Location location = locationRepository.save(LocationFixture.create()); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + Pin pin1 = pinRepository.save(PinFixture.create( + location, + topic, + creator + )); + Pin pin2 = pinRepository.save(PinFixture.create( + location, + topic, + creator + )); + + // when + List response = memberQueryService.findPinsByMember(AuthMember.from(creator)); + + // then + assertThat(response).usingRecursiveComparison() + .isEqualTo(List.of(PinResponse.from(pin1), PinResponse.from(pin2))); + } + + @Test + @DisplayName("존재하지 않는 유저가 Pin 을 조회할 때 예외가 발생한다.") + void findPinsByMember_whenNoneExists_thenFail() { + // given + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + memberRepository.delete(member); + + // when then + assertThatThrownBy(() -> memberQueryService.findPinsByMember(AuthMember.from(member))) + .isInstanceOf(NoSuchElementException.class); + } + + @Test + @DisplayName("유저가 만든 토픽을 조회한다.") + void findTopicsByMember() { + // given + Member creator = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Topic topic1 = topicRepository.save(TopicFixture.createByName("topic1", creator)); + Topic topic2 = topicRepository.save(TopicFixture.createByName("topic2", creator)); + + // when + List response = memberQueryService.findTopicsByMember(AuthMember.from(creator)); + + // then + assertThat(response).usingRecursiveComparison() + .isEqualTo(List.of(TopicResponse.from(topic1), TopicResponse.from(topic2))); + } + + @Test + @DisplayName("존재하지 않는 유저가 본인이 만든 토픽을 조회할 때 예외가 발생한다.") + void findTopicsByMember_whenNoneExists_thenFail() { + // given + Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + memberRepository.delete(member); + + // when then + assertThatThrownBy(() -> memberQueryService.findTopicsByMember(AuthMember.from(member))) + .isInstanceOf(NoSuchElementException.class); + } + } From 96d3512a5baf5518cfca43aaab58dcce06737cc8 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 20:21:32 +0900 Subject: [PATCH 72/88] =?UTF-8?q?test=20:=20=EC=9C=A0=EC=A0=80=EA=B0=80=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A0=20=ED=86=A0=ED=94=BD,=20=ED=95=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9D=B8=EC=88=98=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberQueryServiceTest.java | 24 ++--- .../presentation/MemberControllerTest.java | 44 +++++++++ .../presentation/MemberIntegrationTest.java | 90 ++++++++++++++++++- 3 files changed, 146 insertions(+), 12 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index bd1b26655..822aae8a6 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -172,16 +172,20 @@ void findPinsByMember() { ); Location location = locationRepository.save(LocationFixture.create()); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); - Pin pin1 = pinRepository.save(PinFixture.create( - location, - topic, - creator - )); - Pin pin2 = pinRepository.save(PinFixture.create( - location, - topic, - creator - )); + Pin pin1 = pinRepository.save( + PinFixture.create( + location, + topic, + creator + ) + ); + Pin pin2 = pinRepository.save( + PinFixture.create( + location, + topic, + creator + ) + ); // when List response = memberQueryService.findPinsByMember(AuthMember.from(creator)); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 563b8512c..c8d50be56 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -188,4 +188,48 @@ void findMemberById() throws Exception { ).andDo(restDocs.document()); } + @Test + @DisplayName("유저 단일 조회") + void findPinsByMember() throws Exception { + MemberDetailResponse memberDetailResponse = new MemberDetailResponse( + 1L, + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + LocalDateTime.now() + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + memberDetailResponse.email()).getBytes() + ); + + given(memberQueryService.findById(any())).willReturn(memberDetailResponse); + + mockMvc.perform( + MockMvcRequestBuilders.get("/members/1") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } + + @Test + @DisplayName("유저 단일 조회") + void findTopicsByMember() throws Exception { + MemberDetailResponse memberDetailResponse = new MemberDetailResponse( + 1L, + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + LocalDateTime.now() + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + memberDetailResponse.email()).getBytes() + ); + + given(memberQueryService.findById(any())).willReturn(memberDetailResponse); + + mockMvc.perform( + MockMvcRequestBuilders.get("/members/1") + .header(AUTHORIZATION, authHeader) + ).andDo(restDocs.document()); + } + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index 4088d3669..dd5ac42aa 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -5,6 +5,9 @@ import static org.assertj.core.api.Assertions.assertThat; import com.mapbefine.mapbefine.common.IntegrationTest; +import com.mapbefine.mapbefine.location.LocationFixture; +import com.mapbefine.mapbefine.location.domain.Location; +import com.mapbefine.mapbefine.location.domain.LocationRepository; import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; @@ -13,9 +16,14 @@ import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -35,6 +43,12 @@ class MemberIntegrationTest extends IntegrationTest { @Autowired private TopicRepository topicRepository; + @Autowired + private PinRepository pinRepository; + + @Autowired + private LocationRepository locationRepository; + @Test @DisplayName("Topic 을 만든자가 특정 유저에게 권한을 준다.") void addMemberTopicPermission() { @@ -151,7 +165,8 @@ void findMemberTopicPermissionAll() { .extract(); // then - List memberResponses = response.as(new TypeRef<>() {}); + List memberResponses = response.as(new TypeRef<>() { + }); assertThat(response.statusCode()) .isEqualTo(HttpStatus.OK.value()); assertThat(memberResponses).usingRecursiveComparison() @@ -271,7 +286,8 @@ void findAllMember() { .then().log().all() .extract(); - List memberResponses = response.as(new TypeRef<>() {}); + List memberResponses = response.as(new TypeRef<>() { + }); // then assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); @@ -322,4 +338,74 @@ void findMemberById() { .isEqualTo(MemberDetailResponse.from(member)); } + @Test + @DisplayName("유저가 생성한 핀을 조회한다.") + void findPinsByMember() { + // given + Member creator = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Location location = locationRepository.save(LocationFixture.create()); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + Pin pin1 = pinRepository.save( + PinFixture.create( + location, + topic, + creator + ) + ); + Pin pin2 = pinRepository.save( + PinFixture.create( + location, + topic, + creator + ) + ); + String authHeader = Base64.encodeBase64String( + ("Basic " + creator.getMemberInfo().getEmail()).getBytes() + ); + + // when + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/members/pins") + .then().log().all() + .extract(); + List pinResponses = response.as(new TypeRef<>() {}); + + // then + assertThat(pinResponses).hasSize(2) + .usingRecursiveComparison() + .isEqualTo(List.of(PinResponse.from(pin1), PinResponse.from(pin2))); + } + + @Test + @DisplayName("유저가 생성한 토픽을 조회한다.") + void findTopicsByMember() { + // given + Member creator = memberRepository.save( + MemberFixture.create("member", "member@naver.com", Role.USER) + ); + Topic topic1 = topicRepository.save(TopicFixture.createByName("topic1", creator)); + Topic topic2 = topicRepository.save(TopicFixture.createByName("topic2", creator)); + String authHeader = Base64.encodeBase64String( + ("Basic " + creator.getMemberInfo().getEmail()).getBytes() + ); + + // when + ExtractableResponse response = given().log().all() + .header(AUTHORIZATION, authHeader) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/members/topics") + .then().log().all() + .extract(); + List topicResponses = response.as(new TypeRef<>() {}); + + // then + assertThat(topicResponses).hasSize(2) + .usingRecursiveComparison() + .isEqualTo(List.of(TopicResponse.from(topic1), TopicResponse.from(topic2))); + } + } From 019f330d391367e869d36b219c22597a2feb9248 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Thu, 3 Aug 2023 20:31:49 +0900 Subject: [PATCH 73/88] =?UTF-8?q?docs=20:=20=EC=9C=A0=EC=A0=80=EA=B0=80=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A0=20=ED=86=A0=ED=94=BD,=20=ED=95=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20API=20=EB=AA=85=EC=84=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/member.adoc | 8 +++ .../application/MemberQueryService.java | 1 - .../member/domain/MemberRepository.java | 1 - .../presentation/MemberControllerTest.java | 62 ++++++++++++------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc index 5ca81ca4b..75796870d 100644 --- a/backend/src/docs/asciidoc/member.adoc +++ b/backend/src/docs/asciidoc/member.adoc @@ -27,3 +27,11 @@ operation::member-controller-test/find-all-member[snippets='http-request,http-re === 유저 단일 조회 operation::member-controller-test/find-member-by-id[snippets='http-request,http-response'] + +=== 유저가 만든 핀 조회 + +operation::member-controller-test/find-pins-by-member[snippets='http-request,http-response'] + +=== 유저가 만든 토픽 조회 + +operation::member-controller-test/find-topics-by-member[snippets='http-request,http-response'] diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 15001fdc3..d51557293 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -15,7 +15,6 @@ import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.List; import java.util.NoSuchElementException; -import java.util.Optional; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index bd5ee2dc2..4935e1628 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -2,7 +2,6 @@ import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.lang.Nullable; public interface MemberRepository extends JpaRepository { diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index c8d50be56..70fabc29c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -14,6 +14,8 @@ import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.pin.dto.response.PinResponse; +import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.time.LocalDateTime; import java.util.List; import org.apache.tomcat.util.codec.binary.Base64; @@ -189,45 +191,63 @@ void findMemberById() throws Exception { } @Test - @DisplayName("유저 단일 조회") + @DisplayName("유저가 만든 핀 조회") void findPinsByMember() throws Exception { - MemberDetailResponse memberDetailResponse = new MemberDetailResponse( - 1L, - "member", - "member@naver.com", - "https://map-befine-official.github.io/favicon.png", - LocalDateTime.now() + List pinResponses = List.of( + new PinResponse( + 1L, + "매튜의 산스장", + "지번 주소", + "매튜가 사랑하는 산스장", + 37, + 127 + ), new PinResponse( + 2L, + "매튜의 안갈집", + "지번 주소", + "매튜가 두번은 안 갈 집", + 37, + 127 + ) ); String authHeader = Base64.encodeBase64String( - ("Basic " + memberDetailResponse.email()).getBytes() + "Basic member@naver.com".getBytes() ); - given(memberQueryService.findById(any())).willReturn(memberDetailResponse); + given(memberQueryService.findPinsByMember(any())).willReturn(pinResponses); mockMvc.perform( - MockMvcRequestBuilders.get("/members/1") + MockMvcRequestBuilders.get("/members/pins") .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } @Test - @DisplayName("유저 단일 조회") + @DisplayName("유저가 만든 토픽 조회") void findTopicsByMember() throws Exception { - MemberDetailResponse memberDetailResponse = new MemberDetailResponse( - 1L, - "member", - "member@naver.com", - "https://map-befine-official.github.io/favicon.png", - LocalDateTime.now() - ); String authHeader = Base64.encodeBase64String( - ("Basic " + memberDetailResponse.email()).getBytes() + "Basic member@naver.com".getBytes() + ); + List topicResponses = List.of( + new TopicResponse( + 1L, + "준팍의 또 토픽", + "https://map-befine-official.github.io/favicon.png", + 3, + LocalDateTime.now() + ), new TopicResponse( + 2L, + "준팍의 두번째 토픽", + "https://map-befine-official.github.io/favicon.png", + 5, + LocalDateTime.now() + ) ); - given(memberQueryService.findById(any())).willReturn(memberDetailResponse); + given(memberQueryService.findTopicsByMember(any())).willReturn(topicResponses); mockMvc.perform( - MockMvcRequestBuilders.get("/members/1") + MockMvcRequestBuilders.get("/members/topics") .header(AUTHORIZATION, authHeader) ).andDo(restDocs.document()); } From ec9060c830e0b8728ed3480fd0f92a9211d0ffff Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 7 Aug 2023 15:24:56 +0900 Subject: [PATCH 74/88] =?UTF-8?q?refactor=20:=20MemberInfoTest=20Role=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/member/domain/MemberInfoTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java index 59533cc01..3be1b5f44 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java @@ -58,7 +58,7 @@ void whenNameIsInvalid_thenFail(String invalidName) { @ParameterizedTest @NullSource @EmptySource - @ValueSource(strings = "jakind") + @ValueSource(strings = "member") @DisplayName("유효한 이메일이 아닌 경우 예외가 발생한다") void whenEmailIsInvalid_thenFail(String invalidEmail) { //given when then @@ -87,18 +87,15 @@ void whenImageUrlIsInvalid_thenFail() { @Test @DisplayName("유효하지 않은 Role 이 들어오는 경우 예외가 발생한다.") void whenRoleIsInvalid_thenFail() { - String invalidImageUrl = "image.png"; - //given when then assertThatThrownBy(() -> MemberInfo.of( VALID_NAME, VALID_EMAIL, - invalidImageUrl, - VALID_ROLE + VALID_IMAGE_URL, + null )).isInstanceOf(IllegalArgumentException.class); } - } @Nested From fd70f241b83e14994cbccefa5e44940b423e5951 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 7 Aug 2023 15:27:53 +0900 Subject: [PATCH 75/88] =?UTF-8?q?refactor=20:=20MemberTest=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/mapbefine/member/domain/MemberTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java index baa016399..eb543453b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java @@ -16,12 +16,12 @@ void createMember_success() { String imageUrl = "https://map-befine-official.github.io/favicon.png"; Role role = Role.ADMIN; - // then + // when Member member = Member.of( - "member", - "member@naver.com", - "https://map-befine-official.github.io/favicon.png", - Role.ADMIN + name, + email, + imageUrl, + role ); // then From 459248e72da3ba38f76e0eea5dd03d633f4bc867 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 7 Aug 2023 20:33:25 +0900 Subject: [PATCH 76/88] =?UTF-8?q?refactor=20:=20ServiceTest=20=EB=82=B4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A4=80?= =?UTF-8?q?=EB=B9=84=EA=B3=BC=EC=A0=95=EC=9D=84=20Repository=20=EB=A1=9C?= =?UTF-8?q?=EB=A7=8C=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pin/dto/response/PinDetailResponse.java | 1 - .../application/MemberCommandServiceTest.java | 123 ++++++++++++------ .../application/MemberQueryServiceTest.java | 18 ++- .../domain/MemberTopicPermissionTest.java | 12 +- 4 files changed, 106 insertions(+), 48 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java index e20762ab4..51d835625 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java @@ -4,7 +4,6 @@ import com.mapbefine.mapbefine.pin.Domain.Pin; import com.mapbefine.mapbefine.pin.Domain.PinImage; import com.mapbefine.mapbefine.pin.Domain.PinInfo; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java index c811892c3..628ab47f5 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java @@ -4,19 +4,21 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.mapbefine.mapbefine.auth.domain.AuthMember; +import com.mapbefine.mapbefine.auth.domain.member.Guest; import com.mapbefine.mapbefine.common.annotation.ServiceTest; import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberInfo; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; -import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; import java.util.NoSuchElementException; -import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -36,6 +38,9 @@ class MemberCommandServiceTest { @Autowired private MemberRepository memberRepository; + @Autowired + private MemberTopicPermissionRepository memberTopicPermissionRepository; + @Test @DisplayName("Admin 이 권한을 주는 경우 정상적으로 권한이 주어진다.") void saveMemberTopicPermissionByAdmin() { @@ -51,13 +56,13 @@ void saveMemberTopicPermissionByAdmin() { // when Long savedId = memberCommandService.saveMemberTopicPermission(authAdmin, request); - MemberDetailResponse memberDetailResponse = memberQueryService.findMemberTopicPermissionById(savedId); + MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(savedId) + .orElseThrow(NoSuchElementException::new); + Member memberWithPermission = memberTopicPermission.getMember(); // then - assertThat(memberDetailResponse.id()).isEqualTo(member.getId()); - assertThat(memberDetailResponse.name()).isEqualTo(member.getMemberInfo().getName()); - assertThat(memberDetailResponse.email()).isEqualTo(member.getMemberInfo().getEmail()); - assertThat(memberDetailResponse.imageUrl()).isEqualTo(member.getMemberInfo().getImageUrl()); + assertThat(member).usingRecursiveComparison() + .isEqualTo(memberWithPermission); } @Test @@ -75,13 +80,13 @@ void saveMemberTopicPermissionByCreator() { // when Long savedId = memberCommandService.saveMemberTopicPermission(authCreator, request); - MemberDetailResponse memberDetailResponse = memberQueryService.findMemberTopicPermissionById(savedId); + MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(savedId) + .orElseThrow(NoSuchElementException::new); + Member memberWithPermission = memberTopicPermission.getMember(); // then - assertThat(memberDetailResponse.id()).isEqualTo(member.getId()); - assertThat(memberDetailResponse.name()).isEqualTo(member.getMemberInfo().getName()); - assertThat(memberDetailResponse.email()).isEqualTo(member.getMemberInfo().getEmail()); - assertThat(memberDetailResponse.imageUrl()).isEqualTo(member.getMemberInfo().getImageUrl()); + assertThat(member).usingRecursiveComparison() + .isEqualTo(memberWithPermission); } @Test @@ -103,6 +108,24 @@ void saveMemberTopicPermissionByUser() { .isInstanceOf(IllegalArgumentException.class); } + @Test + @DisplayName("Guest 가 유저에게 권한을 주려는 경우 예외가 발생한다.") + void saveMemberTopicPermissionByGuest() { + // given + Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create("memberss", "memberss@naver.com", Role.USER)); + Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + AuthMember guest = new Guest(); + MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( + topic.getId(), + member.getId() + ); + + // when then + assertThatThrownBy(() -> memberCommandService.saveMemberTopicPermission(guest, request)) + .isInstanceOf(IllegalArgumentException.class); + } + @Test @DisplayName("본인에게 권한을 주려하는 경우 예외가 발생한다.") void saveMemberTopicPermissionByCreator_whenSelf_thenFail() { @@ -124,15 +147,29 @@ void saveMemberTopicPermissionByCreator_whenSelf_thenFail() { @DisplayName("이미 권한을 부여 받은 사람에게 권한을 주는 경우 예외가 발생한다.") void saveMemberTopicPermissionByCreator_whenDuplicate_thenFail() { // given - Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); - Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); + Member creator = memberRepository.save( + MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) + ); + Member member = memberRepository.save( + MemberFixture.create( + "members", + "members@naver.com", + Role.USER + ) + ); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + memberTopicPermissionRepository.save(memberTopicPermission); AuthMember authCreator = AuthMember.from(creator); MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( topic.getId(), member.getId() ); - memberCommandService.saveMemberTopicPermission(authCreator, request); // when then assertThatThrownBy(() -> memberCommandService.saveMemberTopicPermission(authCreator, request)) @@ -147,13 +184,11 @@ void deleteMemberTopicPermissionByAdmin() { Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", admin)); AuthMember authAdmin = AuthMember.from(admin); - MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( - topic.getId(), - member.getId() - ); // when - Long savedId = memberCommandService.saveMemberTopicPermission(authAdmin, request); + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + Long savedId = memberTopicPermissionRepository.save(memberTopicPermission).getId(); memberCommandService.deleteMemberTopicPermission(authAdmin, savedId); // then @@ -168,13 +203,11 @@ void deleteMemberTopicPermissionByCreator() { Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); AuthMember authCreator = AuthMember.from(creator); - MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( - topic.getId(), - member.getId() - ); // when - Long savedId = memberCommandService.saveMemberTopicPermission(authCreator, request); + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + Long savedId = memberTopicPermissionRepository.save(memberTopicPermission).getId(); memberCommandService.deleteMemberTopicPermission(authCreator, savedId); // then @@ -189,15 +222,12 @@ void deleteMemberTopicPermissionByUser() { Member nonCreator = memberRepository.save(MemberFixture.create("memberss", "memberss@naver.com", Role.USER)); Member member = memberRepository.save(MemberFixture.create("members", "members@naver.com", Role.USER)); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); - AuthMember authCreator = AuthMember.from(creator); AuthMember authNonCreator = AuthMember.from(nonCreator); - MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( - topic.getId(), - member.getId() - ); // when - Long savedId = memberCommandService.saveMemberTopicPermission(authCreator, request); + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + Long savedId = memberTopicPermissionRepository.save(memberTopicPermission).getId(); // then assertThatThrownBy(() -> memberCommandService.deleteMemberTopicPermission(authNonCreator, savedId)) @@ -208,7 +238,13 @@ void deleteMemberTopicPermissionByUser() { @DisplayName("존재하지 않는 유저의 권한을 삭제하려 하려는 경우 예외가 발생한다.") void deleteMemberTopicPermissionByCreator_whenNoneExistsPermission_thenFail() { // given - Member creator = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member creator = memberRepository.save( + MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) + ); AuthMember authCreator = AuthMember.from(creator); // when then @@ -225,11 +261,12 @@ void save() { "member@naver.com", Role.USER ); + MemberInfo memberInfo = member.getMemberInfo(); MemberCreateRequest memberCreateRequest = new MemberCreateRequest( - member.getMemberInfo().getName(), - member.getMemberInfo().getEmail(), - member.getMemberInfo().getImageUrl(), - member.getMemberInfo().getRole() + memberInfo.getName(), + memberInfo.getEmail(), + memberInfo.getImageUrl(), + memberInfo.getRole() ); // when @@ -253,11 +290,12 @@ void save_whenDuplicateName_thenFail() { Role.USER ); memberRepository.save(member); + MemberInfo memberInfo = member.getMemberInfo(); MemberCreateRequest memberCreateRequest = new MemberCreateRequest( - member.getMemberInfo().getName(), + memberInfo.getName(), "memberr@naver.com", - member.getMemberInfo().getImageUrl(), - member.getMemberInfo().getRole() + memberInfo.getImageUrl(), + memberInfo.getRole() ); // when @@ -275,11 +313,12 @@ void save_whenDuplicateEmail_thenFail() { Role.USER ); memberRepository.save(member); + MemberInfo memberInfo = member.getMemberInfo(); MemberCreateRequest memberCreateRequest = new MemberCreateRequest( "memberr", - member.getMemberInfo().getEmail(), - member.getMemberInfo().getImageUrl(), - member.getMemberInfo().getRole() + memberInfo.getEmail(), + memberInfo.getImageUrl(), + memberInfo.getRole() ); // when diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index 822aae8a6..cfc219158 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; @ServiceTest -public class MemberQueryServiceTest { +class MemberQueryServiceTest { @Autowired private MemberQueryService memberQueryService; @@ -199,7 +199,13 @@ void findPinsByMember() { @DisplayName("존재하지 않는 유저가 Pin 을 조회할 때 예외가 발생한다.") void findPinsByMember_whenNoneExists_thenFail() { // given - Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save( + MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) + ); memberRepository.delete(member); // when then @@ -229,7 +235,13 @@ void findTopicsByMember() { @DisplayName("존재하지 않는 유저가 본인이 만든 토픽을 조회할 때 예외가 발생한다.") void findTopicsByMember_whenNoneExists_thenFail() { // given - Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save( + MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) + ); memberRepository.delete(member); // when then diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java index 9e24f0c81..067fddd07 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java @@ -15,7 +15,11 @@ class MemberTopicPermissionTest { @DisplayName("정상적인 값을 입력하면 객체가 생성된다.") void createMemberTopicPermission() { // given - Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.ADMIN + ); Topic topic = TopicFixture.createByName("topic", member); // when @@ -33,7 +37,11 @@ void createMemberTopicPermission() { @DisplayName("MemberTopicPermission 을 생성하면, Topic 과 Member 에 등록이 된다.") void createPermissionAssociatedWithTopicAndMember() { // given - Member member = MemberFixture.create("member", "member@naver.com", Role.ADMIN); + Member member = MemberFixture.create( + "member", + "member@naver.com", + Role.ADMIN + ); Topic topic = TopicFixture.createByName("topic", member); // when From 8e192c2c82758e76e1e07758b5d81cc3903dbaad Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 7 Aug 2023 20:49:40 +0900 Subject: [PATCH 77/88] =?UTF-8?q?refactor=20:=20Integeration=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=97=90=EC=84=9C=EB=8F=84=20Repository=20?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=B4=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=A5=BC=20=EC=A4=80=EB=B9=84=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/MemberControllerTest.java | 2 - .../presentation/MemberIntegrationTest.java | 139 ++++++++---------- 2 files changed, 60 insertions(+), 81 deletions(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 70fabc29c..50537a5ef 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -86,7 +86,6 @@ void findMemberTopicPermissionAll() throws Exception { "memberr@naver.com" ) ); - String authHeader = Base64.encodeBase64String( ("Basic " + memberResponses.get(0).email()).getBytes() ); @@ -109,7 +108,6 @@ void findMemberTopicPermissionById() throws Exception { "https://map-befine-official.github.io/favicon.png", LocalDateTime.now() ); - String authHeader = Base64.encodeBase64String( ("Basic " + memberDetailResponse.email()).getBytes() ); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index dd5ac42aa..c2d1c27ad 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -11,6 +11,8 @@ import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.request.MemberCreateRequest; import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; @@ -49,6 +51,9 @@ class MemberIntegrationTest extends IntegrationTest { @Autowired private LocationRepository locationRepository; + @Autowired + private MemberTopicPermissionRepository memberTopicPermissionRepository; + @Test @DisplayName("Topic 을 만든자가 특정 유저에게 권한을 준다.") void addMemberTopicPermission() { @@ -72,24 +77,17 @@ void addMemberTopicPermission() { ); // when - ExtractableResponse response = saveMemberTopicPermission(authHeader, request); - - // then - assertThat(response.header("Location")).isNotBlank(); - assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); - } - - private ExtractableResponse saveMemberTopicPermission( - String authHeader, - MemberTopicPermissionCreateRequest request - ) { - return given().log().all() + ExtractableResponse response = given().log().all() .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/members/permissions") .then().log().all() .extract(); + + // then + assertThat(response.header("Location")).isNotBlank(); + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } @Test @@ -104,22 +102,24 @@ void deleteMemberTopicPermission() { Role.USER ) ); - Member member = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member = memberRepository.save(MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) + ); String authHeader = Base64.encodeBase64String( ("Basic " + creator.getMemberInfo().getEmail()).getBytes() ); Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); - MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( - topic.getId(), - member.getId() - ); // when - ExtractableResponse newMemberTopicPermission = saveMemberTopicPermission(authHeader, request); - long memberTopicPermissionId = Long.parseLong(newMemberTopicPermission.header("Location").split("/")[3]); + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + Long savedId = memberTopicPermissionRepository.save(memberTopicPermission).getId(); ExtractableResponse response = given().log().all() .header(AUTHORIZATION, authHeader) - .when().delete("/members/permissions/" + memberTopicPermissionId) + .when().delete("/members/permissions/" + savedId) .then().log().all() .extract(); @@ -140,24 +140,32 @@ void findMemberTopicPermissionAll() { Role.USER ) ); - Member member1 = memberRepository.save(MemberFixture.create("memberrr", "memberrr@naver.com", Role.USER)); - Member member2 = memberRepository.save(MemberFixture.create("member", "member@naver.com", Role.USER)); + Member member1 = memberRepository.save( + MemberFixture.create( + "memberrr", + "memberrr@naver.com", + Role.USER + ) + ); + Member member2 = memberRepository.save( + MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) + ); String authHeader = Base64.encodeBase64String( ("Basic " + creator.getMemberInfo().getEmail()).getBytes() ); Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); - MemberTopicPermissionCreateRequest request1 = new MemberTopicPermissionCreateRequest( - topic.getId(), - member1.getId() - ); - MemberTopicPermissionCreateRequest request2 = new MemberTopicPermissionCreateRequest( - topic.getId(), - member2.getId() - ); + MemberTopicPermission memberTopicPermission1 = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member1); + MemberTopicPermission memberTopicPermission2 = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member2); // when - saveMemberTopicPermission(authHeader, request1); - saveMemberTopicPermission(authHeader, request2); + memberTopicPermissionRepository.save(memberTopicPermission1); + memberTopicPermissionRepository.save(memberTopicPermission2); ExtractableResponse response = given().log().all() .header(AUTHORIZATION, authHeader) .when().get("/members/permissions/topics/" + topic.getId()) @@ -165,8 +173,7 @@ void findMemberTopicPermissionAll() { .extract(); // then - List memberResponses = response.as(new TypeRef<>() { - }); + List memberResponses = response.as(new TypeRef<>() {}); assertThat(response.statusCode()) .isEqualTo(HttpStatus.OK.value()); assertThat(memberResponses).usingRecursiveComparison() @@ -190,18 +197,14 @@ void findMemberTopicPermissionById() { ("Basic " + creator.getMemberInfo().getEmail()).getBytes() ); Topic topic = topicRepository.save(TopicFixture.createByName("topicName", creator)); - MemberTopicPermissionCreateRequest request = new MemberTopicPermissionCreateRequest( - topic.getId(), - member.getId() - ); + MemberTopicPermission memberTopicPermission = + MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); // when - ExtractableResponse newMemberTopicPermission = saveMemberTopicPermission(authHeader, request); - long memberTopicPermissionId = Long.parseLong(newMemberTopicPermission.header("Location").split("/")[3]); - + memberTopicPermission = memberTopicPermissionRepository.save(memberTopicPermission); ExtractableResponse response = given().log().all() .header(AUTHORIZATION, authHeader) - .when().get("/members/permissions/" + memberTopicPermissionId) + .when().get("/members/permissions/" + memberTopicPermission.getId()) .then().log().all() .extract(); @@ -225,22 +228,16 @@ void add() { ); // when - ExtractableResponse response = saveMember(request); - - // then - assertThat(response.header("Location")).isNotBlank(); - assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); - } - - private ExtractableResponse saveMember( - MemberCreateRequest request - ) { - return given().log().all() + ExtractableResponse response = given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/members") .then().log().all() .extract(); + + // then + assertThat(response.header("Location")).isNotBlank(); + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } @Test @@ -259,25 +256,13 @@ void findAllMember() { "https://map-befine-official.github.io/favicon.png", Role.USER ); - MemberCreateRequest request1 = new MemberCreateRequest( - member.getMemberInfo().getName(), - member.getMemberInfo().getEmail(), - member.getMemberInfo().getImageUrl(), - member.getMemberInfo().getRole() - ); - MemberCreateRequest request2 = new MemberCreateRequest( - memberr.getMemberInfo().getName(), - memberr.getMemberInfo().getEmail(), - memberr.getMemberInfo().getImageUrl(), - memberr.getMemberInfo().getRole() - ); String authHeader = Base64.encodeBase64String( ("Basic " + member.getMemberInfo().getEmail()).getBytes() ); // when - saveMember(request1); - saveMember(request2); + memberRepository.save(member); + memberRepository.save(memberr); ExtractableResponse response = given().log().all() .header(AUTHORIZATION, authHeader) @@ -286,8 +271,7 @@ void findAllMember() { .then().log().all() .extract(); - List memberResponses = response.as(new TypeRef<>() { - }); + List memberResponses = response.as(new TypeRef<>() {}); // then assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); @@ -307,24 +291,17 @@ void findMemberById() { "https://map-befine-official.github.io/favicon.png", Role.USER ); - MemberCreateRequest request = new MemberCreateRequest( - member.getMemberInfo().getName(), - member.getMemberInfo().getEmail(), - member.getMemberInfo().getImageUrl(), - member.getMemberInfo().getRole() - ); String authHeader = Base64.encodeBase64String( ("Basic " + member.getMemberInfo().getEmail()).getBytes() ); // when - ExtractableResponse saveMemberResponse = saveMember(request); - Long newMemberId = Long.parseLong(saveMemberResponse.header("Location").split("/")[2]); + member = memberRepository.save(member); ExtractableResponse response = given().log().all() .header(AUTHORIZATION, authHeader) .contentType(MediaType.APPLICATION_JSON_VALUE) - .when().get("/members/" + newMemberId) + .when().get("/members/" + member.getId()) .then().log().all() .extract(); @@ -343,7 +320,11 @@ void findMemberById() { void findPinsByMember() { // given Member creator = memberRepository.save( - MemberFixture.create("member", "member@naver.com", Role.USER) + MemberFixture.create( + "member", + "member@naver.com", + Role.USER + ) ); Location location = locationRepository.save(LocationFixture.create()); Topic topic = topicRepository.save(TopicFixture.createByName("topic", creator)); From 6424bde68cd8bf688dc61e06c7f476d40bc3c5c9 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Mon, 7 Aug 2023 20:55:30 +0900 Subject: [PATCH 78/88] =?UTF-8?q?style=20:=20=EA=B0=9C=ED=96=89=20?= =?UTF-8?q?=EB=B0=8F=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20import=20=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberQueryService.java | 6 ++- .../MemberTopicPermissionRepository.java | 2 +- .../dto/response/MemberDetailResponse.java | 1 + .../member/dto/response/MemberResponse.java | 1 + .../member/presentation/MemberController.java | 52 +++++++++---------- 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index d51557293..8a4d16648 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -83,7 +83,10 @@ private void validateNull(Long id) { } public List findAllWithPermission(Long topicId) { - return memberTopicPermissionRepository.findByTopicId(topicId) + Topic topic = topicRepository.findById(topicId) + .orElseThrow(NoSuchElementException::new); + + return memberTopicPermissionRepository.findByTopic(topic) .stream() .map(MemberTopicPermission::getMember) .map(MemberResponse::from) @@ -96,4 +99,5 @@ public MemberDetailResponse findMemberTopicPermissionById(Long permissionId) { return MemberDetailResponse.from(memberTopicPermission.getMember()); } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java index c30b9c814..eefca6b8e 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java @@ -6,7 +6,7 @@ public interface MemberTopicPermissionRepository extends JpaRepository { - List findByTopicId(Long topicId); + List findByTopic(Topic topic); boolean existsByTopicAndMember(Topic topic, Member member); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java index 11d308669..24ba9e61b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java @@ -22,4 +22,5 @@ public static MemberDetailResponse from(Member member) { member.getUpdatedAt() ); } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java index 701bdd313..b4c072a31 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java @@ -18,4 +18,5 @@ public static MemberResponse from(Member member) { memberInfo.getEmail() ); } + } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 4d2916285..57b6521d8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -36,6 +36,24 @@ public MemberController( this.memberQueryService = memberQueryService; } + @PostMapping + public ResponseEntity add(@RequestBody MemberCreateRequest request) { + Long savedId = memberCommandService.save(request); + + return ResponseEntity.created(URI.create("/members/" + savedId)).build(); + } + + @LoginRequired + @PostMapping("/permissions") + public ResponseEntity addMemberTopicPermission( + AuthMember authMember, + @RequestBody MemberTopicPermissionCreateRequest request + ) { + Long savedId = memberCommandService.saveMemberTopicPermission(authMember, request); + + return ResponseEntity.created(URI.create("/members/permissions/" + savedId)).build(); + } + @LoginRequired @GetMapping("/{memberId}") public ResponseEntity findMemberById(@PathVariable Long memberId) { @@ -52,13 +70,6 @@ public ResponseEntity> findAllMember() { return ResponseEntity.ok(responses); } - @PostMapping - public ResponseEntity add(@RequestBody MemberCreateRequest request) { - Long savedId = memberCommandService.save(request); - - return ResponseEntity.created(URI.create("/members/" + savedId)).build(); - } - @LoginRequired @GetMapping("/topics") public ResponseEntity> findTopicsByMember(AuthMember authMember) { @@ -75,25 +86,6 @@ public ResponseEntity> findPinsByMember(AuthMember authMember) return ResponseEntity.ok(responses); } - @LoginRequired - @PostMapping("/permissions") - public ResponseEntity addMemberTopicPermission( - AuthMember authMember, - @RequestBody MemberTopicPermissionCreateRequest request - ) { - Long savedId = memberCommandService.saveMemberTopicPermission(authMember, request); - - return ResponseEntity.created(URI.create("/members/permissions/" + savedId)).build(); - } - - @LoginRequired - @DeleteMapping("/permissions/{permissionId}") - public ResponseEntity deleteMemberTopicPermission(AuthMember authMember, @PathVariable Long permissionId) { - memberCommandService.deleteMemberTopicPermission(authMember, permissionId); - - return ResponseEntity.noContent().build(); - } - @LoginRequired @GetMapping("/permissions/topics/{topicId}") public ResponseEntity> findMemberTopicPermissionAll(@PathVariable Long topicId) { @@ -110,4 +102,12 @@ public ResponseEntity findMemberTopicPermissionById(@PathV return ResponseEntity.ok(response); } + @LoginRequired + @DeleteMapping("/permissions/{permissionId}") + public ResponseEntity deleteMemberTopicPermission(AuthMember authMember, @PathVariable Long permissionId) { + memberCommandService.deleteMemberTopicPermission(authMember, permissionId); + + return ResponseEntity.noContent().build(); + } + } From a17a621ce03c395827ed00b4d944e8d067da5a71 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 8 Aug 2023 17:44:58 +0900 Subject: [PATCH 79/88] =?UTF-8?q?refactor=20:=20=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=EA=B6=8C=ED=95=9C=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20ID=20=EA=B0=92=EB=8F=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=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 --- .../application/LocationQueryService.java | 2 +- .../mapbefine/location/domain/Location.java | 3 +- .../application/MemberQueryService.java | 15 ++++--- .../mapbefine/member/domain/Member.java | 2 +- .../MemberTopicPermissionDetailResponse.java | 17 +++++++ .../MemberTopicPermissionResponse.java | 17 +++++++ .../member/presentation/MemberController.java | 10 +++-- .../pin/application/PinCommandService.java | 6 +-- .../pin/application/PinQueryService.java | 4 +- .../mapbefine/pin/{Domain => domain}/Pin.java | 2 +- .../pin/{Domain => domain}/PinImage.java | 2 +- .../pin/{Domain => domain}/PinInfo.java | 2 +- .../pin/{Domain => domain}/PinRepository.java | 2 +- .../pin/dto/response/PinDetailResponse.java | 6 +-- .../pin/dto/response/PinResponse.java | 5 +-- .../application/TopicCommandService.java | 4 +- .../mapbefine/topic/domain/Topic.java | 2 +- .../application/MemberQueryServiceTest.java | 18 +++++--- .../presentation/MemberControllerTest.java | 45 ++++++++++++------- .../presentation/MemberIntegrationTest.java | 19 +++++--- .../mapbefine/mapbefine/pin/PinFixture.java | 2 +- .../application/PinCommandServiceTest.java | 4 +- .../pin/application/PinQueryServiceTest.java | 6 +-- .../mapbefine/pin/domain/PinImageTest.java | 2 - .../mapbefine/pin/domain/PinInfoTest.java | 1 - .../pin/domain/PinRepositoryTest.java | 2 - .../mapbefine/pin/domain/PinTest.java | 2 - .../mapbefine/topic/TopicIntegrationTest.java | 4 +- .../application/TopicCommandServiceTest.java | 2 +- .../mapbefine/topic/domain/TopicTest.java | 2 +- 30 files changed, 131 insertions(+), 79 deletions(-) create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java create mode 100644 backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionResponse.java rename backend/src/main/java/com/mapbefine/mapbefine/pin/{Domain => domain}/Pin.java (98%) rename backend/src/main/java/com/mapbefine/mapbefine/pin/{Domain => domain}/PinImage.java (95%) rename backend/src/main/java/com/mapbefine/mapbefine/pin/{Domain => domain}/PinInfo.java (97%) rename backend/src/main/java/com/mapbefine/mapbefine/pin/{Domain => domain}/PinRepository.java (95%) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java index e77e28248..713aa5e4a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/application/LocationQueryService.java @@ -7,7 +7,7 @@ import com.mapbefine.mapbefine.location.domain.Location; import com.mapbefine.mapbefine.location.domain.LocationRepository; import com.mapbefine.mapbefine.location.dto.CoordinateRequest; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.Collection; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java index a5e859130..d4b61dcd9 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/location/domain/Location.java @@ -3,14 +3,13 @@ import static lombok.AccessLevel.PROTECTED; import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import lombok.Getter; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 8a4d16648..a19c2a01d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -7,8 +7,10 @@ import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; +import com.mapbefine.mapbefine.pin.domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; @@ -82,22 +84,21 @@ private void validateNull(Long id) { } } - public List findAllWithPermission(Long topicId) { + public List findAllWithPermission(Long topicId) { Topic topic = topicRepository.findById(topicId) .orElseThrow(NoSuchElementException::new); return memberTopicPermissionRepository.findByTopic(topic) .stream() - .map(MemberTopicPermission::getMember) - .map(MemberResponse::from) + .map(MemberTopicPermissionResponse::from) .toList(); } - public MemberDetailResponse findMemberTopicPermissionById(Long permissionId) { + public MemberTopicPermissionDetailResponse findMemberTopicPermissionById(Long permissionId) { MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) .orElseThrow(NoSuchElementException::new); - return MemberDetailResponse.from(memberTopicPermission.getMember()); + return MemberTopicPermissionDetailResponse.from(memberTopicPermission); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 7e5c5d0e0..b734a0a00 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -3,7 +3,7 @@ import static lombok.AccessLevel.PROTECTED; import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.topic.domain.Topic; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java new file mode 100644 index 000000000..946fece8c --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java @@ -0,0 +1,17 @@ +package com.mapbefine.mapbefine.member.dto.response; + +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; + +public record MemberTopicPermissionDetailResponse( + Long id, + MemberDetailResponse memberDetailResponse +) { + + public static MemberTopicPermissionDetailResponse from(MemberTopicPermission memberTopicPermission) { + return new MemberTopicPermissionDetailResponse( + memberTopicPermission.getId(), + MemberDetailResponse.from(memberTopicPermission.getMember()) + ); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionResponse.java new file mode 100644 index 000000000..0e0dc6daa --- /dev/null +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionResponse.java @@ -0,0 +1,17 @@ +package com.mapbefine.mapbefine.member.dto.response; + +import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; + +public record MemberTopicPermissionResponse( + Long id, + MemberResponse memberResponse +) { + + public static MemberTopicPermissionResponse from(MemberTopicPermission memberTopicPermission) { + return new MemberTopicPermissionResponse( + memberTopicPermission.getId(), + MemberResponse.from(memberTopicPermission.getMember()) + ); + } + +} diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index 57b6521d8..c2300157f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -8,6 +8,8 @@ import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.net.URI; @@ -88,16 +90,16 @@ public ResponseEntity> findPinsByMember(AuthMember authMember) @LoginRequired @GetMapping("/permissions/topics/{topicId}") - public ResponseEntity> findMemberTopicPermissionAll(@PathVariable Long topicId) { - List responses = memberQueryService.findAllWithPermission(topicId); + public ResponseEntity> findMemberTopicPermissionAll(@PathVariable Long topicId) { + List responses = memberQueryService.findAllWithPermission(topicId); return ResponseEntity.ok(responses); } @LoginRequired @GetMapping("/permissions/{permissionId}") - public ResponseEntity findMemberTopicPermissionById(@PathVariable Long permissionId) { - MemberDetailResponse response = memberQueryService.findMemberTopicPermissionById(permissionId); + public ResponseEntity findMemberTopicPermissionById(@PathVariable Long permissionId) { + MemberTopicPermissionDetailResponse response = memberQueryService.findMemberTopicPermissionById(permissionId); return ResponseEntity.ok(response); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java index c0c8929d0..14d1749b7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinCommandService.java @@ -7,9 +7,9 @@ import com.mapbefine.mapbefine.location.domain.LocationRepository; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinImage; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinImage; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; import com.mapbefine.mapbefine.topic.domain.Topic; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java index 94e9e17f0..20daf3de8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/application/PinQueryService.java @@ -1,8 +1,8 @@ package com.mapbefine.mapbefine.pin.application; import com.mapbefine.mapbefine.auth.domain.AuthMember; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/Pin.java similarity index 98% rename from backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/domain/Pin.java index 309188653..c5741fdab 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/Pin.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/Pin.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.pin.Domain; +package com.mapbefine.mapbefine.pin.domain; import static lombok.AccessLevel.PROTECTED; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinImage.java similarity index 95% rename from backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinImage.java index 5e3e27741..ef38515c7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinImage.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinImage.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.pin.Domain; +package com.mapbefine.mapbefine.pin.domain; import com.mapbefine.mapbefine.common.entity.Image; import jakarta.persistence.Embedded; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java similarity index 97% rename from backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java index 225bd12ef..2f203c946 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.pin.Domain; +package com.mapbefine.mapbefine.pin.domain; import static lombok.AccessLevel.PROTECTED; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java similarity index 95% rename from backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java rename to backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java index 58b0ca093..56c5aeb69 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/Domain/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java @@ -1,4 +1,4 @@ -package com.mapbefine.mapbefine.pin.Domain; +package com.mapbefine.mapbefine.pin.domain; import com.mapbefine.mapbefine.member.domain.Member; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java index 51d835625..fb2c2cd65 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinDetailResponse.java @@ -1,9 +1,9 @@ package com.mapbefine.mapbefine.pin.dto.response; import com.mapbefine.mapbefine.common.entity.Image; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinImage; -import com.mapbefine.mapbefine.pin.Domain.PinInfo; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinImage; +import com.mapbefine.mapbefine.pin.domain.PinInfo; import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java index a4eb25903..d93d6820d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/dto/response/PinResponse.java @@ -1,8 +1,7 @@ package com.mapbefine.mapbefine.pin.dto.response; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinInfo; -import java.math.BigDecimal; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinInfo; public record PinResponse( Long id, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java index 9c12cbf62..4537cbea7 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/application/TopicCommandService.java @@ -3,8 +3,8 @@ import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; import com.mapbefine.mapbefine.topic.dto.request.TopicCreateRequest; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java index 16766ebb6..266f39101 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/Topic.java @@ -5,7 +5,7 @@ import com.mapbefine.mapbefine.common.entity.BaseTimeEntity; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Embedded; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java index cfc219158..3b8765e69 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberQueryServiceTest.java @@ -16,9 +16,11 @@ import com.mapbefine.mapbefine.member.domain.Role; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; import com.mapbefine.mapbefine.pin.PinFixture; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; @@ -77,12 +79,13 @@ void findAllWithPermission() { ); // when - List memberResponses = memberQueryService.findAllWithPermission(topic1.getId()); + List memberTopicPermissionResponses = memberQueryService.findAllWithPermission(topic1.getId()); MemberResponse memberResponse1 = MemberResponse.from(member1InTopic1); MemberResponse memberResponse2 = MemberResponse.from(member2InTopic1); // then - assertThat(memberResponses).hasSize(2) + assertThat(memberTopicPermissionResponses).hasSize(2) + .extracting(MemberTopicPermissionResponse::memberResponse) .usingRecursiveComparison() .isEqualTo(List.of(memberResponse1, memberResponse2)); } @@ -103,11 +106,14 @@ void findMemberTopicPermissionById() { ).getId(); // when - MemberDetailResponse memberDetailResponse = memberQueryService.findMemberTopicPermissionById(savedId); + MemberTopicPermissionDetailResponse memberTopicPermissionDetailResponse = + memberQueryService.findMemberTopicPermissionById(savedId); MemberDetailResponse permissionUserResponse = MemberDetailResponse.from(permissionUser); // then - assertThat(memberDetailResponse).usingRecursiveComparison() + assertThat(memberTopicPermissionDetailResponse) + .extracting(MemberTopicPermissionDetailResponse::memberDetailResponse) + .usingRecursiveComparison() .isEqualTo(permissionUserResponse); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 50537a5ef..36db78c5a 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -14,6 +14,8 @@ import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.time.LocalDateTime; @@ -74,23 +76,29 @@ void deleteMemberTopicPermission() throws Exception { @Test @DisplayName("권한이 있는 자들 모두 조회") void findMemberTopicPermissionAll() throws Exception { - List memberResponses = List.of( - new MemberResponse( + List memberTopicPermissionResponses = List.of( + new MemberTopicPermissionResponse( 1L, - "member", - "member@naver.com" + new MemberResponse( + 1L, + "member", + "member@naver.com" + ) ), - new MemberResponse( - 2L, - "memberr", - "memberr@naver.com" + new MemberTopicPermissionResponse( + 1L, + new MemberResponse( + 2L, + "memberr", + "memberr@naver.com" + ) ) ); String authHeader = Base64.encodeBase64String( - ("Basic " + memberResponses.get(0).email()).getBytes() + ("Basic " + memberTopicPermissionResponses.get(0).memberResponse().email()).getBytes() ); - given(memberQueryService.findAllWithPermission(any())).willReturn(memberResponses); + given(memberQueryService.findAllWithPermission(any())).willReturn(memberTopicPermissionResponses); mockMvc.perform( MockMvcRequestBuilders.get("/members/permissions/topics/1") @@ -101,18 +109,21 @@ void findMemberTopicPermissionAll() throws Exception { @Test @DisplayName("권한이 있는 자들 모두 조회") void findMemberTopicPermissionById() throws Exception { - MemberDetailResponse memberDetailResponse = new MemberDetailResponse( + MemberTopicPermissionDetailResponse memberTopicPermissionDetailResponse = new MemberTopicPermissionDetailResponse( 1L, - "member", - "member@naver.com", - "https://map-befine-official.github.io/favicon.png", - LocalDateTime.now() + new MemberDetailResponse( + 1L, + "member", + "member@naver.com", + "https://map-befine-official.github.io/favicon.png", + LocalDateTime.now() + ) ); String authHeader = Base64.encodeBase64String( - ("Basic " + memberDetailResponse.email()).getBytes() + ("Basic " + memberTopicPermissionDetailResponse.memberDetailResponse().email()).getBytes() ); - given(memberQueryService.findMemberTopicPermissionById(any())).willReturn(memberDetailResponse); + given(memberQueryService.findMemberTopicPermissionById(any())).willReturn(memberTopicPermissionDetailResponse); mockMvc.perform( MockMvcRequestBuilders.get("/members/permissions/1") diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index c2d1c27ad..a9e8b2e48 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -18,8 +18,10 @@ import com.mapbefine.mapbefine.member.dto.request.MemberTopicPermissionCreateRequest; import com.mapbefine.mapbefine.member.dto.response.MemberDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberResponse; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; +import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.PinFixture; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.TopicFixture; @@ -173,10 +175,13 @@ void findMemberTopicPermissionAll() { .extract(); // then - List memberResponses = response.as(new TypeRef<>() {}); + List memberTopicPermissionResponses = response.as(new TypeRef<>() {}); assertThat(response.statusCode()) .isEqualTo(HttpStatus.OK.value()); - assertThat(memberResponses).usingRecursiveComparison() + assertThat(memberTopicPermissionResponses) + .hasSize(2) + .extracting(MemberTopicPermissionResponse::memberResponse) + .usingRecursiveComparison() .isEqualTo(List.of(MemberResponse.from(member1), MemberResponse.from(member2))); } @@ -209,10 +214,12 @@ void findMemberTopicPermissionById() { .extract(); // then - MemberDetailResponse memberResponses = response.as(MemberDetailResponse.class); + MemberTopicPermissionDetailResponse memberTopicPermissionDetailResponse = response.as(MemberTopicPermissionDetailResponse.class); assertThat(response.statusCode()) .isEqualTo(HttpStatus.OK.value()); - assertThat(memberResponses).usingRecursiveComparison() + assertThat(memberTopicPermissionDetailResponse) + .extracting(MemberTopicPermissionDetailResponse::memberDetailResponse) + .usingRecursiveComparison() .isEqualTo(MemberDetailResponse.from(member)); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java index f87333bef..07f8e38b5 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/PinFixture.java @@ -2,7 +2,7 @@ import com.mapbefine.mapbefine.location.domain.Location; import com.mapbefine.mapbefine.member.domain.Member; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicInfo; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java index fe54e25ec..dd0f8e130 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java @@ -12,8 +12,8 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest; import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest; import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index 002631223..54774b77b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -13,9 +13,9 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinImage; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinImage; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.domain.Permission; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java index f13f8f57e..fd6697756 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinImageTest.java @@ -7,8 +7,6 @@ import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinImage; import com.mapbefine.mapbefine.pin.PinFixture; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java index d572d1bea..a3f446377 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinInfoTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.mapbefine.mapbefine.pin.Domain.PinInfo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java index 17e0850b5..0a976acd2 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java @@ -10,8 +10,6 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java index bd9ce6922..331fb5e3f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java @@ -10,8 +10,6 @@ import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinInfo; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Permission; import com.mapbefine.mapbefine.topic.domain.Publicity; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java index a8aeddbe2..cffd1505d 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/TopicIntegrationTest.java @@ -7,8 +7,8 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; -import com.mapbefine.mapbefine.pin.Domain.PinRepository; +import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.topic.domain.Permission; import com.mapbefine.mapbefine.topic.domain.Publicity; import com.mapbefine.mapbefine.topic.domain.Topic; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java index d96ce26d3..5e5294032 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/application/TopicCommandServiceTest.java @@ -11,7 +11,7 @@ import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.pin.PinFixture; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java index 6a328c4b4..bbee93cd5 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicTest.java @@ -6,7 +6,7 @@ import com.mapbefine.mapbefine.member.MemberFixture; import com.mapbefine.mapbefine.member.domain.Member; import com.mapbefine.mapbefine.member.domain.Role; -import com.mapbefine.mapbefine.pin.Domain.Pin; +import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.pin.PinFixture; import java.util.List; import org.junit.jupiter.api.BeforeEach; From e6846a47da4d490a9688b6243632eac6877c15ca Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 8 Aug 2023 22:27:43 +0900 Subject: [PATCH 80/88] =?UTF-8?q?fix=20:=20ignoringFields=20=EC=97=90=20cr?= =?UTF-8?q?eatedAt,=20updatedAt=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/MemberTopicPermissionDetailResponse.java | 3 +++ .../mapbefine/mapbefine/topic/domain/TopicRepository.java | 2 ++ .../member/application/MemberCommandServiceTest.java | 2 ++ .../mapbefine/member/domain/MemberTopicPermissionTest.java | 4 ++++ .../mapbefine/member/presentation/MemberControllerTest.java | 1 + .../member/presentation/MemberIntegrationTest.java | 6 +++--- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java index 946fece8c..50c554681 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberTopicPermissionDetailResponse.java @@ -1,15 +1,18 @@ package com.mapbefine.mapbefine.member.dto.response; import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; +import java.time.LocalDateTime; public record MemberTopicPermissionDetailResponse( Long id, + LocalDateTime updatedAt, MemberDetailResponse memberDetailResponse ) { public static MemberTopicPermissionDetailResponse from(MemberTopicPermission memberTopicPermission) { return new MemberTopicPermissionDetailResponse( memberTopicPermission.getId(), + memberTopicPermission.getUpdatedAt(), MemberDetailResponse.from(memberTopicPermission.getMember()) ); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java index e64543382..91b7e818c 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java @@ -19,4 +19,6 @@ public interface TopicRepository extends JpaRepository { List findByCreator(Member creator); + List findByCreatorId(Long creatorId); + } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java index 465cc781e..c5003a615 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java @@ -62,6 +62,7 @@ void saveMemberTopicPermissionByAdmin() { // then assertThat(member).usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") .isEqualTo(memberWithPermission); } @@ -90,6 +91,7 @@ void saveMemberTopicPermissionByCreator() { // then assertThat(member).usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") .isEqualTo(memberWithPermission); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java index 067fddd07..ec058f00a 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionTest.java @@ -28,8 +28,10 @@ void createMemberTopicPermission() { // then assertThat(memberTopicPermission.getMember()).usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") .isEqualTo(member); assertThat(memberTopicPermission.getTopic()).usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") .isEqualTo(topic); } @@ -54,8 +56,10 @@ void createPermissionAssociatedWithTopicAndMember() { assertThat(topicsWithPermission).hasSize(1); assertThat(memberTopicPermissions).hasSize(1); assertThat(topicsWithPermission.get(0)).usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") .isEqualTo(topic); assertThat(memberTopicPermissions.get(0)).usingRecursiveComparison() + .ignoringFields("createdAt", "updatedAt") .isEqualTo(memberTopicPermission); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java index 36db78c5a..527f8a125 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberControllerTest.java @@ -111,6 +111,7 @@ void findMemberTopicPermissionAll() throws Exception { void findMemberTopicPermissionById() throws Exception { MemberTopicPermissionDetailResponse memberTopicPermissionDetailResponse = new MemberTopicPermissionDetailResponse( 1L, + LocalDateTime.now(), new MemberDetailResponse( 1L, "member", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index a9e8b2e48..e9516935b 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -20,9 +20,9 @@ import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; +import com.mapbefine.mapbefine.pin.PinFixture; import com.mapbefine.mapbefine.pin.domain.Pin; import com.mapbefine.mapbefine.pin.domain.PinRepository; -import com.mapbefine.mapbefine.pin.PinFixture; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.TopicFixture; import com.mapbefine.mapbefine.topic.domain.Topic; @@ -220,6 +220,7 @@ void findMemberTopicPermissionById() { assertThat(memberTopicPermissionDetailResponse) .extracting(MemberTopicPermissionDetailResponse::memberDetailResponse) .usingRecursiveComparison() + .ignoringFields("updatedAt") .isEqualTo(MemberDetailResponse.from(member)); } @@ -284,7 +285,6 @@ void findAllMember() { assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); assertThat(memberResponses).hasSize(2) .usingRecursiveComparison() - .ignoringFields("id") .isEqualTo(List.of(MemberResponse.from(member), MemberResponse.from(memberr))); } @@ -318,7 +318,7 @@ void findMemberById() { assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); assertThat(memberDetailResponse) .usingRecursiveComparison() - .ignoringFields("id", "updateAt") + .ignoringFields("updateAt") .isEqualTo(MemberDetailResponse.from(member)); } From f623a603a20849cc5cd53c8254b97928a619ef97 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Tue, 8 Aug 2023 22:35:09 +0900 Subject: [PATCH 81/88] =?UTF-8?q?fix=20:=20github=20action=20test=20?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EA=B9=A8=EC=A7=80=EB=8A=94=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/member/presentation/MemberIntegrationTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index e9516935b..c4eef6e6f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -3,6 +3,7 @@ import static io.restassured.RestAssured.given; import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.LOCAL_DATE_TIME; import com.mapbefine.mapbefine.common.IntegrationTest; import com.mapbefine.mapbefine.location.LocationFixture; @@ -31,6 +32,7 @@ import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import java.time.LocalDateTime; import java.util.List; import org.apache.commons.codec.binary.Base64; import org.junit.jupiter.api.DisplayName; @@ -220,7 +222,7 @@ void findMemberTopicPermissionById() { assertThat(memberTopicPermissionDetailResponse) .extracting(MemberTopicPermissionDetailResponse::memberDetailResponse) .usingRecursiveComparison() - .ignoringFields("updatedAt") + .ignoringFieldsOfTypes(LocalDateTime.class) .isEqualTo(MemberDetailResponse.from(member)); } @@ -393,6 +395,7 @@ void findTopicsByMember() { // then assertThat(topicResponses).hasSize(2) .usingRecursiveComparison() + .ignoringFieldsOfTypes(LocalDateTime.class) .isEqualTo(List.of(TopicResponse.from(topic1), TopicResponse.from(topic2))); } From 0b3210166a5e4c52078cb6387a78250bc50a946f Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 09:31:14 +0900 Subject: [PATCH 82/88] =?UTF-8?q?refactor=20:=20MemberDetailResponse=20upd?= =?UTF-8?q?ateAt=20->=20updatedAt=20=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/member/dto/response/MemberDetailResponse.java | 2 +- .../mapbefine/member/presentation/MemberIntegrationTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java index 24ba9e61b..25aa2aa0b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java @@ -9,7 +9,7 @@ public record MemberDetailResponse( String name, String email, String imageUrl, - LocalDateTime updateAt + LocalDateTime updatedAt ) { public static MemberDetailResponse from(Member member) { MemberInfo memberInfo = member.getMemberInfo(); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java index c4eef6e6f..502e8aa2c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/presentation/MemberIntegrationTest.java @@ -320,7 +320,7 @@ void findMemberById() { assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); assertThat(memberDetailResponse) .usingRecursiveComparison() - .ignoringFields("updateAt") + .ignoringFields("updatedAt") .isEqualTo(MemberDetailResponse.from(member)); } From 50888d3260ff29dea549067a468f1e42f6aa1b13 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 09:40:16 +0900 Subject: [PATCH 83/88] =?UTF-8?q?refactor=20:=20Member=20name=20->=20nickN?= =?UTF-8?q?ame=20=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberCommandService.java | 2 +- .../mapbefine/member/domain/MemberInfo.java | 34 +++++++++---------- .../member/domain/MemberRepository.java | 2 +- .../dto/response/MemberDetailResponse.java | 4 +-- .../member/dto/response/MemberResponse.java | 4 +-- .../mapbefine/pin/domain/PinInfo.java | 2 +- .../mapbefine/topic/domain/TopicInfo.java | 2 +- .../mapbefine/common/RestDocsIntegration.java | 2 +- .../application/MemberCommandServiceTest.java | 4 +-- .../domain/MemberDetailResponseTest.java | 4 +-- .../member/domain/MemberInfoTest.java | 26 +++++++------- .../member/domain/MemberResponseTest.java | 4 +-- .../mapbefine/member/domain/MemberTest.java | 6 ++-- .../application/PinCommandServiceTest.java | 20 +++++------ .../pin/application/PinQueryServiceTest.java | 8 ++--- .../pin/domain/PinRepositoryTest.java | 8 ++--- .../mapbefine/pin/domain/PinTest.java | 4 +-- .../mapbefine/topic/domain/TopicInfoTest.java | 4 +-- 18 files changed, 70 insertions(+), 70 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index f77ebc500..b22dba6c8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -47,7 +47,7 @@ public Long save(MemberCreateRequest request) { } private void validateUniqueName(String name) { - if (memberRepository.existsByMemberInfoName(name)) { + if (memberRepository.existsByMemberInfoNickName(name)) { throw new IllegalArgumentException("이미 존재하는 이름입니다."); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index cc14fa656..f876e0984 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -16,11 +16,11 @@ @Getter public class MemberInfo { - private static final int MAX_NAME_LENGTH = 20; + private static final int MAX_NICK_NAME_LENGTH = 20; private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; @Column(nullable = false, length = 20, unique = true) - private String name; + private String nickName; @Column(nullable = false, unique = true) private String email; @@ -33,56 +33,56 @@ public class MemberInfo { private Role role; private MemberInfo( - String name, + String nickName, String email, Image imageUrl, Role role ) { - this.name = name; + this.nickName = nickName; this.email = email; this.imageUrl = imageUrl; this.role = role; } public static MemberInfo of( - String name, + String nickName, String email, String imageUrl, Role role ) { - validateName(name); + validateNickName(nickName); validateEmail(email); validateRole(role); return new MemberInfo( - name, + nickName, email, Image.of(imageUrl), role ); } - public void update(String name, String email, String imageUrl) { - validateName(name); + public void update(String nickName, String email, String imageUrl) { + validateNickName(nickName); validateEmail(email); - this.name = name; + this.nickName = nickName; this.email = email; this.imageUrl = Image.of(imageUrl); } - private static void validateName(String name) { - if (name == null) { - throw new IllegalArgumentException("name null"); + private static void validateNickName(String nickName) { + if (nickName == null) { + throw new IllegalArgumentException("닉네임은 필수로 입력해야합니다."); } - if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { - throw new IllegalArgumentException("이름 길이 이상"); + if (nickName.isBlank() || nickName.length() > MAX_NICK_NAME_LENGTH) { + throw new IllegalArgumentException("닉네임 길이는 최소 1 자에서 " + MAX_NICK_NAME_LENGTH + " 자여야 합니다."); } } private static void validateEmail(String email) { if (email == null) { - throw new IllegalArgumentException("email null"); + throw new IllegalArgumentException("이메일은 필수로 입력해야합니다."); } if (!RegexUtil.matches(VALID_EMAIL_URL_REGEX, email)) { @@ -92,7 +92,7 @@ private static void validateEmail(String email) { private static void validateRole(Role role) { if (role == null) { - throw new IllegalArgumentException("role null"); + throw new IllegalArgumentException("역할은 필수로 입력해야합니다."); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java index 4935e1628..175c0d1a8 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberRepository.java @@ -7,7 +7,7 @@ public interface MemberRepository extends JpaRepository { Optional findByMemberInfoEmail(String email); - boolean existsByMemberInfoName(String name); + boolean existsByMemberInfoNickName(String name); boolean existsByMemberInfoEmail(String email); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java index 25aa2aa0b..1dc6ccdc4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberDetailResponse.java @@ -6,7 +6,7 @@ public record MemberDetailResponse( Long id, - String name, + String nickName, String email, String imageUrl, LocalDateTime updatedAt @@ -16,7 +16,7 @@ public static MemberDetailResponse from(Member member) { return new MemberDetailResponse( member.getId(), - memberInfo.getName(), + memberInfo.getNickName(), memberInfo.getEmail(), memberInfo.getImageUrl(), member.getUpdatedAt() diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java index b4c072a31..394ee43c5 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/response/MemberResponse.java @@ -5,7 +5,7 @@ public record MemberResponse ( Long id, - String name, + String nickName, String email ) { @@ -14,7 +14,7 @@ public static MemberResponse from(Member member) { return new MemberResponse( member.getId(), - memberInfo.getName(), + memberInfo.getNickName(), memberInfo.getEmail() ); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java index 2f203c946..7f7c7bcd4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinInfo.java @@ -37,7 +37,7 @@ public static PinInfo of(String name, String description) { private static void validateName(String name) { if (name == null) { - throw new IllegalArgumentException("name null"); + throw new IllegalArgumentException("nickName null"); } if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { throw new IllegalArgumentException("이름 길이 이상"); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java index d4d2bf002..8850766c6 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java @@ -56,7 +56,7 @@ public static TopicInfo of( private static void validateName(String name) { if (name == null) { - throw new IllegalArgumentException("name null"); + throw new IllegalArgumentException("nickName null"); } if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { throw new IllegalArgumentException("이름 길이 이상"); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java b/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java index a6ecf542e..3bf037791 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/common/RestDocsIntegration.java @@ -44,7 +44,7 @@ void beforeEach( final RestDocumentationContextProvider provider ) throws Exception { given(authInterceptor.preHandle(any(), any(), any())).willReturn(true); - this.restDocs = MockMvcRestDocumentation.document("{class-name}/{method-name}"); + this.restDocs = MockMvcRestDocumentation.document("{class-nickName}/{method-nickName}"); this.mockMvc = MockMvcBuilders.webAppContextSetup(context) .apply( MockMvcRestDocumentation.documentationConfiguration(provider) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java index c5003a615..563e06d2c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/application/MemberCommandServiceTest.java @@ -293,7 +293,7 @@ void save() { ); MemberInfo memberInfo = member.getMemberInfo(); MemberCreateRequest memberCreateRequest = new MemberCreateRequest( - memberInfo.getName(), + memberInfo.getNickName(), memberInfo.getEmail(), memberInfo.getImageUrl(), memberInfo.getRole() @@ -322,7 +322,7 @@ void save_whenDuplicateName_thenFail() { memberRepository.save(member); MemberInfo memberInfo = member.getMemberInfo(); MemberCreateRequest memberCreateRequest = new MemberCreateRequest( - memberInfo.getName(), + memberInfo.getNickName(), "memberr@naver.com", memberInfo.getImageUrl(), memberInfo.getRole() diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java index 9aea6b74d..1d8f8c5ea 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberDetailResponseTest.java @@ -23,8 +23,8 @@ void createMemberResponse_success() { MemberDetailResponse memberDetailResponse = MemberDetailResponse.from(member); // then - assertThat(memberDetailResponse.name()) - .isEqualTo(member.getMemberInfo().getName()); + assertThat(memberDetailResponse.nickName()) + .isEqualTo(member.getMemberInfo().getNickName()); assertThat(memberDetailResponse.email()) .isEqualTo(member.getMemberInfo().getEmail()); assertThat(memberDetailResponse.imageUrl()) diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java index 3be1b5f44..6e72d1674 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java @@ -17,7 +17,7 @@ public class MemberInfoTest { @Nested class Validate { - private final String VALID_NAME = "member"; + private final String VALID_NICK_NAME = "member"; private final String VALID_EMAIL = "member@naver.com"; private final String VALID_IMAGE_URL = "https://map-befine-official.github.io/favicon.png"; private final Role VALID_ROLE = Role.ADMIN; @@ -27,7 +27,7 @@ class Validate { void success() { //given when MemberInfo memberInfo = MemberInfo.of( - VALID_NAME, + VALID_NICK_NAME, VALID_EMAIL, VALID_IMAGE_URL, VALID_ROLE @@ -35,7 +35,7 @@ void success() { //then assertThat(memberInfo).isNotNull(); - assertThat(memberInfo.getName()).isEqualTo(VALID_NAME); + assertThat(memberInfo.getNickName()).isEqualTo(VALID_NICK_NAME); assertThat(memberInfo.getEmail()).isEqualTo(VALID_EMAIL); assertThat(memberInfo.getImageUrl()).isEqualTo(VALID_IMAGE_URL); assertThat(memberInfo.getRole()).isEqualTo(VALID_ROLE); @@ -45,10 +45,10 @@ void success() { @NullSource @ValueSource(strings = {"", "aaaaaaaaaaaaaaaaaaaaa"}) @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") - void whenNameIsInvalid_thenFail(String invalidName) { + void whenNameIsInvalid_thenFail(String invalidNickName) { //given when then assertThatThrownBy(() -> MemberInfo.of( - invalidName, + invalidNickName, VALID_EMAIL, VALID_IMAGE_URL, VALID_ROLE @@ -63,7 +63,7 @@ void whenNameIsInvalid_thenFail(String invalidName) { void whenEmailIsInvalid_thenFail(String invalidEmail) { //given when then assertThatThrownBy(() -> MemberInfo.of( - VALID_NAME, + VALID_NICK_NAME, invalidEmail, VALID_IMAGE_URL, VALID_ROLE @@ -77,7 +77,7 @@ void whenImageUrlIsInvalid_thenFail() { //given when then assertThatThrownBy(() -> MemberInfo.of( - VALID_NAME, + VALID_NICK_NAME, VALID_EMAIL, invalidImageUrl, VALID_ROLE @@ -89,7 +89,7 @@ void whenImageUrlIsInvalid_thenFail() { void whenRoleIsInvalid_thenFail() { //given when then assertThatThrownBy(() -> MemberInfo.of( - VALID_NAME, + VALID_NICK_NAME, VALID_EMAIL, VALID_IMAGE_URL, null @@ -101,7 +101,7 @@ void whenRoleIsInvalid_thenFail() { @Nested class Update { - private final String name = "member1"; + private final String nickName = "member1"; private final String email = "memberr@naver.com"; private final String imageUrl = "https://map-befine-official.github.io/Matthew.png"; @@ -126,11 +126,11 @@ void setUp() { @DisplayName("정확한 값을 입력하면 객체가 수정된다") void success() { //when - memberInfo.update(name, email, imageUrl); + memberInfo.update(nickName, email, imageUrl); //then assertThat(memberInfo).isNotNull(); - assertThat(memberInfo.getName()).isEqualTo(name); + assertThat(memberInfo.getNickName()).isEqualTo(nickName); assertThat(memberInfo.getEmail()).isEqualTo(email); assertThat(memberInfo.getImageUrl()).isEqualTo(imageUrl); } @@ -154,7 +154,7 @@ void whenNameIsInvalid_thenFail(String invalidName) { void whenEmailIsInvalid_thenFail(String invalidEmail) { // given when then assertThatThrownBy( - () -> memberInfo.update(name, invalidEmail, imageUrl) + () -> memberInfo.update(nickName, invalidEmail, imageUrl) ).isInstanceOf(IllegalArgumentException.class); } @@ -165,7 +165,7 @@ void whenImageUrlIsInvalid_thenFail() { String invalidImageUrl = "image.png"; // when then assertThatThrownBy( - () -> memberInfo.update(name, email, invalidImageUrl) + () -> memberInfo.update(nickName, email, invalidImageUrl) ).isInstanceOf(IllegalArgumentException.class); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java index 2aba90279..1af18864c 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberResponseTest.java @@ -23,8 +23,8 @@ void createMemberResponse_success() { MemberResponse memberResponse = MemberResponse.from(member); // then - assertThat(memberResponse.name()) - .isEqualTo(member.getMemberInfo().getName()); + assertThat(memberResponse.nickName()) + .isEqualTo(member.getMemberInfo().getNickName()); assertThat(memberResponse.email()) .isEqualTo(member.getMemberInfo().getEmail()); } diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java index eb543453b..b23efecf4 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberTest.java @@ -11,14 +11,14 @@ class MemberTest { @DisplayName("유효한 정보를 입력했을 때 객체가 정상 생성 된다.") void createMember_success() { // given - String name = "member"; + String nickName = "member"; String email = "member@naver.com"; String imageUrl = "https://map-befine-official.github.io/favicon.png"; Role role = Role.ADMIN; // when Member member = Member.of( - name, + nickName, email, imageUrl, role @@ -26,7 +26,7 @@ void createMember_success() { // then assertThat(member).isNotNull(); - assertThat(member.getMemberInfo().getName()).isEqualTo(name); + assertThat(member.getMemberInfo().getNickName()).isEqualTo(nickName); assertThat(member.getMemberInfo().getEmail()).isEqualTo(email); assertThat(member.getMemberInfo().getImageUrl()).isEqualTo(imageUrl); assertThat(member.getMemberInfo().getRole()).isEqualTo(role); diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java index 2aecc3e6b..9fbb10bf8 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinCommandServiceTest.java @@ -89,7 +89,7 @@ void saveIfExistLocation_Success() { // when PinCreateRequest request = new PinCreateRequest( topic.getId(), - "name", + "nickName", "description", "road", "legalDongCode", @@ -104,7 +104,7 @@ void saveIfExistLocation_Success() { PinDetailResponse actual = pinQueryService.findById(authMember, savedPinId); PinDetailResponse expected = new PinDetailResponse( savedPinId, - "name", + "nickName", "road", "description", latitude, @@ -145,7 +145,7 @@ void saveIfNotExistLocation_Success() { // when PinCreateRequest request = new PinCreateRequest( topic.getId(), - "name", + "nickName", "description", "address", "legalDongCode", @@ -159,7 +159,7 @@ void saveIfNotExistLocation_Success() { PinDetailResponse actual = pinQueryService.findById(authMember, savedPinId); PinDetailResponse expected = new PinDetailResponse( savedPinId, - "name", + "nickName", "address", "description", latitude, @@ -180,7 +180,7 @@ void saveIfNotExistLocation_Success() { } @Test - @DisplayName("제약 사항(name, description)을 지킨 정보로 핀의 정보를 수정하면 핀이 수정된다.") + @DisplayName("제약 사항(nickName, description)을 지킨 정보로 핀의 정보를 수정하면 핀이 수정된다.") void update_Success() { // given double latitude = 37.123456; @@ -190,7 +190,7 @@ void update_Success() { PinCreateRequest createRequest = new PinCreateRequest( topic.getId(), - "name", + "nickName", "description", "address", "legalDongCode", @@ -227,7 +227,7 @@ void update_Success() { } @Test - @DisplayName("제약 사항(name, description)을 지키지 않은 정보로 핀의 정보를 수정하면 핀이 수정되지 않는다.") + @DisplayName("제약 사항(nickName, description)을 지키지 않은 정보로 핀의 정보를 수정하면 핀이 수정되지 않는다.") void update_Fail() { // given double latitude = 37.123456; @@ -237,7 +237,7 @@ void update_Fail() { PinCreateRequest createRequest = new PinCreateRequest( topic.getId(), - "name", + "nickName", "description", "address", "legalDongCode", @@ -264,7 +264,7 @@ void removeById_Success() { PinCreateRequest createRequest = new PinCreateRequest( topic.getId(), - "name", + "nickName", "description", "address", "legalDongCode", @@ -297,7 +297,7 @@ void removeAllByTopicId_Success() { PinCreateRequest createRequest = new PinCreateRequest( topic.getId(), - "name", + "nickName", "description", "address", "legalDongCode", diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java index 6c7974252..29b6fac49 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/application/PinQueryServiceTest.java @@ -84,11 +84,11 @@ void findAll_Success() { // given List expected = new ArrayList<>(); for (int i = 0; i < 10; i++) { - Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("nickName", "description", location, topic, member); Long savedId = pinRepository.save(pin).getId(); expected.add(new PinResponse( savedId, - "name", + "nickName", "road", "description", coordinate.getLatitude(), @@ -108,14 +108,14 @@ void findAll_Success() { @DisplayName("핀의 Id 를 넘기면 핀을 가져온다.") void findById_Success() { // given - Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("nickName", "description", location, topic, member); PinImage.createPinImageAssociatedWithPin(BASE_IMAGES.get(0), pin); Long savedId = pinRepository.save(pin).getId(); // when PinDetailResponse expected = new PinDetailResponse( savedId, - "name", + "nickName", "road", "description", coordinate.getLatitude(), diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java index 2860cfae2..6d84b43b3 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinRepositoryTest.java @@ -49,7 +49,7 @@ void deleteById_Success() { Role.ADMIN ) ); - Topic topic = TopicFixture.createByName("name", member); + Topic topic = TopicFixture.createByName("nickName", member); Address address = new Address( "parcel", "road", @@ -63,7 +63,7 @@ void deleteById_Success() { locationRepository.save(location); Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( - "name", + "nickName", "description", location, topic, @@ -89,7 +89,7 @@ void deleteAllByTopicId_Success() { "member@naver.com", Role.ADMIN) ); - Topic topic = TopicFixture.createByName("name", member); + Topic topic = TopicFixture.createByName("nickName", member); Address address = new Address( "parcel", "road", @@ -102,7 +102,7 @@ void deleteAllByTopicId_Success() { for (int i = 0; i < 10; i++) { Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( - "name", + "nickName", "description", location, topic, diff --git a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java index f91dec741..07c412999 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/pin/domain/PinTest.java @@ -83,7 +83,7 @@ void createPinAssociatedWithLocationAndTopic_Fail(String name, String descriptio @DisplayName("정상적인 정보를 통해 Update 를 진행하면 Pin 의 정보가 정상적으로 수정된다.") void update_Success(String name, String description) { // given - Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("name", "description", location, topic, member); + Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember("nickName", "description", location, topic, member); // when pin.updatePinInfo(name, description); @@ -111,7 +111,7 @@ static Stream validNameAndDescription() { void update_Fail(String name, String description) { // given Pin pin = Pin.createPinAssociatedWithLocationAndTopicAndMember( - "name", + "nickName", "description", location, topic, diff --git a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java index d0daef31c..7cf34b899 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/topic/domain/TopicInfoTest.java @@ -41,7 +41,7 @@ void success() { @ParameterizedTest @NullSource - @ValueSource(strings = {"", "This name is definitely more than twenty characters long"}) + @ValueSource(strings = {"", "This nickName is definitely more than twenty characters long"}) @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") void whenNameIsInvalid_thenFail(String input) { //given @@ -161,7 +161,7 @@ void success() { @ParameterizedTest @NullSource - @ValueSource(strings = {"", "This name is definitely more than twenty characters long"}) + @ValueSource(strings = {"", "This nickName is definitely more than twenty characters long"}) @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") void whenNameIsInvalid_thenFail(String input) { //when From 67ba9d9b9f2387c6c1a77f4f97afe218c5d35cc7 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 09:46:25 +0900 Subject: [PATCH 84/88] =?UTF-8?q?style=20:=20=EA=B0=9C=ED=96=89=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 --- .../application/MemberCommandService.java | 8 +++++++- .../application/MemberQueryService.java | 1 - .../mapbefine/member/domain/Member.java | 19 ++++++++++++++++--- .../mapbefine/member/domain/MemberInfo.java | 6 +++++- .../member/domain/MemberTopicPermission.java | 1 + .../member/presentation/MemberController.java | 8 ++++++-- 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index b22dba6c8..1936e35fb 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -67,10 +67,16 @@ public Long saveMemberTopicPermission( Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); - validateSaveMemberTopicPermission(authMember, request, member, topic); + validateSaveMemberTopicPermission( + authMember, + request, + member, + topic + ); MemberTopicPermission memberTopicPermission = MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); + return memberTopicPermissionRepository.save(memberTopicPermission).getId(); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index a19c2a01d..f1397e62a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -29,7 +29,6 @@ public class MemberQueryService { private final PinRepository pinRepository; private final MemberTopicPermissionRepository memberTopicPermissionRepository; - public MemberQueryService( MemberRepository memberRepository, TopicRepository topicRepository, diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index b734a0a00..721d4d796 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -49,12 +49,25 @@ public static Member of( String imageUrl, Role role ) { - MemberInfo memberInfo = MemberInfo.of(name, email, imageUrl, role); + MemberInfo memberInfo = MemberInfo.of( + name, + email, + imageUrl, + role + ); return new Member(memberInfo); } - public void update(String name, String email, String imageUrl) { - memberInfo.update(name, email, imageUrl); + public void update( + String name, + String email, + String imageUrl + ) { + memberInfo.update( + name, + email, + imageUrl + ); } public void addTopic(Topic topic) { diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index f876e0984..360d7ae99 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -62,7 +62,11 @@ public static MemberInfo of( ); } - public void update(String nickName, String email, String imageUrl) { + public void update( + String nickName, + String email, + String imageUrl + ) { validateNickName(nickName); validateEmail(email); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java index 865594823..2cd41de02 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermission.java @@ -42,6 +42,7 @@ public static MemberTopicPermission createPermissionAssociatedWithTopicAndMember MemberTopicPermission memberTopicPermission = new MemberTopicPermission(topic, member); topic.addMemberTopicPermission(memberTopicPermission); member.addMemberTopicPermission(memberTopicPermission); + return memberTopicPermission; } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java index c2300157f..5cb391ce0 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/presentation/MemberController.java @@ -90,7 +90,9 @@ public ResponseEntity> findPinsByMember(AuthMember authMember) @LoginRequired @GetMapping("/permissions/topics/{topicId}") - public ResponseEntity> findMemberTopicPermissionAll(@PathVariable Long topicId) { + public ResponseEntity> findMemberTopicPermissionAll( + @PathVariable Long topicId + ) { List responses = memberQueryService.findAllWithPermission(topicId); return ResponseEntity.ok(responses); @@ -98,7 +100,9 @@ public ResponseEntity> findMemberTopicPermis @LoginRequired @GetMapping("/permissions/{permissionId}") - public ResponseEntity findMemberTopicPermissionById(@PathVariable Long permissionId) { + public ResponseEntity findMemberTopicPermissionById( + @PathVariable Long permissionId + ) { MemberTopicPermissionDetailResponse response = memberQueryService.findMemberTopicPermissionById(permissionId); return ResponseEntity.ok(response); From 6ba447fe066155b8251d44555873aeafed132af3 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 10:07:15 +0900 Subject: [PATCH 85/88] =?UTF-8?q?refactor=20:=20Objects.isNull=20=EC=9D=84?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20null=20=EC=9D=84=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC=20=EB=B0=8F=20Repository=20=EB=A7=A4=EA=B0=9C?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberCommandService.java | 6 ++--- .../application/MemberQueryService.java | 23 ++++++++----------- .../mapbefine/member/domain/MemberInfo.java | 7 +++--- .../MemberTopicPermissionRepository.java | 4 ++-- .../mapbefine/pin/domain/PinRepository.java | 3 +-- .../mapbefine/topic/domain/TopicInfo.java | 2 +- .../topic/domain/TopicRepository.java | 3 --- 7 files changed, 21 insertions(+), 27 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index 1936e35fb..f895bb284 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -88,7 +88,7 @@ private void validateSaveMemberTopicPermission( ) { validateMemberCanTopicUpdate(authMember, topic); validateSelfPermission(authMember, request); - validateDuplicatePermission(member, topic); + validateDuplicatePermission(topic.getId(), member.getId()); } private void validateMemberCanTopicUpdate(AuthMember authMember, Topic topic) { @@ -106,8 +106,8 @@ private void validateSelfPermission( } } - private void validateDuplicatePermission(Member member, Topic topic) { - if (memberTopicPermissionRepository.existsByTopicAndMember(topic, member)) { + private void validateDuplicatePermission(Long topicId, Long memberId) { + if (memberTopicPermissionRepository.existsByTopicIdAndMemberId(topicId, memberId)) { throw new IllegalArgumentException("권한은 중복으로 줄 수 없습니다."); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index f1397e62a..78f5ecd0d 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -17,6 +17,7 @@ import com.mapbefine.mapbefine.topic.dto.response.TopicResponse; import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -56,10 +57,8 @@ public List findAll() { } public List findTopicsByMember(AuthMember authMember) { - validateNull(authMember.getMemberId()); - Member member = memberRepository.findById(authMember.getMemberId()) - .orElseThrow(NoSuchElementException::new); - List topicsByCreator = topicRepository.findByCreator(member); + validateNonExistsMember(authMember.getMemberId()); + List topicsByCreator = topicRepository.findByCreatorId(authMember.getMemberId()); return topicsByCreator.stream() .map(TopicResponse::from) @@ -67,19 +66,17 @@ public List findTopicsByMember(AuthMember authMember) { } public List findPinsByMember(AuthMember authMember) { - validateNull(authMember.getMemberId()); - Member creator = memberRepository.findById(authMember.getMemberId()) - .orElseThrow(NoSuchElementException::new); - List pinsByCreator = pinRepository.findByCreator(creator); + validateNonExistsMember(authMember.getMemberId()); + List pinsByCreator = pinRepository.findByCreatorId(authMember.getMemberId()); return pinsByCreator.stream() .map(PinResponse::from) .toList(); } - - private void validateNull(Long id) { - if (id == null) { - throw new IllegalArgumentException("id 는 null 일 수 없습니다."); + + public void validateNonExistsMember(Long memberId) { + if (Objects.isNull(memberId)) { + throw new IllegalArgumentException("존재하지 않는 유저입니다."); } } @@ -87,7 +84,7 @@ public List findAllWithPermission(Long topicId) { Topic topic = topicRepository.findById(topicId) .orElseThrow(NoSuchElementException::new); - return memberTopicPermissionRepository.findByTopic(topic) + return memberTopicPermissionRepository.findAllByTopic(topic) .stream() .map(MemberTopicPermissionResponse::from) .toList(); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index 360d7ae99..8b82fda4a 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -8,6 +8,7 @@ import jakarta.persistence.Embeddable; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import java.util.Objects; import lombok.Getter; import lombok.NoArgsConstructor; @@ -76,7 +77,7 @@ public void update( } private static void validateNickName(String nickName) { - if (nickName == null) { + if (Objects.isNull(nickName)) { throw new IllegalArgumentException("닉네임은 필수로 입력해야합니다."); } if (nickName.isBlank() || nickName.length() > MAX_NICK_NAME_LENGTH) { @@ -85,7 +86,7 @@ private static void validateNickName(String nickName) { } private static void validateEmail(String email) { - if (email == null) { + if (Objects.isNull(email)) { throw new IllegalArgumentException("이메일은 필수로 입력해야합니다."); } @@ -95,7 +96,7 @@ private static void validateEmail(String email) { } private static void validateRole(Role role) { - if (role == null) { + if (Objects.isNull(role)) { throw new IllegalArgumentException("역할은 필수로 입력해야합니다."); } } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java index eefca6b8e..0ab5dde24 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberTopicPermissionRepository.java @@ -6,8 +6,8 @@ public interface MemberTopicPermissionRepository extends JpaRepository { - List findByTopic(Topic topic); + List findAllByTopic(Topic topic); - boolean existsByTopicAndMember(Topic topic, Member member); + boolean existsByTopicIdAndMemberId(Long topicId, Long memberId); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java index 56c5aeb69..38bbe5057 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/pin/domain/PinRepository.java @@ -1,6 +1,5 @@ package com.mapbefine.mapbefine.pin.domain; -import com.mapbefine.mapbefine.member.domain.Member; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -21,6 +20,6 @@ public interface PinRepository extends JpaRepository { List findAllByTopicId(Long topicId); - List findByCreator(Member creator); + List findByCreatorId(Long creatorId); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java index 8850766c6..0e4e26c5b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicInfo.java @@ -56,7 +56,7 @@ public static TopicInfo of( private static void validateName(String name) { if (name == null) { - throw new IllegalArgumentException("nickName null"); + throw new IllegalArgumentException("Name null"); } if (name.isBlank() || name.length() > MAX_NAME_LENGTH) { throw new IllegalArgumentException("이름 길이 이상"); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java index 91b7e818c..10f9d0cd1 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/topic/domain/TopicRepository.java @@ -1,6 +1,5 @@ package com.mapbefine.mapbefine.topic.domain; -import com.mapbefine.mapbefine.member.domain.Member; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; @@ -17,8 +16,6 @@ public interface TopicRepository extends JpaRepository { @Query("update Topic t set t.isDeleted = true where t.id = :topicId") void deleteById(@Param("topicId") Long topicId); - List findByCreator(Member creator); - List findByCreatorId(Long creatorId); } From f97ac2dfbe9b4d3f686983a7f30e73dfbaa5dad1 Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 10:13:01 +0900 Subject: [PATCH 86/88] =?UTF-8?q?refactor=20:=20=EB=B6=80=EC=A0=95=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapbefine/member/application/MemberCommandService.java | 6 ++++-- .../java/com/mapbefine/mapbefine/member/domain/Member.java | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index f895bb284..b5e43f55b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -92,9 +92,11 @@ private void validateSaveMemberTopicPermission( } private void validateMemberCanTopicUpdate(AuthMember authMember, Topic topic) { - if (!authMember.canTopicUpdate(topic)) { - throw new IllegalArgumentException("해당 유저는 해당 토픽에서 다른 유저에게 권한을 줄 수 없습니다."); + if (authMember.canTopicUpdate(topic)) { + return; } + + throw new IllegalArgumentException("해당 유저는 해당 토픽에서 다른 유저에게 권한을 줄 수 없습니다."); } private void validateSelfPermission( diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 721d4d796..1d1d64881 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -55,6 +55,7 @@ public static Member of( imageUrl, role ); + return new Member(memberInfo); } From 9a0b57f47060fd40a98cfc42effb89856089a66e Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 13:36:49 +0900 Subject: [PATCH 87/88] =?UTF-8?q?refactor=20:=20MemberInfo=20Update=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 --- .../application/MemberCommandService.java | 7 +- .../mapbefine/member/domain/Member.java | 13 ++-- .../mapbefine/member/domain/MemberInfo.java | 15 +--- .../dto/request/MemberCreateRequest.java | 2 +- .../member/domain/MemberInfoTest.java | 74 ------------------- 5 files changed, 13 insertions(+), 98 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index b5e43f55b..0694ccbe4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -2,6 +2,7 @@ import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.member.domain.Member; +import com.mapbefine.mapbefine.member.domain.MemberInfo; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; @@ -32,11 +33,11 @@ public MemberCommandService( } public Long save(MemberCreateRequest request) { - validateUniqueName(request.name()); + validateUniqueNickName(request.nickName()); validateUniqueEmail(request.email()); Member member = Member.of( - request.name(), + request.nickName(), request.email(), request.imageUrl(), request.role() @@ -46,7 +47,7 @@ public Long save(MemberCreateRequest request) { .getId(); } - private void validateUniqueName(String name) { + private void validateUniqueNickName(String name) { if (memberRepository.existsByMemberInfoNickName(name)) { throw new IllegalArgumentException("이미 존재하는 이름입니다."); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 1d1d64881..3b60bc503 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -44,13 +44,13 @@ private Member( } public static Member of( - String name, + String nickName, String email, String imageUrl, Role role ) { MemberInfo memberInfo = MemberInfo.of( - name, + nickName, email, imageUrl, role @@ -60,14 +60,15 @@ public static Member of( } public void update( - String name, + String nickName, String email, String imageUrl ) { - memberInfo.update( - name, + memberInfo = MemberInfo.of( + nickName, email, - imageUrl + imageUrl, + memberInfo.getRole() ); } diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java index 8b82fda4a..f05151c1b 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/MemberInfo.java @@ -18,7 +18,7 @@ public class MemberInfo { private static final int MAX_NICK_NAME_LENGTH = 20; - private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; + private static final String VALID_EMAIL_URL_REGEX = "^[a-zA-Z0-9]+@[a-zA-Z]+\\.[a-zA-Z]{2,}$"; @Column(nullable = false, length = 20, unique = true) private String nickName; @@ -63,19 +63,6 @@ public static MemberInfo of( ); } - public void update( - String nickName, - String email, - String imageUrl - ) { - validateNickName(nickName); - validateEmail(email); - - this.nickName = nickName; - this.email = email; - this.imageUrl = Image.of(imageUrl); - } - private static void validateNickName(String nickName) { if (Objects.isNull(nickName)) { throw new IllegalArgumentException("닉네임은 필수로 입력해야합니다."); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java index 4e62aaee5..b97787ce4 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/dto/request/MemberCreateRequest.java @@ -3,7 +3,7 @@ import com.mapbefine.mapbefine.member.domain.Role; public record MemberCreateRequest( - String name, + String nickName, String email, String imageUrl, Role role diff --git a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java index 6e72d1674..ffe38488f 100644 --- a/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java +++ b/backend/src/test/java/com/mapbefine/mapbefine/member/domain/MemberInfoTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -98,77 +97,4 @@ void whenRoleIsInvalid_thenFail() { } - @Nested - class Update { - - private final String nickName = "member1"; - private final String email = "memberr@naver.com"; - private final String imageUrl = "https://map-befine-official.github.io/Matthew.png"; - - private final String VALID_NAME = "member"; - private final String VALID_EMAIL = "member@naver.com"; - private final String VALID_IMAGE_URL = "https://map-befine-official.github.io/favicon.png"; - private final Role VALID_ROLE = Role.ADMIN; - - private MemberInfo memberInfo; - - @BeforeEach - void setUp() { - memberInfo = MemberInfo.of( - VALID_NAME, - VALID_EMAIL, - VALID_IMAGE_URL, - VALID_ROLE - ); - } - - @Test - @DisplayName("정확한 값을 입력하면 객체가 수정된다") - void success() { - //when - memberInfo.update(nickName, email, imageUrl); - - //then - assertThat(memberInfo).isNotNull(); - assertThat(memberInfo.getNickName()).isEqualTo(nickName); - assertThat(memberInfo.getEmail()).isEqualTo(email); - assertThat(memberInfo.getImageUrl()).isEqualTo(imageUrl); - } - - - @ParameterizedTest - @NullSource - @ValueSource(strings = {"", "aaaaaaaaaaaaaaaaaaaaa"}) - @DisplayName("유효한 이름이 아닌 경우 예외가 발생한다") - void whenNameIsInvalid_thenFail(String invalidName) { - // given when then - assertThatThrownBy( - () -> memberInfo.update(invalidName, email, imageUrl) - ).isInstanceOf(IllegalArgumentException.class); - } - - @ParameterizedTest - @NullSource - @EmptySource - @DisplayName("유효한 email 아닌 경우 예외가 발생한다") - void whenEmailIsInvalid_thenFail(String invalidEmail) { - // given when then - assertThatThrownBy( - () -> memberInfo.update(nickName, invalidEmail, imageUrl) - ).isInstanceOf(IllegalArgumentException.class); - } - - @Test - @DisplayName("유효한 Image Url 이 아닌 경우 예외가 발생한다.") - void whenImageUrlIsInvalid_thenFail() { - // given - String invalidImageUrl = "image.png"; - // when then - assertThatThrownBy( - () -> memberInfo.update(nickName, email, invalidImageUrl) - ).isInstanceOf(IllegalArgumentException.class); - } - - } - } From 4da72dcd46e8a763c8f0a4734a8651d3dbcee0ab Mon Sep 17 00:00:00 2001 From: jaeyeon kim Date: Wed, 9 Aug 2023 14:16:24 +0900 Subject: [PATCH 88/88] =?UTF-8?q?style=20:=20=EA=B0=9C=ED=96=89=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberCommandService.java | 24 +++++-------------- .../application/MemberQueryService.java | 2 +- .../mapbefine/member/domain/Member.java | 4 +--- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java index 0694ccbe4..6aed8af7f 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberCommandService.java @@ -2,7 +2,6 @@ import com.mapbefine.mapbefine.auth.domain.AuthMember; import com.mapbefine.mapbefine.member.domain.Member; -import com.mapbefine.mapbefine.member.domain.MemberInfo; import com.mapbefine.mapbefine.member.domain.MemberRepository; import com.mapbefine.mapbefine.member.domain.MemberTopicPermission; import com.mapbefine.mapbefine.member.domain.MemberTopicPermissionRepository; @@ -47,9 +46,9 @@ public Long save(MemberCreateRequest request) { .getId(); } - private void validateUniqueNickName(String name) { - if (memberRepository.existsByMemberInfoNickName(name)) { - throw new IllegalArgumentException("이미 존재하는 이름입니다."); + private void validateUniqueNickName(String nickName) { + if (memberRepository.existsByMemberInfoNickName(nickName)) { + throw new IllegalArgumentException("이미 존재하는 닉네임입니다."); } } @@ -59,21 +58,13 @@ private void validateUniqueEmail(String email) { } } - public Long saveMemberTopicPermission( - AuthMember authMember, - MemberTopicPermissionCreateRequest request - ) { + public Long saveMemberTopicPermission(AuthMember authMember, MemberTopicPermissionCreateRequest request) { Member member = memberRepository.findById(request.memberId()) .orElseThrow(NoSuchElementException::new); Topic topic = topicRepository.findById(request.topicId()) .orElseThrow(NoSuchElementException::new); - validateSaveMemberTopicPermission( - authMember, - request, - member, - topic - ); + validateSaveMemberTopicPermission(authMember, request, member, topic); MemberTopicPermission memberTopicPermission = MemberTopicPermission.createPermissionAssociatedWithTopicAndMember(topic, member); @@ -115,10 +106,7 @@ private void validateDuplicatePermission(Long topicId, Long memberId) { } } - public void deleteMemberTopicPermission( - AuthMember authMember, - Long permissionId - ) { + public void deleteMemberTopicPermission(AuthMember authMember, Long permissionId) { MemberTopicPermission memberTopicPermission = memberTopicPermissionRepository.findById(permissionId) .orElseThrow(NoSuchElementException::new); diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java index 78f5ecd0d..fc6515b67 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/application/MemberQueryService.java @@ -9,8 +9,8 @@ import com.mapbefine.mapbefine.member.dto.response.MemberResponse; import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionDetailResponse; import com.mapbefine.mapbefine.member.dto.response.MemberTopicPermissionResponse; -import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.domain.Pin; +import com.mapbefine.mapbefine.pin.domain.PinRepository; import com.mapbefine.mapbefine.pin.dto.response.PinResponse; import com.mapbefine.mapbefine.topic.domain.Topic; import com.mapbefine.mapbefine.topic.domain.TopicRepository; diff --git a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java index 3b60bc503..280e47ea1 100644 --- a/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java +++ b/backend/src/main/java/com/mapbefine/mapbefine/member/domain/Member.java @@ -37,9 +37,7 @@ public class Member extends BaseTimeEntity { @OneToMany(mappedBy = "member") private List topicsWithPermissions = new ArrayList<>(); - private Member( - MemberInfo memberInfo - ) { + private Member(MemberInfo memberInfo) { this.memberInfo = memberInfo; }